This removes all non-Camera stuff from Camera2.

Note: Camera2 is a clone of Gallery2 right now.
Note 2: I will bring .mk files back later.

Change-Id: Ida958654296f5ebaacb6bb0ff59d52a7c37ce6fc
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index ef1d914..57209ee 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -1,16 +1,11 @@
-<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.android.camera2"
+    android:versionCode="1"
+    android:versionName="2.0" >
 
-<manifest android:versionCode="40030"
-        android:versionName="1.1.40030"
-        xmlns:android="http://schemas.android.com/apk/res/android"
-        package="com.android.gallery3d">
-
-    <original-package android:name="com.android.gallery3d" />
-
-    <uses-sdk android:minSdkVersion="14" android:targetSdkVersion="17" />
-
-    <permission android:name="com.android.gallery3d.permission.GALLERY_PROVIDER"
-            android:protectionLevel="signatureOrSystem" />
+    <uses-sdk
+        android:minSdkVersion="14"
+        android:targetSdkVersion="17" />
 
     <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
     <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
@@ -30,380 +25,80 @@
     <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" />
-    <uses-permission android:name="com.android.gallery3d.permission.GALLERY_PROVIDER" />
 
-    <supports-screens android:smallScreens="false"
-            android:normalScreens="true" android:largeScreens="true"
-            android:anyDensity="true" />
+    <supports-screens
+        android:anyDensity="true"
+        android:largeScreens="true"
+        android:normalScreens="true"
+        android:smallScreens="false" />
 
-    <application android:icon="@mipmap/ic_launcher_gallery" android:label="@string/app_name"
-            android:name="com.android.gallery3d.app.GalleryAppImpl"
-            android:theme="@style/Theme.Gallery"
-            android:logo="@mipmap/ic_launcher_gallery"
-            android:hardwareAccelerated="true"
-            android:largeHeap="true"
-            android:backupAgent="com.android.camera.CameraBackupAgent"
-            android:restoreAnyVersion="true">
-        <uses-library android:name="com.google.android.media.effects" android:required="false" />
-        <meta-data android:name="com.google.android.backup.api_key"
-                android:value="AEdPqrEAAAAIRIXquXawbz6duuuCIUAZ_YJv1zbFMMcjZ0NoVw" />
-        <activity android:name="com.android.gallery3d.app.MovieActivity"
-                android:label="@string/movie_view_label"
-                android:configChanges="orientation|keyboardHidden|screenSize">
-            <intent-filter>
-                <action android:name="android.intent.action.VIEW" />
-                <category android:name="android.intent.category.DEFAULT" />
-                <category android:name="android.intent.category.BROWSABLE" />
-                <data android:scheme="rtsp" />
-             </intent-filter>
-             <intent-filter>
-                <action android:name="android.intent.action.VIEW" />
-                <category android:name="android.intent.category.DEFAULT" />
-                <category android:name="android.intent.category.BROWSABLE" />
-                <data android:scheme="http" />
-                <data android:scheme="https" />
-                <data android:scheme="content" />
-                <data android:scheme="file" />
-                <data android:mimeType="video/mpeg4" />
-                <data android:mimeType="video/mp4" />
-                <data android:mimeType="video/3gp" />
-                <data android:mimeType="video/3gpp" />
-                <data android:mimeType="video/3gpp2" />
-                <data android:mimeType="video/webm" />
-                <data android:mimeType="video/avi" />
-                <data android:mimeType="application/sdp" />
-             </intent-filter>
-             <intent-filter>
-                <!-- HTTP live support -->
-                <action android:name="android.intent.action.VIEW" />
-                <category android:name="android.intent.category.DEFAULT" />
-                <category android:name="android.intent.category.BROWSABLE" />
-                <data android:scheme="http" />
-                <data android:scheme="https" />
-                <data android:mimeType="audio/x-mpegurl" />
-                <data android:mimeType="audio/mpegurl" />
-                <data android:mimeType="application/vnd.apple.mpegurl" />
-                <data android:mimeType="application/x-mpegurl" />
-             </intent-filter>
-        </activity>
-
-        <activity android:name="com.android.gallery3d.app.Gallery" android:label="@string/app_name"
-                android:configChanges="keyboardHidden|orientation|screenSize">
-            <intent-filter>
-                <action android:name="android.intent.action.MAIN" />
-                <category android:name="android.intent.category.DEFAULT" />
-                <category android:name="android.intent.category.LAUNCHER" />
-                <category android:name="android.intent.category.APP_GALLERY" />
-            </intent-filter>
-            <intent-filter>
-                <action android:name="android.intent.action.GET_CONTENT" />
-                <category android:name="android.intent.category.OPENABLE" />
-                <data android:mimeType="vnd.android.cursor.dir/image" />
-            </intent-filter>
-            <intent-filter>
-                <action android:name="android.intent.action.GET_CONTENT" />
-                <category android:name="android.intent.category.OPENABLE" />
-                <category android:name="android.intent.category.DEFAULT" />
-                <data android:mimeType="image/*" />
-                <data android:mimeType="video/*" />
-            </intent-filter>
-            <!-- We do NOT support the PICK intent, we add these intent-filter for
-                 backward compatibility. Handle it as GET_CONTENT. -->
-            <intent-filter>
-                <action android:name="android.intent.action.PICK" />
-                <category android:name="android.intent.category.DEFAULT" />
-                <data android:mimeType="image/*" />
-                <data android:mimeType="video/*" />
-            </intent-filter>
-            <intent-filter>
-                <action android:name="android.intent.action.PICK" />
-                <category android:name="android.intent.category.DEFAULT" />
-                <data android:mimeType="vnd.android.cursor.dir/image" />
-                <data android:mimeType="vnd.android.cursor.dir/video" />
-            </intent-filter>
-            <intent-filter>
-                <action android:name="android.intent.action.VIEW" />
-                <category android:name="android.intent.category.DEFAULT" />
-                <data android:mimeType="vnd.android.cursor.dir/image" />
-                <data android:mimeType="vnd.android.cursor.dir/video" />
-            </intent-filter>
-            <intent-filter>
-                <action android:name="android.intent.action.VIEW" />
-                <action android:name="com.android.camera.action.REVIEW" />
-                <category android:name="android.intent.category.DEFAULT" />
-                <category android:name="android.intent.category.BROWSABLE" />
-                <data android:scheme="" />
-                <data android:scheme="http" />
-                <data android:scheme="https" />
-                <data android:scheme="content" />
-                <data android:scheme="file" />
-                <data android:mimeType="image/bmp" />
-                <data android:mimeType="image/jpeg" />
-                <data android:mimeType="image/gif" />
-                <data android:mimeType="image/png" />
-                <data android:mimeType="image/webp" />
-                <data android:mimeType="image/x-ms-bmp" />
-                <data android:mimeType="image/vnd.wap.wbmp" />
-                <data android:mimeType="application/vnd.google.panorama360+jpg" />
-            </intent-filter>
-            <intent-filter>
-                <action android:name="com.android.camera.action.REVIEW" />
-                <category android:name="android.intent.category.DEFAULT" />
-                <category android:name="android.intent.category.BROWSABLE" />
-                <data android:scheme="http" />
-                <data android:scheme="https" />
-                <data android:scheme="content" />
-                <data android:scheme="file" />
-                <data android:mimeType="video/mpeg4" />
-                <data android:mimeType="video/mp4" />
-                <data android:mimeType="video/3gp" />
-                <data android:mimeType="video/3gpp" />
-                <data android:mimeType="video/3gpp2" />
-                <data android:mimeType="application/sdp" />
-            </intent-filter>
-        </activity>
-
-        <!-- we add this activity-alias for shortcut backward compatibility -->
-        <!-- Note: The alias must put after the target activity -->
-        <activity-alias android:name="com.cooliris.media.Gallery"
-                android:targetActivity="com.android.gallery3d.app.Gallery"
-                android:configChanges="keyboardHidden|orientation|screenSize"
-                android:label="@string/app_name">
-            <intent-filter>
-                <action android:name="android.intent.action.MAIN" />
-            </intent-filter>
-        </activity-alias>
-
-         <!-- This activity receives USB_DEVICE_ATTACHED intents and allows importing
-         media from attached MTP devices, like cameras and camera phones -->
-        <activity android:launchMode="singleInstance"
-            android:taskAffinity="" android:name="com.android.gallery3d.ingest.IngestActivity"
-            android:configChanges="orientation|screenSize"
-            android:label="@string/app_name">
-            <intent-filter>
-                <action android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED" />
-            </intent-filter>
-            <meta-data android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED"
-                android:resource="@xml/device_filter" />
-        </activity>
-        <service android:name="com.android.gallery3d.ingest.IngestService" />
-
-        <activity android:name="com.android.gallery3d.app.Wallpaper"
-                android:configChanges="keyboardHidden|orientation|screenSize"
-                android:theme="@style/android:Theme.Translucent.NoTitleBar">
-            <intent-filter android:label="@string/camera_setas_wallpaper">
-                <action android:name="android.intent.action.ATTACH_DATA" />
-                <data android:mimeType="image/*" />
-                <category android:name="android.intent.category.DEFAULT" />
-            </intent-filter>
-            <intent-filter android:label="@string/app_name">
-                <action android:name="android.intent.action.SET_WALLPAPER" />
-                <category android:name="android.intent.category.DEFAULT" />
-            </intent-filter>
-            <meta-data android:name="android.wallpaper.preview"
-                    android:resource="@xml/wallpaper_picker_preview" />
-        </activity>
-        <activity android:name="com.android.gallery3d.app.TrimVideo"
-                android:label="@string/trim_label">
-        </activity>
-
-        <permission android:name="com.android.gallery3d.filtershow.permission.READ"
-                    android:protectionLevel="signature" />
-
-        <permission android:name="com.android.gallery3d.filtershow.permission.WRITE"
-                    android:protectionLevel="signature" />
-
-        <provider
-            android:name="com.android.gallery3d.filtershow.provider.SharedImageProvider"
-            android:authorities="com.android.gallery3d.filtershow.provider.SharedImageProvider"
-            android:grantUriPermissions="true"
-            android:readPermission="com.android.gallery3d.filtershow.permission.READ"
-            android:writePermission="com.android.gallery3d.filtershow.permission.WRITE" />
-
-        <service
-                android:name=".filtershow.pipeline.ProcessingService"
-                android:exported="false" />
-
+    <application
+        android:name="com.android.camera.app.CameraApp"
+        android:backupAgent="com.android.camera.CameraBackupAgent"
+        android:hardwareAccelerated="true"
+        android:icon="@mipmap/ic_launcher_camera"
+        android:label="@string/app_name"
+        android:largeHeap="true"
+        android:logo="@mipmap/ic_launcher_camera"
+        android:restoreAnyVersion="true"
+        android:theme="@style/Theme.Camera" >
         <activity
-            android:name="com.android.gallery3d.filtershow.FilterShowActivity"
-            android:label="@string/title_activity_filter_show"
-            android:theme="@style/Theme.FilterShow"
-            android:configChanges="keyboardHidden|orientation|screenSize">
-            <intent-filter>
-                <action android:name="android.intent.action.EDIT" />
-                <category android:name="android.intent.category.DEFAULT" />
-                <data android:mimeType="image/*" />
-            </intent-filter>
-            <intent-filter>
-                <action android:name="action_nextgen_edit" />
-                <category android:name="android.intent.category.DEFAULT" />
-                <data android:mimeType="image/*" />
-            </intent-filter>
-        </activity>
-
-        <activity
-            android:name="com.android.gallery3d.filtershow.crop.CropActivity"
-            android:label="@string/crop"
-            android:theme="@style/Theme.FilterShow"
-            android:configChanges="keyboardHidden|orientation|screenSize">
-           <intent-filter android:label="@string/crop_label">
-                <action android:name="com.android.camera.action.CROP" />
-                <data android:scheme="http" />
-                <data android:scheme="https" />
-                <data android:scheme="content" />
-                <data android:scheme="file" />
-                <data android:scheme="" />
-                <data android:mimeType="image/*" />
-                <category android:name="android.intent.category.DEFAULT" />
-                <category android:name="android.intent.category.ALTERNATIVE" />
-                <category android:name="android.intent.category.SELECTED_ALTERNATIVE" />
-            </intent-filter>
-        </activity>
-
-        <uses-library android:name="com.google.android.media.effects"
-                android:required="false" />
-
-        <activity android:name="com.android.gallery3d.settings.GallerySettings"
-                android:theme="@style/Theme.Gallery"
-                android:configChanges="orientation|keyboardHidden|screenSize" />
-
-        <provider android:name="com.android.gallery3d.provider.GalleryProvider"
-                android:syncable="false"
-                android:grantUriPermissions="true"
-                android:exported="true"
-                android:permission="com.android.gallery3d.permission.GALLERY_PROVIDER"
-                android:authorities="com.android.gallery3d.provider" />
-        <provider
-                android:name="com.android.photos.data.PhotoProvider"
-                android:authorities="com.android.gallery3d.photoprovider"
-                android:syncable="false"
-                android:exported="false"/>
-        <activity android:name="com.android.gallery3d.gadget.WidgetClickHandler" />
-        <activity android:name="com.android.gallery3d.app.DialogPicker"
-                android:configChanges="keyboardHidden|orientation|screenSize"
-                android:theme="@style/DialogPickerTheme"/>
-        <activity android:name="com.android.gallery3d.app.AlbumPicker"
-                android:configChanges="keyboardHidden|orientation|screenSize"
-                android:theme="@style/DialogPickerTheme"/>
-        <activity android:name="com.android.gallery3d.gadget.WidgetTypeChooser"
-                android:configChanges="keyboardHidden|orientation|screenSize"
-                android:theme="@style/Theme.Gallery.Dialog"/>
-        <activity android:name="com.android.camera.CameraActivity"
-                android:taskAffinity="com.android.camera.CameraActivity"
-                android:label="@string/camera_label"
-                android:theme="@style/Theme.Camera"
-                android:icon="@mipmap/ic_launcher_camera"
-                android:configChanges="orientation|screenSize|keyboardHidden"
-                android:clearTaskOnLaunch="true"
-                android:windowSoftInputMode="stateAlwaysHidden|adjustPan">
+            android:name="com.android.camera.CameraActivity"
+            android:clearTaskOnLaunch="true"
+            android:configChanges="orientation|screenSize|keyboardHidden"
+            android:icon="@mipmap/ic_launcher_camera"
+            android:label="@string/camera_2"
+            android:taskAffinity="com.android.camera.CameraActivity"
+            android:theme="@style/Theme.Camera"
+            android:windowSoftInputMode="stateAlwaysHidden|adjustPan" >
             <intent-filter>
                 <action android:name="android.media.action.IMAGE_CAPTURE" />
+
                 <category android:name="android.intent.category.DEFAULT" />
             </intent-filter>
             <intent-filter>
                 <action android:name="android.media.action.STILL_IMAGE_CAMERA" />
+
                 <category android:name="android.intent.category.DEFAULT" />
             </intent-filter>
-            <meta-data android:name="com.android.keyguard.layout"
-                    android:resource="@layout/keyguard_widget" />
-        </activity>
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
 
-        <activity android:name="com.android.camera.SecureCameraActivity"
-                android:taskAffinity="com.android.camera.SecureCameraActivity"
-                android:excludeFromRecents="true"
-                android:label="@string/camera_label"
-                android:theme="@style/Theme.Camera"
-                android:icon="@mipmap/ic_launcher_camera"
-                android:configChanges="orientation|screenSize|keyboardHidden"
-                android:clearTaskOnLaunch="true"
-                android:windowSoftInputMode="stateAlwaysHidden|adjustPan">
+                <category android:name="android.intent.category.DEFAULT" />
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+
+            <meta-data
+                android:name="com.android.keyguard.layout"
+                android:resource="@layout/keyguard_widget" />
+        </activity>
+        <activity
+            android:name="com.android.camera.SecureCameraActivity"
+            android:clearTaskOnLaunch="true"
+            android:configChanges="orientation|screenSize|keyboardHidden"
+            android:excludeFromRecents="true"
+            android:icon="@mipmap/ic_launcher_camera"
+            android:label="@string/camera_2"
+            android:taskAffinity="com.android.camera.SecureCameraActivity"
+            android:theme="@style/Theme.Camera"
+            android:windowSoftInputMode="stateAlwaysHidden|adjustPan" >
             <intent-filter>
                 <action android:name="android.media.action.STILL_IMAGE_CAMERA_SECURE" />
+
                 <category android:name="android.intent.category.DEFAULT" />
             </intent-filter>
             <intent-filter>
                 <action android:name="android.media.action.IMAGE_CAPTURE_SECURE" />
+
                 <category android:name="android.intent.category.DEFAULT" />
             </intent-filter>
-            <meta-data android:name="com.android.keyguard.layout"
-                    android:resource="@layout/keyguard_widget" />
+
+            <meta-data
+                android:name="com.android.keyguard.layout"
+                android:resource="@layout/keyguard_widget" />
         </activity>
 
-        <activity-alias android:icon="@mipmap/ic_launcher_camera"
-                        android:label="@string/camera_label"
-                        android:name="com.android.camera.CameraLauncher"
-                        android:targetActivity="com.android.camera.CameraActivity" >
-            <intent-filter>
-                <action android:name="android.intent.action.MAIN" />
-                <category android:name="android.intent.category.DEFAULT" />
-                <category android:name="android.intent.category.LAUNCHER" />
-            </intent-filter>
-        </activity-alias>
-
-        <activity-alias android:icon="@mipmap/ic_launcher_camera"
-                        android:label="@string/camera_label"
-                        android:name="com.android.camera.Camera"
-                        android:targetActivity="com.android.camera.CameraActivity" >
-            <intent-filter>
-                <action android:name="android.intent.action.MAIN" />
-                <category android:name="android.intent.category.DEFAULT" />
-            </intent-filter>
-        </activity-alias>
-
-        <activity-alias android:icon="@mipmap/ic_launcher_video_camera"
-                android:label="@string/video_camera_label"
-                android:name="com.android.camera.VideoCamera"
-                android:targetActivity="com.android.camera.CameraActivity" >
-            <intent-filter>
-                <action android:name="android.media.action.VIDEO_CAMERA" />
-                <category android:name="android.intent.category.DEFAULT" />
-            </intent-filter>
-            <intent-filter>
-                <action android:name="android.media.action.VIDEO_CAPTURE" />
-                <category android:name="android.intent.category.DEFAULT" />
-            </intent-filter>
-        </activity-alias>
-
-        <receiver android:name="com.android.gallery3d.gadget.PhotoAppWidgetProvider"
-                android:label="@string/appwidget_title">
-            <intent-filter>
-                <action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
-            </intent-filter>
-            <meta-data android:name="android.appwidget.provider"
-                    android:resource="@xml/widget_info" />
-        </receiver>
-        <receiver android:name="com.android.gallery3d.app.PackagesMonitor">
-            <intent-filter>
-                <action android:name="android.intent.action.PACKAGE_ADDED"/>
-                <action android:name="android.intent.action.PACKAGE_REMOVED"/>
-                <action android:name="android.intent.action.PACKAGE_CHANGED"/>
-                <data android:scheme="package"/>
-            </intent-filter>
-        </receiver>
-        <service android:name="com.android.gallery3d.app.PackagesMonitor$AsyncService"/>
-        <receiver android:name="com.android.camera.CameraButtonIntentReceiver">
-            <intent-filter>
-                <action android:name="android.intent.action.CAMERA_BUTTON"/>
-            </intent-filter>
-        </receiver>
-        <receiver android:name="com.android.camera.DisableCameraReceiver">
-            <intent-filter>
-                <action android:name="android.intent.action.BOOT_COMPLETED" />
-            </intent-filter>
-        </receiver>
-        <service android:name="com.android.gallery3d.gadget.WidgetService"
-                android:permission="android.permission.BIND_REMOTEVIEWS"/>
-        <activity android:name="com.android.gallery3d.gadget.WidgetConfigure"
-                android:configChanges="keyboardHidden|orientation|screenSize"
-                android:theme="@style/android:Theme.Translucent.NoTitleBar">
-            <intent-filter>
-                <action android:name="android.appwidget.action.APPWIDGET_CONFIGURE" />
-            </intent-filter>
-        </activity>
-        <activity android:name="com.android.camera.ProxyLauncher"
-                android:theme="@style/Theme.ProxyLauncher">
-        </activity>
-        <service android:name="com.android.gallery3d.app.BatchService" />
         <service android:name="com.android.camera.MediaSaveService" />
     </application>
-</manifest>
+
+</manifest>
\ No newline at end of file
diff --git a/jni/filters/bwfilter.c b/jni/filters/bwfilter.c
deleted file mode 100644
index f7fb31a..0000000
--- a/jni/filters/bwfilter.c
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * 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.
- */
-
-#include <math.h>
-#include "filters.h"
-
-void JNIFUNCF(ImageFilterBwFilter, nativeApplyFilter, jobject bitmap, jint width, jint height, jint rw, jint gw, jint bw)
-{
-    char* destination = 0;
-    AndroidBitmap_lockPixels(env, bitmap, (void**) &destination);
-    unsigned char * rgb = (unsigned char * )destination;
-    float sr = rw;
-    float sg = gw;
-    float sb = bw;
-
-    float min = MIN(sg,sb);
-    min = MIN(sr,min);
-    float max =  MAX(sg,sb);
-    max = MAX(sr,max);
-    float avg = (min+max)/2;
-    sb /= avg;
-    sg /= avg;
-    sr /= avg;
-    int i;
-    int len = width * height * 4;
-
-    for (i = 0; i < len; i+=4)
-    {
-        float r = sr *rgb[RED];
-        float g = sg *rgb[GREEN];
-        float b = sb *rgb[BLUE];
-        min = MIN(g,b);
-        min = MIN(r,min);
-        max = MAX(g,b);
-        max = MAX(r,max);
-        avg =(min+max)/2;
-        rgb[RED]   = CLAMP(avg);
-        rgb[GREEN] = rgb[RED];
-        rgb[BLUE]  = rgb[RED];
-    }
-    AndroidBitmap_unlockPixels(env, bitmap);
-}
diff --git a/jni/filters/contrast.c b/jni/filters/contrast.c
deleted file mode 100644
index b04e936..0000000
--- a/jni/filters/contrast.c
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * 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.
- */
-
-#include <math.h>
-#include "filters.h"
-
-unsigned char clamp(int c)
-{
-    int N = 255;
-    c &= ~(c >> 31);
-    c -= N;
-    c &= (c >> 31);
-    c += N;
-    return  (unsigned char) c;
-}
-
-int clampMax(int c,int max)
-{
-    c &= ~(c >> 31);
-    c -= max;
-    c &= (c >> 31);
-    c += max;
-    return  c;
-}
-
-void JNIFUNCF(ImageFilterContrast, nativeApplyFilter, jobject bitmap, jint width, jint height, jfloat bright)
-{
-    char* destination = 0;
-    AndroidBitmap_lockPixels(env, bitmap, (void**) &destination);
-    unsigned char * rgb = (unsigned char * )destination;
-    int i;
-    int len = width * height * 4;
-    float m =  (float)pow(2, bright/100.);
-    float c =  127-m*127;
-
-    for (i = 0; i < len; i+=4) {
-        rgb[RED]   = clamp((int)(m*rgb[RED]+c));
-        rgb[GREEN] = clamp((int)(m*rgb[GREEN]+c));
-        rgb[BLUE]  = clamp((int)(m*rgb[BLUE]+c));
-    }
-    AndroidBitmap_unlockPixels(env, bitmap);
-}
-
diff --git a/jni/filters/edge.c b/jni/filters/edge.c
deleted file mode 100644
index 9f5d88f..0000000
--- a/jni/filters/edge.c
+++ /dev/null
@@ -1,126 +0,0 @@
-/*
- * 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.
- */
-
-#include <math.h>
-#include "filters.h"
-
-void JNIFUNCF(ImageFilterEdge, nativeApplyFilter, jobject bitmap, jint width, jint height, jfloat p)
-{
-    char* destination = 0;
-    AndroidBitmap_lockPixels(env, bitmap, (void**) &destination);
-
-    // using contrast function:
-    // f(v) = exp(-alpha * v^beta)
-    // use beta ~ 1
-
-    float const alpha = 5.0f;
-    float const beta = p;
-    float const c_min = 100.0f;
-    float const c_max = 500.0f;
-
-    // pixels must be 4 bytes
-    char * dst = destination;
-
-    int j, k;
-    char * ptr = destination;
-    int row_stride = 4 * width;
-
-    // set 2 row buffer (avoids bitmap copy)
-    int buf_len = 2 * row_stride;
-    char buf[buf_len];
-    int buf_row_ring = 0;
-
-    // set initial buffer to black
-    memset(buf, 0, buf_len * sizeof(char));
-    for (j = 3; j < buf_len; j+=4) {
-        *(buf + j) = 255;  // set initial alphas
-    }
-
-    // apply sobel filter
-    for (j = 1; j < height - 1; j++) {
-
-        for (k = 1; k < width - 1; k++){
-            int loc = j * row_stride + k * 4;
-
-            float bestx = 0.0f;
-            int l;
-            for (l = 0; l < 3; l++) {
-                float tmp = 0.0f;
-                tmp += *(ptr + (loc - row_stride + 4 + l));
-                tmp += *(ptr + (loc + 4 + l)) * 2.0f;
-                tmp += *(ptr + (loc + row_stride + 4 + l));
-                tmp -= *(ptr + (loc - row_stride - 4 + l));
-                tmp -= *(ptr + (loc - 4 + l)) * 2.0f;
-                tmp -= *(ptr + (loc + row_stride - 4 + l));
-                if (fabs(tmp) > fabs(bestx)) {
-                    bestx = tmp;
-                }
-            }
-
-            float besty = 0.0f;
-            for (l = 0; l < 3; l++) {
-                float tmp = 0.0f;
-                tmp -= *(ptr + (loc - row_stride - 4 + l));
-                tmp -= *(ptr + (loc - row_stride + l)) * 2.0f;
-                tmp -= *(ptr + (loc - row_stride + 4 + l));
-                tmp += *(ptr + (loc + row_stride - 4 + l));
-                tmp += *(ptr + (loc + row_stride + l)) * 2.0f;
-                tmp += *(ptr + (loc + row_stride + 4 + l));
-                if (fabs(tmp) > fabs(besty)) {
-                    besty = tmp;
-                }
-            }
-
-            // compute gradient magnitude
-            float mag = sqrt(bestx * bestx + besty * besty);
-
-            // clamp
-            mag = MIN(MAX(c_min, mag), c_max);
-
-            // scale to [0, 1]
-            mag = (mag - c_min) / (c_max - c_min);
-
-            float ret = 1.0f - exp (- alpha * pow(mag, beta));
-            ret = 255 * ret;
-
-            int off = k * 4;
-            *(buf + buf_row_ring + off) = ret;
-            *(buf + buf_row_ring + off + 1) = ret;
-            *(buf + buf_row_ring + off + 2) = ret;
-            *(buf + buf_row_ring + off + 3) = *(ptr + loc + 3);
-        }
-
-        buf_row_ring += row_stride;
-        buf_row_ring %= buf_len;
-
-        if (j - 1 >= 0) {
-            memcpy((dst + row_stride * (j - 1)), (buf + buf_row_ring), row_stride * sizeof(char));
-        }
-
-    }
-    buf_row_ring += row_stride;
-    buf_row_ring %= buf_len;
-    int second_last_row = row_stride * (height - 2);
-    memcpy((dst + second_last_row), (buf + buf_row_ring), row_stride * sizeof(char));
-
-    // set last row to black
-    int last_row = row_stride * (height - 1);
-    memset((dst + last_row), 0, row_stride * sizeof(char));
-    for (j = 3; j < row_stride; j+=4) {
-        *(dst + last_row + j) = 255;  // set alphas
-    }
-    AndroidBitmap_unlockPixels(env, bitmap);
-}
diff --git a/jni/filters/exposure.c b/jni/filters/exposure.c
deleted file mode 100644
index 6b32798..0000000
--- a/jni/filters/exposure.c
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * 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.
- */
-
-#include "filters.h"
-
-void JNIFUNCF(ImageFilterExposure, nativeApplyFilter, jobject bitmap, jint width, jint height, jfloat bright)
-{
-    char* destination = 0;
-    AndroidBitmap_lockPixels(env, bitmap, (void**) &destination);
-    unsigned char * rgb = (unsigned char * )destination;
-    int i;
-    int len = width * height * 4;
-
-    int m =   (255-bright);
-
-    for (i = 0; i < len; i+=4)
-    {
-        rgb[RED]   = clamp((255*(rgb[RED]))/m);
-        rgb[GREEN] = clamp((255*(rgb[GREEN]))/m);
-        rgb[BLUE]  = clamp((255*(rgb[BLUE]))/m);
-    }
-    AndroidBitmap_unlockPixels(env, bitmap);
-}
-
diff --git a/jni/filters/filters.h b/jni/filters/filters.h
deleted file mode 100644
index 14b69cd..0000000
--- a/jni/filters/filters.h
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * 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.
- */
-
-#ifndef FILTERS_H
-#define FILTERS_H
-
-#include <jni.h>
-#include <string.h>
-#include <android/log.h>
-#include <android/bitmap.h>
-
-typedef unsigned int Color;
-
-#define SetColor(a, r, g, b) ((a << 24) | (b << 16) | (g << 8) | (r << 0));
-#define GetA(color) (((color) >> 24) & 0xFF)
-#define GetB(color) (((color) >> 16) & 0xFF)
-#define GetG(color) (((color) >> 8) & 0xFF)
-#define GetR(color) (((color) >> 0) & 0xFF)
-
-#define MIN(a, b) (a < b ? a : b)
-#define MAX(a, b) (a > b ? a : b)
-
-#define LOG(msg...) __android_log_print(ANDROID_LOG_VERBOSE, "NativeFilters", msg)
-
-#define JNIFUNCF(cls, name, vars...) Java_com_android_gallery3d_filtershow_filters_ ## cls ## _ ## name(JNIEnv* env, jobject obj, vars)
-
-#define RED i
-#define GREEN i+1
-#define BLUE i+2
-#define ALPHA i+3
-#define CLAMP(c) (MAX(0, MIN(255, c)))
-
-__inline__ unsigned char  clamp(int c);
-__inline__ int clampMax(int c,int max);
-
-extern void rgb2hsv( unsigned char *rgb,int rgbOff,unsigned short *hsv,int hsvOff);
-extern void hsv2rgb(unsigned short *hsv,int hsvOff,unsigned char  *rgb,int rgbOff);
-extern void filterRedEye(unsigned char *src, unsigned char *dest, int iw, int ih, short *rect);
-extern double fastevalPoly(double *poly,int n, double x);
-#endif // FILTERS_H
diff --git a/jni/filters/fx.c b/jni/filters/fx.c
deleted file mode 100644
index c3c9cbd..0000000
--- a/jni/filters/fx.c
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- * 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.
- */
-
-#include "filters.h"
-
-__inline__ int  interp(unsigned char  *src, int p , int *off ,float dr,float dg, float db){
-
-    float fr00 = (src[p+off[0]])*(1-dr)+(src[p+off[1]])*dr;
-    float fr01 = (src[p+off[2]])*(1-dr)+(src[p+off[3]])*dr;
-    float fr10 = (src[p+off[4]])*(1-dr)+(src[p+off[5]])*dr;
-    float fr11 = (src[p+off[6]])*(1-dr)+(src[p+off[7]])*dr;
-    float frb0 = fr00 * (1-db)+fr01*db;
-    float frb1 = fr10 * (1-db)+fr11*db;
-    float frbg = frb0 * (1-dg)+frb1*dg;
-
-    return (int)frbg ;
-}
-
-void JNIFUNCF(ImageFilterFx, nativeApplyFilter, jobject bitmap, jint width, jint height,
-        jobject lutbitmap, jint lutwidth, jint lutheight,
-        jint start, jint end)
-{
-    char* destination = 0;
-    char* lut = 0;
-    AndroidBitmap_lockPixels(env, bitmap, (void**) &destination);
-    AndroidBitmap_lockPixels(env, lutbitmap, (void**) &lut);
-    unsigned char * rgb = (unsigned char * )destination;
-    unsigned char * lutrgb = (unsigned char * )lut;
-    int lutdim_r   = lutheight;
-    int lutdim_g   = lutheight;;
-    int lutdim_b   = lutwidth/lutheight;;
-    int STEP = 4;
-
-    int off[8] =  {
-            0,
-            STEP*1,
-            STEP*lutdim_r,
-            STEP*(lutdim_r + 1),
-            STEP*(lutdim_r*lutdim_b),
-            STEP*(lutdim_r*lutdim_b+1),
-            STEP*(lutdim_r*lutdim_b+lutdim_r),
-            STEP*(lutdim_r*lutdim_b+lutdim_r + 1)
-    };
-
-    float scale_R = (lutdim_r-1.f)/256.f;
-    float scale_G = (lutdim_g-1.f)/256.f;
-    float scale_B = (lutdim_b-1.f)/256.f;
-
-    int i;
-    for (i = start; i < end; i+= STEP)
-    {
-        int r = rgb[RED];
-        int g = rgb[GREEN];
-        int b = rgb[BLUE];
-
-        float fb = b*scale_B;
-        float fg = g*scale_G;
-        float fr = r*scale_R;
-        int lut_b = (int)fb;
-        int lut_g = (int)fg;
-        int lut_r = (int)fr;
-        int p = lut_r+lut_b*lutdim_r+lut_g*lutdim_r*lutdim_b;
-        p*=STEP;
-        float dr = fr-lut_r;
-        float dg = fg-lut_g;
-        float db = fb-lut_b;
-        rgb[RED]   = clamp(interp(lutrgb,p  ,off,dr,dg,db));
-        rgb[GREEN] = clamp(interp(lutrgb,p+1,off,dr,dg,db));
-        rgb[BLUE]  = clamp(interp(lutrgb,p+2,off,dr,dg,db));
-
-    }
-
-    AndroidBitmap_unlockPixels(env, bitmap);
-    AndroidBitmap_unlockPixels(env, lutbitmap);
-}
diff --git a/jni/filters/geometry.c b/jni/filters/geometry.c
deleted file mode 100644
index a0b5aaa..0000000
--- a/jni/filters/geometry.c
+++ /dev/null
@@ -1,184 +0,0 @@
-/*
- * 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.
- */
-
-#include "filters.h"
-#include <stdio.h>
-
-__inline__ void flipVertical(char * source, int srcWidth, int srcHeight, char * destination, int dstWidth, int dstHeight){
-    //Vertical
-    size_t cpy_bytes = sizeof(char) * 4;
-    int width = cpy_bytes * srcWidth;
-    int length = srcHeight;
-    int total = length * width;
-    size_t bytes_to_copy = sizeof(char) * width;
-    int i = 0;
-    int temp = total - width;
-    for (i = 0; i < total; i += width) {
-        memcpy(destination + temp - i, source + i, bytes_to_copy);
-    }
-}
-
-__inline__ void flipHorizontal(char * source, int srcWidth, int srcHeight, char * destination, int dstWidth, int dstHeight){
-    //Horizontal
-    size_t cpy_bytes = sizeof(char) * 4;
-    int width = cpy_bytes * srcWidth;
-    int length = srcHeight;
-    int total = length * width;
-    int i = 0;
-    int j = 0;
-    int temp = 0;
-    for (i = 0; i < total; i+= width) {
-        temp = width + i - cpy_bytes;
-        for (j = 0; j < width; j+=cpy_bytes) {
-            memcpy(destination + temp - j, source + i + j, cpy_bytes);
-        }
-    }
-}
-
-__inline__ void flip_fun(int flip, char * source, int srcWidth, int srcHeight, char * destination, int dstWidth, int dstHeight){
-    int horiz = (flip & 1) != 0;
-    int vert = (flip & 2) != 0;
-    if (horiz && vert){
-        int arr_len = dstWidth * dstHeight * sizeof(char) * 4;
-        char* temp = (char *) malloc(arr_len);
-        flipHorizontal(source, srcWidth, srcHeight, temp, dstWidth, dstHeight);
-        flipVertical(temp, dstWidth, dstHeight, destination, dstWidth, dstHeight);
-        free(temp);
-        return;
-    }
-    if (horiz){
-        flipHorizontal(source, srcWidth, srcHeight, destination, dstWidth, dstHeight);
-        return;
-    }
-    if (vert){
-        flipVertical(source, srcWidth, srcHeight, destination, dstWidth, dstHeight);
-        return;
-    }
-}
-
-//90 CCW (opposite of what's used in UI?)
-__inline__ void rotate90(char * source, int srcWidth, int srcHeight, char * destination, int dstWidth, int dstHeight){
-    size_t cpy_bytes = sizeof(char) * 4;
-    int width = cpy_bytes * srcWidth;
-    int length = srcHeight;
-    int total = length * width;
-    int i = 0;
-    int j = 0;
-    for (j = 0; j < length * cpy_bytes; j+= cpy_bytes){
-        for (i = 0; i < width; i+=cpy_bytes){
-            int column_disp = (width - cpy_bytes - i) * length;
-            int row_disp = j;
-            memcpy(destination + column_disp + row_disp , source + j * srcWidth + i, cpy_bytes);
-        }
-    }
-}
-
-__inline__ void rotate180(char * source, int srcWidth, int srcHeight, char * destination, int dstWidth, int dstHeight){
-    flip_fun(3, source, srcWidth, srcHeight, destination, dstWidth, dstHeight);
-}
-
-__inline__ void rotate270(char * source, int srcWidth, int srcHeight, char * destination, int dstWidth, int dstHeight){
-    rotate90(source, srcWidth, srcHeight, destination, dstWidth, dstHeight);
-    flip_fun(3, destination, dstWidth, dstHeight, destination, dstWidth, dstHeight);
-}
-
-// rotate == 1 is 90 degrees, 2 is 180, 3 is 270 (positive is CCW).
-__inline__ void rotate_fun(int rotate, char * source, int srcWidth, int srcHeight, char * destination, int dstWidth, int dstHeight){
-    switch( rotate )
-    {
-        case 1:
-            rotate90(source, srcWidth, srcHeight, destination, dstWidth, dstHeight);
-            break;
-        case 2:
-            rotate180(source, srcWidth, srcHeight, destination, dstWidth, dstHeight);
-            break;
-        case 3:
-            rotate270(source, srcWidth, srcHeight, destination, dstWidth, dstHeight);
-            break;
-        default:
-            break;
-    }
-}
-
-__inline__ void crop(char * source, int srcWidth, int srcHeight, char * destination, int dstWidth, int dstHeight, int offsetWidth, int offsetHeight){
-    size_t cpy_bytes = sizeof(char) * 4;
-    int row_width = cpy_bytes * srcWidth;
-    int new_row_width = cpy_bytes * dstWidth;
-    if ((srcWidth > dstWidth + offsetWidth) || (srcHeight > dstHeight + offsetHeight)){
-        return;
-    }
-    int i = 0;
-    int j = 0;
-    for (j = offsetHeight; j < offsetHeight + dstHeight; j++){
-        memcpy(destination + (j - offsetHeight) * new_row_width, source + j * row_width + offsetWidth * cpy_bytes, cpy_bytes * dstWidth );
-    }
-}
-
-void JNIFUNCF(ImageFilterGeometry, nativeApplyFilterFlip, jobject src, jint srcWidth, jint srcHeight, jobject dst, jint dstWidth, jint dstHeight, jint flip) {
-    char* destination = 0;
-    char* source = 0;
-    if (srcWidth != dstWidth || srcHeight != dstHeight) {
-        return;
-    }
-    AndroidBitmap_lockPixels(env, src, (void**) &source);
-    AndroidBitmap_lockPixels(env, dst, (void**) &destination);
-    flip_fun(flip, source, srcWidth, srcHeight, destination, dstWidth, dstHeight);
-    AndroidBitmap_unlockPixels(env, dst);
-    AndroidBitmap_unlockPixels(env, src);
-}
-
-void JNIFUNCF(ImageFilterGeometry, nativeApplyFilterRotate, jobject src, jint srcWidth, jint srcHeight, jobject dst, jint dstWidth, jint dstHeight, jint rotate) {
-    char* destination = 0;
-    char* source = 0;
-    int len = dstWidth * dstHeight * 4;
-    AndroidBitmap_lockPixels(env, src, (void**) &source);
-    AndroidBitmap_lockPixels(env, dst, (void**) &destination);
-    rotate_fun(rotate, source, srcWidth, srcHeight, destination, dstWidth, dstHeight);
-    AndroidBitmap_unlockPixels(env, dst);
-    AndroidBitmap_unlockPixels(env, src);
-}
-
-void JNIFUNCF(ImageFilterGeometry, nativeApplyFilterCrop, jobject src, jint srcWidth, jint srcHeight, jobject dst, jint dstWidth, jint dstHeight, jint offsetWidth, jint offsetHeight) {
-    char* destination = 0;
-    char* source = 0;
-    int len = dstWidth * dstHeight * 4;
-    AndroidBitmap_lockPixels(env, src, (void**) &source);
-    AndroidBitmap_lockPixels(env, dst, (void**) &destination);
-    crop(source, srcWidth, srcHeight, destination, dstWidth, dstHeight, offsetWidth, offsetHeight);
-    AndroidBitmap_unlockPixels(env, dst);
-    AndroidBitmap_unlockPixels(env, src);
-}
-
-void JNIFUNCF(ImageFilterGeometry, nativeApplyFilterStraighten, jobject src, jint srcWidth, jint srcHeight, jobject dst, jint dstWidth, jint dstHeight, jfloat straightenAngle) {
-    char* destination = 0;
-    char* source = 0;
-    int len = dstWidth * dstHeight * 4;
-    AndroidBitmap_lockPixels(env, src, (void**) &source);
-    AndroidBitmap_lockPixels(env, dst, (void**) &destination);
-    // TODO: implement straighten
-    int i = 0;
-    for (; i < len; i += 4) {
-        int r = source[RED];
-        int g = source[GREEN];
-        int b = source[BLUE];
-        destination[RED] = 128;
-        destination[GREEN] = g;
-        destination[BLUE] = 128;
-    }
-    AndroidBitmap_unlockPixels(env, dst);
-    AndroidBitmap_unlockPixels(env, src);
-}
-
diff --git a/jni/filters/gradient.c b/jni/filters/gradient.c
deleted file mode 100644
index 1a85697..0000000
--- a/jni/filters/gradient.c
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * 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.
- */
-
-#include "filters.h"
-
-void JNIFUNCF(ImageFilter, nativeApplyGradientFilter, jobject bitmap, jint width, jint height,
-        jintArray redGradient, jintArray greenGradient, jintArray blueGradient)
-{
-    char* destination = 0;
-    jint* redGradientArray = 0;
-    jint* greenGradientArray = 0;
-    jint* blueGradientArray = 0;
-    if (redGradient)
-        redGradientArray = (*env)->GetIntArrayElements(env, redGradient, NULL);
-    if (greenGradient)
-        greenGradientArray = (*env)->GetIntArrayElements(env, greenGradient, NULL);
-    if (blueGradient)
-        blueGradientArray = (*env)->GetIntArrayElements(env, blueGradient, NULL);
-
-    AndroidBitmap_lockPixels(env, bitmap, (void**) &destination);
-    int i;
-    int len = width * height * 4;
-    for (i = 0; i < len; i+=4)
-    {
-        if (redGradient)
-        {
-            int r = destination[RED];
-            r = redGradientArray[r];
-            destination[RED] = r;
-        }
-        if (greenGradient)
-        {
-            int g = destination[GREEN];
-            g = greenGradientArray[g];
-            destination[GREEN] = g;
-        }
-        if (blueGradient)
-        {
-            int b = destination[BLUE];
-            b = blueGradientArray[b];
-            destination[BLUE] = b;
-        }
-    }
-    if (redGradient)
-        (*env)->ReleaseIntArrayElements(env, redGradient, redGradientArray, 0);
-    if (greenGradient)
-        (*env)->ReleaseIntArrayElements(env, greenGradient, greenGradientArray, 0);
-    if (blueGradient)
-        (*env)->ReleaseIntArrayElements(env, blueGradient, blueGradientArray, 0);
-    AndroidBitmap_unlockPixels(env, bitmap);
-}
-
diff --git a/jni/filters/highlight.c b/jni/filters/highlight.c
deleted file mode 100644
index fe9b88f..0000000
--- a/jni/filters/highlight.c
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright (C) 2013 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.
- */
-
-#include <math.h>
-#include "filters.h"
-
-void JNIFUNCF(ImageFilterHighlights, nativeApplyFilter, jobject bitmap,
-              jint width, jint height, jfloatArray luminanceMap){
-    char* destination = 0;
-    AndroidBitmap_lockPixels(env, bitmap, (void**) &destination);
-    unsigned char * rgb = (unsigned char * )destination;
-    int i;
-    int len = width * height * 4;
-    jfloat* lum = (*env)->GetFloatArrayElements(env, luminanceMap,0);
-    unsigned short * hsv = (unsigned short *)malloc(3*sizeof(short));
-
-    for (i = 0; i < len; i+=4)
-    {
-        rgb2hsv(rgb,i,hsv,0);
-        int v = clampMax(hsv[0],4080);
-        hsv[0] = (unsigned short) clampMax(lum[((255*v)/4080)]*4080,4080);
-        hsv2rgb(hsv,0, rgb,i);
-    }
-
-    free(hsv);
-    AndroidBitmap_unlockPixels(env, bitmap);
-}
diff --git a/jni/filters/hsv.c b/jni/filters/hsv.c
deleted file mode 100644
index aabd053..0000000
--- a/jni/filters/hsv.c
+++ /dev/null
@@ -1,156 +0,0 @@
-/*
- * 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.
- */
-
-#include <math.h>
-#include "filters.h"
-
-double fastevalPoly(double *poly,int n, double x){
-
-    double f =x;
-    double sum = poly[0]+poly[1]*f;
-    int i;
-    for (i = 2; i < n; i++) {
-        f*=x;
-        sum += poly[i]*f;
-    }
-    return sum;
-}
-
-void rgb2hsv( unsigned char *rgb,int rgbOff,unsigned short *hsv,int hsvOff)
-{
-    int iMin,iMax,chroma;
-    int ABITS = 4;
-    int HSCALE = 256;
-
-    int k1=255 << ABITS;
-    int k2=HSCALE << ABITS;
-
-    int ri = rgb[rgbOff+0];
-    int gi = rgb[rgbOff+1];
-    int bi = rgb[rgbOff+2];
-    short rv,rs,rh;
-
-    if (ri > gi) {
-        iMax = MAX (ri, bi);
-        iMin = MIN (gi, bi);
-    } else {
-        iMax = MAX (gi, bi);
-        iMin = MIN (ri, bi);
-    }
-
-    chroma = iMax - iMin;
-    // set value
-    rv = (short)( iMax << ABITS);
-
-    // set saturation
-    if (rv == 0)
-        rs = 0;
-    else
-        rs = (short)((k1*chroma)/iMax);
-
-    // set hue
-    if (rs == 0)
-        rh = 0;
-    else {
-        if ( ri == iMax ) {
-            rh  = (short)( (k2*(6*chroma+gi - bi))/(6*chroma));
-            if (rh >= k2) rh -= k2;
-        } else if (gi  == iMax)
-            rh  = (short)( (k2*(2*chroma+bi - ri ))/(6*chroma));
-        else // (bi == iMax )
-                    rh  = (short)( (k2*(4*chroma+ri - gi ))/(6*chroma));
-    }
-    hsv[hsvOff+0] = rv;
-    hsv[hsvOff+1] = rs;
-    hsv[hsvOff+2] = rh;
-}
-
-void hsv2rgb(unsigned short *hsv,int hsvOff, unsigned char *rgb,int rgbOff)
-{
-    int ABITS = 4;
-    int HSCALE = 256;
-    int m;
-    int H,X,ih,is,iv;
-    int k1=255<<ABITS;
-    int k2=HSCALE<<ABITS;
-    int k3=1<<(ABITS-1);
-    int rr=0;
-    int rg=0;
-    int rb=0;
-    short cv = hsv[hsvOff+0];
-    short cs = hsv[hsvOff+1];
-    short ch = hsv[hsvOff+2];
-
-    // set chroma and min component value m
-    //chroma = ( cv * cs )/k1;
-    //m = cv - chroma;
-    m = ((int)cv*(k1 - (int)cs ))/k1;
-
-    // chroma  == 0 <-> cs == 0 --> m=cv
-    if (cs == 0) {
-        rb = ( rg = ( rr =( cv >> ABITS) ));
-    } else {
-        ih=(int)ch;
-        is=(int)cs;
-        iv=(int)cv;
-
-        H = (6*ih)/k2;
-        X = ((iv*is)/k2)*(k2- abs(6*ih- 2*(H>>1)*k2 - k2)) ;
-
-        // removing additional bits --> unit8
-        X=( (X+iv*(k1 - is ))/k1 + k3 ) >> ABITS;
-        m=m >> ABITS;
-
-        // ( chroma + m ) --> cv ;
-        cv=(short) (cv >> ABITS);
-        switch (H) {
-        case 0:
-            rr = cv;
-            rg = X;
-            rb = m;
-            break;
-        case 1:
-            rr = X;
-            rg = cv;
-            rb = m;
-            break;
-        case 2:
-            rr = m;
-            rg = cv;
-            rb = X;
-            break;
-        case 3:
-            rr = m;
-            rg = X;
-            rb = cv;
-            break;
-        case 4:
-            rr = X;
-            rg = m;
-            rb = cv;
-            break;
-        case 5:
-            rr = cv;
-            rg = m ;
-            rb = X;
-            break;
-        }
-    }
-    rgb[rgbOff+0] =  rr;
-    rgb[rgbOff+1] =  rg;
-    rgb[rgbOff+2] =  rb;
-}
-
diff --git a/jni/filters/hue.c b/jni/filters/hue.c
deleted file mode 100644
index a4aef93..0000000
--- a/jni/filters/hue.c
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * 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.
- */
-
-#include "filters.h"
-
-void JNIFUNCF(ImageFilterHue, nativeApplyFilter, jobject bitmap, jint width, jint height, jfloatArray matrix)
-{
-    char* destination = 0;
-    AndroidBitmap_lockPixels(env, bitmap, (void**) &destination);
-    unsigned char * rgb = (unsigned char * )destination;
-    int i;
-    int len = width * height * 4;
-    jfloat* mat = (*env)->GetFloatArrayElements(env, matrix,0);
-
-    for (i = 0; i < len; i+=4)
-    {
-      int r = rgb[RED];
-      int g = rgb[GREEN];
-      int b = rgb[BLUE];
-
-      float rf = r*mat[0] + g*mat[4] +  b*mat[8] + mat[12];
-      float gf = r*mat[1] + g*mat[5] +  b*mat[9] + mat[13];
-      float bf = r*mat[2] + g*mat[6] +  b*mat[10] + mat[14];
-
-      rgb[RED]   = clamp((int)rf);
-      rgb[GREEN] = clamp((int)gf);
-      rgb[BLUE]  = clamp((int)bf);
-    }
-
-    (*env)->ReleaseFloatArrayElements(env, matrix, mat, 0);
-    AndroidBitmap_unlockPixels(env, bitmap);
-}
-
diff --git a/jni/filters/kmeans.cc b/jni/filters/kmeans.cc
deleted file mode 100644
index 97cead7..0000000
--- a/jni/filters/kmeans.cc
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * 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.
- */
-
-#include "filters.h"
-#include "kmeans.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/*
- * For reasonable speeds:
- * k < 30
- * small_ds_bitmap width/height < 64 pixels.
- * large_ds_bitmap width/height < 512 pixels
- *
- * bad for high-frequency image noise
- */
-
-void JNIFUNCF(ImageFilterKMeans, nativeApplyFilter, jobject bitmap, jint width, jint height,
-        jobject large_ds_bitmap, jint lwidth, jint lheight, jobject small_ds_bitmap,
-        jint swidth, jint sheight, jint p, jint seed)
-{
-    char* destination = 0;
-    char* larger_ds_dst = 0;
-    char* smaller_ds_dst = 0;
-    AndroidBitmap_lockPixels(env, bitmap, (void**) &destination);
-    AndroidBitmap_lockPixels(env, large_ds_bitmap, (void**) &larger_ds_dst);
-    AndroidBitmap_lockPixels(env, small_ds_bitmap, (void**) &smaller_ds_dst);
-    unsigned char * dst = (unsigned char *) destination;
-
-    unsigned char * small_ds = (unsigned char *) smaller_ds_dst;
-    unsigned char * large_ds = (unsigned char *) larger_ds_dst;
-
-    // setting for small bitmap
-    int len = swidth * sheight * 4;
-    int dimension = 3;
-    int stride = 4;
-    int iterations = 20;
-    int k = p;
-    unsigned int s = seed;
-    unsigned char finalCentroids[k * stride];
-
-    // get initial picks from small downsampled image
-    runKMeans<unsigned char, int>(k, finalCentroids, small_ds, len, dimension,
-            stride, iterations, s);
-
-
-    len = lwidth * lheight * 4;
-    iterations = 8;
-    unsigned char nextCentroids[k * stride];
-
-    // run kmeans on large downsampled image
-    runKMeansWithPicks<unsigned char, int>(k, nextCentroids, large_ds, len,
-            dimension, stride, iterations, finalCentroids);
-
-    len = width * height * 4;
-
-    // apply to final image
-    applyCentroids<unsigned char, int>(k, nextCentroids, dst, len, dimension, stride);
-
-    AndroidBitmap_unlockPixels(env, small_ds_bitmap);
-    AndroidBitmap_unlockPixels(env, large_ds_bitmap);
-    AndroidBitmap_unlockPixels(env, bitmap);
-}
-#ifdef __cplusplus
-}
-#endif
diff --git a/jni/filters/kmeans.h b/jni/filters/kmeans.h
deleted file mode 100644
index 2450605..0000000
--- a/jni/filters/kmeans.h
+++ /dev/null
@@ -1,232 +0,0 @@
-/*
- * 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.
- */
-
-#ifndef KMEANS_H
-#define KMEANS_H
-
-#include <cstdlib>
-#include <math.h>
-
-// Helper functions
-
-template <typename T, typename N>
-inline void sum(T values[], int len, int dimension, int stride, N dst[]) {
-    int x, y;
-    // zero out dst vector
-    for (x = 0; x < dimension; x++) {
-        dst[x] = 0;
-    }
-    for (x = 0; x < len; x+= stride) {
-        for (y = 0; y < dimension; y++) {
-            dst[y] += values[x + y];
-        }
-    }
-}
-
-template <typename T, typename N>
-inline void set(T val1[], N val2[], int dimension) {
-    int x;
-    for (x = 0; x < dimension; x++) {
-        val1[x] = val2[x];
-    }
-}
-
-template <typename T, typename N>
-inline void add(T val[], N dst[], int dimension) {
-    int x;
-    for (x = 0; x < dimension; x++) {
-        dst[x] += val[x];
-    }
-}
-
-template <typename T, typename N>
-inline void divide(T dst[], N divisor, int dimension) {
-   int x;
-   if (divisor == 0) {
-       return;
-   }
-   for (x = 0; x < dimension; x++) {
-       dst[x] /= divisor;
-   }
-}
-
-/**
- * Calculates euclidean distance.
- */
-
-template <typename T, typename N>
-inline N euclideanDist(T val1[], T val2[], int dimension) {
-    int x;
-    N sum = 0;
-    for (x = 0; x < dimension; x++) {
-        N diff = (N) val1[x] - (N) val2[x];
-        sum += diff * diff;
-    }
-    return sqrt(sum);
-}
-
-// K-Means
-
-
-/**
- * Picks k random starting points from the data set.
- */
-template <typename T>
-void initialPickHeuristicRandom(int k, T values[], int len, int dimension, int stride, T dst[],
-        unsigned int seed) {
-    int x, z, num_vals, cntr;
-    num_vals = len / stride;
-    cntr = 0;
-    srand(seed);
-    unsigned int r_vals[k];
-    unsigned int r;
-
-    for (x = 0; x < k; x++) {
-
-        // ensure randomly chosen value is unique
-        int r_check = 0;
-        while (r_check == 0) {
-            r = (unsigned int) rand() % num_vals;
-            r_check = 1;
-            for (z = 0; z < x; z++) {
-                if (r == r_vals[z]) {
-                    r_check = 0;
-                }
-            }
-        }
-        r_vals[x] = r;
-        r *= stride;
-
-        // set dst to be randomly chosen value
-        set<T,T>(dst + cntr, values + r, dimension);
-        cntr += stride;
-    }
-}
-
-/**
- * Finds index of closet centroid to a value
- */
-template <typename T, typename N>
-inline int findClosest(T values[], T oldCenters[], int dimension, int stride, int pop_size) {
-    int best_ind = 0;
-    N best_len = euclideanDist <T, N>(values, oldCenters, dimension);
-    int y;
-    for (y = stride; y < pop_size; y+=stride) {
-        N l = euclideanDist <T, N>(values, oldCenters + y, dimension);
-        if (l < best_len) {
-            best_len = l;
-            best_ind = y;
-        }
-    }
-    return best_ind;
-}
-
-/**
- * Calculates new centroids by averaging value clusters for old centroids.
- */
-template <typename T, typename N>
-int calculateNewCentroids(int k, T values[], int len, int dimension, int stride, T oldCenters[],
-        T dst[]) {
-    int x, pop_size;
-    pop_size = k * stride;
-    int popularities[k];
-    N tmp[pop_size];
-
-    //zero popularities
-    memset(popularities, 0, sizeof(int) * k);
-    // zero dst, and tmp
-    for (x = 0; x < pop_size; x++) {
-        tmp[x] = 0;
-    }
-
-    // put summation for each k in tmp
-    for (x = 0; x < len; x+=stride) {
-        int best = findClosest<T, N>(values + x, oldCenters, dimension, stride, pop_size);
-        add<T, N>(values + x, tmp + best, dimension);
-        popularities[best / stride]++;
-
-    }
-
-    int ret = 0;
-    int y;
-    // divide to get centroid and set dst to result
-    for (x = 0; x < pop_size; x+=stride) {
-        divide<N, int>(tmp + x, popularities[x / stride], dimension);
-        for (y = 0; y < dimension; y++) {
-            if ((dst + x)[y] != (T) ((tmp + x)[y])) {
-                ret = 1;
-            }
-        }
-        set(dst + x, tmp + x, dimension);
-    }
-    return ret;
-}
-
-template <typename T, typename N>
-void runKMeansWithPicks(int k, T finalCentroids[], T values[], int len, int dimension, int stride,
-        int iterations, T initialPicks[]){
-        int k_len = k * stride;
-        int x;
-
-        // zero newCenters
-        for (x = 0; x < k_len; x++) {
-            finalCentroids[x] = 0;
-        }
-
-        T * c1 = initialPicks;
-        T * c2 = finalCentroids;
-        T * temp;
-        int ret = 1;
-        for (x = 0; x < iterations; x++) {
-            ret = calculateNewCentroids<T, N>(k, values, len, dimension, stride, c1, c2);
-            temp = c1;
-            c1 = c2;
-            c2 = temp;
-            if (ret == 0) {
-                x = iterations;
-            }
-        }
-        set<T, T>(finalCentroids, c1, dimension);
-}
-
-/**
- * Runs the k-means algorithm on dataset values with some initial centroids.
- */
-template <typename T, typename N>
-void runKMeans(int k, T finalCentroids[], T values[], int len, int dimension, int stride,
-        int iterations, unsigned int seed){
-    int k_len = k * stride;
-    T initialPicks [k_len];
-    initialPickHeuristicRandom<T>(k, values, len, dimension, stride, initialPicks, seed);
-
-    runKMeansWithPicks<T, N>(k, finalCentroids, values, len, dimension, stride,
-        iterations, initialPicks);
-}
-
-/**
- * Sets each value in values to the closest centroid.
- */
-template <typename T, typename N>
-void applyCentroids(int k, T centroids[], T values[], int len, int dimension, int stride) {
-    int x, pop_size;
-    pop_size = k * stride;
-    for (x = 0; x < len; x+= stride) {
-        int best = findClosest<T, N>(values + x, centroids, dimension, stride, pop_size);
-        set<T, T>(values + x, centroids + best, dimension);
-    }
-}
-
-#endif // KMEANS_H
diff --git a/jni/filters/negative.c b/jni/filters/negative.c
deleted file mode 100644
index 735e583..0000000
--- a/jni/filters/negative.c
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * 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.
- */
-
-#include "filters.h"
-
-void JNIFUNCF(ImageFilterNegative, nativeApplyFilter, jobject bitmap, jint width, jint height)
-{
-    char* destination = 0;
-    AndroidBitmap_lockPixels(env, bitmap, (void**) &destination);
-
-    int tot_len = height * width * 4;
-    int i;
-    char * dst = destination;
-    for (i = 0; i < tot_len; i+=4) {
-        dst[RED] = 255 - dst[RED];
-        dst[GREEN] = 255 - dst[GREEN];
-        dst[BLUE] = 255 - dst[BLUE];
-    }
-    AndroidBitmap_unlockPixels(env, bitmap);
-}
diff --git a/jni/filters/redEyeMath.c b/jni/filters/redEyeMath.c
deleted file mode 100644
index 26f3f76..0000000
--- a/jni/filters/redEyeMath.c
+++ /dev/null
@@ -1,172 +0,0 @@
-/*
- * 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.
- */
-
-#include <math.h>
-#include "filters.h"
-
-int value(int r, int g, int b) {
-    return MAX(r, MAX(g, b));
-}
-
-int isRed(unsigned char *src, int p) {
-    int b = src[p + 2];
-    int g = src[p + 1];
-    int r = src[p];
-    int max = MAX(g, b);
-
-    return ((r * 100 / (max + 2) > 160) & (max < 80));
-}
-
-void findPossible(unsigned char *src, unsigned char *mask, int iw, int ih,
-        short *rect) {
-    int recX = rect[0], recY = rect[1], recW = rect[2], recH = rect[3];
-    int y, x;
-
-    for (y = 0; y < recH; y++) {
-        int sy = (recY + y) * iw;
-        for (x = 0; x < recW; x++) {
-            int p = (recX + x + sy) * 4;
-
-            int b = src[p + 2];
-            int g = src[p + 1];
-            int r = src[p];
-            mask[x + y * recW] = (
-                    mask[x + y * recW] > 0 && (value(r, g, b) > 240) ? 1 : 0);
-
-        }
-
-    }
-}
-
-void findReds(unsigned char *src, unsigned char *mask, int iw, int ih,
-        short *rect) {
-    int recX = rect[0], recY = rect[1], recW = rect[2], recH = rect[3];
-    int y, x;
-
-    for (y = 0; y < recH; y++) {
-        int sy = (recY + y) * iw;
-        for (x = 0; x < recW; x++) {
-            int p = (recX + x + sy) * 4;
-
-            mask[x + y * recW] = ((isRed(src, p)) ? 1 : 0);
-
-        }
-
-    }
-}
-
-void dialateMaskIfRed(unsigned char *src, int iw, int ih, unsigned char *mask,
-        unsigned char *out, short *rect) {
-    int recX = rect[0], recY = rect[1], recW = rect[2], recH = rect[3];
-    int y, x;
-
-    for (y = 1; y < recH - 1; y++) {
-        int row = recW * y;
-        int sy = (recY + y) * iw;
-        for (x = 1; x < recW - 1; x++) {
-            int p = (recX + x + sy) * 4;
-
-            char b = (mask[row + x] | mask[row + x + 1] | mask[row + x - 1]
-                    | mask[row + x - recW] | mask[row + x + recW]);
-            if (b != 0 && isRed(src, p))
-                out[row + x] = 1;
-            else
-                out[row + x] = mask[row + x];
-        }
-    }
-}
-
-void dialateMask(unsigned char *mask, unsigned char *out, int mw, int mh) {
-    int y, x;
-    for (y = 1; y < mh - 1; y++) {
-        int row = mw * y;
-        for (x = 1; x < mw - 1; x++) {
-            out[row + x] = (mask[row + x] | mask[row + x + 1]
-                    | mask[row + x - 1] | mask[row + x - mw]
-                    | mask[row + x + mw]);
-        }
-    }
-}
-
-void stuff(int r, int g, int b, unsigned char *img, int off) {
-    img[off + 2] = b;
-    img[off + 1] = g;
-    img[off] = r;
-}
-
-void filterRedEye(unsigned char *src, unsigned char *dest, int iw, int ih, short *rect) {
-    int recX = rect[0], recY = rect[1], recW = rect[2], recH = rect[3];
-    unsigned char *mask1 = (unsigned char *) malloc(recW * recH);
-    unsigned char *mask2 = (unsigned char *)malloc(recW*recH);
-    int QUE_LEN = 100;
-    int y, x, i;
-
-    rect[0] = MAX(rect[0],0);
-    rect[1] = MAX(rect[1],0);
-    rect[2] = MIN(rect[2]+rect[0],iw)-rect[0];
-    rect[3] = MIN(rect[3]+rect[1],ih)-rect[1];
-
-    findReds(src, mask2, iw, ih, rect);
-    dialateMask(mask2, mask1, recW, recH);
-    dialateMask(mask1, mask2, recW, recH);
-    dialateMask(mask2, mask1, recW, recH);
-    dialateMask(mask1, mask2, recW, recH);
-    findPossible(src, mask2, iw, ih, rect);
-    dialateMask(mask2, mask1, recW, recH);
-
-    for (i = 0; i < 12; i++) {
-        dialateMaskIfRed(src, iw, ih, mask1, mask2, rect);
-        dialateMaskIfRed(src, iw, ih, mask2, mask1, rect);
-    }
-    dialateMask(mask1, mask2, recW, recH);
-    dialateMask(mask2, mask1, recW, recH);
-
-    for (y = 3; y < recH-3; y++) {
-        int sy = (recY + y) * iw;
-        for (x = 3; x < recW-3; x++) {
-            int p = (recX + x + sy) * 4;
-
-            int b = src[p + 2];
-            int g = src[p + 1];
-            int r = src[p];
-
-            if (mask1[x + y * recW] != 0) {
-                int m = MAX(g,b);
-                float rr = (r - m) / (float) m;
-                if (rr > .7f && g < 60 && b < 60) {
-                    dest[p + 2] = (0);
-                    dest[p + 1] = (0);
-                    dest[p] = (0);
-                } else {
-                    if (mask2[x + y * recW] != 0) {
-                        stuff(r / 2, g / 2, b / 2, dest, p);
-                    } else
-                        stuff((2 * r) / 3, (2 * g) / 3, (2 * b) / 3, dest, p);
-                }
-
-            } else
-                stuff(r, g, b, dest, p);
-
-            //dest[p + 2] = dest[p + 1] =dest[p]=src[p];
-        }
-
-    }
-
-    free(mask1);
-    free(mask2);
-}
-
-
diff --git a/jni/filters/redeye.c b/jni/filters/redeye.c
deleted file mode 100644
index 9a358dd..0000000
--- a/jni/filters/redeye.c
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * 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.
- */
-
-#include <math.h>
-#include "filters.h"
-
- void JNIFUNCF(ImageFilterRedEye, nativeApplyFilter, jobject bitmap, jint width, jint height, jshortArray vrect)
- {
-     char* destination = 0;
-     AndroidBitmap_lockPixels(env, bitmap, (void**) &destination);
-     unsigned char * rgb = (unsigned char * )destination;
-     short* rect = (*env)->GetShortArrayElements(env, vrect,0);
-
-     filterRedEye(rgb,rgb,width,height,rect);
-
-     (*env)->ReleaseShortArrayElements(env, vrect, rect, 0);
-     AndroidBitmap_unlockPixels(env, bitmap);
- }
diff --git a/jni/filters/saturated.c b/jni/filters/saturated.c
deleted file mode 100644
index 1bc0cc5..0000000
--- a/jni/filters/saturated.c
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * 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.
- */
-
-#include "filters.h"
-
-void JNIFUNCF(ImageFilterSaturated, nativeApplyFilter, jobject bitmap, jint width, jint height, jfloat saturation)
-{
-    char* destination = 0;
-    AndroidBitmap_lockPixels(env, bitmap, (void**) &destination);
-    int i;
-    int len = width * height * 4;
-    float Rf = 0.2999f;
-    float Gf = 0.587f;
-    float Bf = 0.114f;
-    float S = saturation;;
-    float MS = 1.0f - S;
-    float Rt = Rf * MS;
-    float Gt = Gf * MS;
-    float Bt = Bf * MS;
-    float R, G, B;
-    for (i = 0; i < len; i+=4)
-    {
-        int r = destination[RED];
-        int g = destination[GREEN];
-        int b = destination[BLUE];
-        int t = (r + g) / 2;
-        R = r;
-        G = g;
-        B = b;
-
-        float Rc = R * (Rt + S) + G * Gt + B * Bt;
-        float Gc = R * Rt + G * (Gt + S) + B * Bt;
-        float Bc = R * Rt + G * Gt + B * (Bt + S);
-
-        destination[RED] = CLAMP(Rc);
-        destination[GREEN] = CLAMP(Gc);
-        destination[BLUE] = CLAMP(Bc);
-    }
-    AndroidBitmap_unlockPixels(env, bitmap);
-}
diff --git a/jni/filters/shadows.c b/jni/filters/shadows.c
deleted file mode 100644
index 38d64c8..0000000
--- a/jni/filters/shadows.c
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * 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.
- */
-
-#include <math.h>
-#include "filters.h"
-
-void JNIFUNCF(ImageFilterShadows, nativeApplyFilter, jobject bitmap, jint width, jint height, float scale){
-    double shadowFilterMap[] = {
-            -0.00591,  0.0001,
-             1.16488,  0.01668,
-            -0.18027, -0.06791,
-            -0.12625,  0.09001,
-             0.15065, -0.03897
-    };
-
-    char* destination = 0;
-    AndroidBitmap_lockPixels(env, bitmap, (void**) &destination);
-    unsigned char * rgb = (unsigned char * )destination;
-    int i;
-    double s = (scale>=0)?scale:scale/5;
-    int len = width * height * 4;
-
-    double *poly = (double *) malloc(5*sizeof(double));
-    for (i = 0; i < 5; i++) {
-        poly[i] = fastevalPoly(shadowFilterMap+i*2,2 , s);
-    }
-
-    unsigned short * hsv = (unsigned short *)malloc(3*sizeof(short));
-
-    for (i = 0; i < len; i+=4)
-    {
-        rgb2hsv(rgb,i,hsv,0);
-
-        double v = (fastevalPoly(poly,5,hsv[0]/4080.)*4080);
-        if (v>4080) v = 4080;
-        hsv[0] = (unsigned short) ((v>0)?v:0);
-
-        hsv2rgb(hsv,0, rgb,i);
-    }
-
-    free(poly);
-    free(hsv);
-    AndroidBitmap_unlockPixels(env, bitmap);
-}
diff --git a/jni/filters/tinyplanet.cc b/jni/filters/tinyplanet.cc
deleted file mode 100644
index beac086..0000000
--- a/jni/filters/tinyplanet.cc
+++ /dev/null
@@ -1,150 +0,0 @@
-/*
- * 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.
- */
-
-#include "filters.h"
-#include <math.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-
-#define PI_F 3.141592653589f
-
-class ImageRGBA {
- public:
-  ImageRGBA(unsigned char* image, int width, int height)
-   : image_(image), width_(width), height_(height) {
-    width_step_ = width * 4;
-  }
-
-  int Width() const {
-    return width_;
-  }
-
-  int Height() const {
-    return height_;
-  }
-
-  // Pixel accessor.
-  unsigned char* operator()(int x, int y) {
-    return image_ + y * width_step_ + x * 4;
-  }
-  const unsigned char* operator()(int x, int y) const {
-    return image_ + y * width_step_ + x * 4;
-  }
-
- private:
-  unsigned char* image_;
-  int width_;
-  int height_;
-  int width_step_;
-};
-
-// Interpolate a pixel in a 3 channel image.
-inline void InterpolatePixel(const ImageRGBA &image, float x, float y,
-                             unsigned char* dest) {
-  // Get pointers and scale factors for the source pixels.
-  float ax = x - floor(x);
-  float ay = y - floor(y);
-  float axn = 1.0f - ax;
-  float ayn = 1.0f - ay;
-  const unsigned char *p = image(x, y);
-  const unsigned char *p2 = image(x, y + 1);
-
-  // Interpolate each image color plane.
-  dest[0] = static_cast<unsigned char>(axn * ayn * p[0] + ax * ayn * p[4] +
-             ax * ay * p2[4] + axn * ay * p2[0] + 0.5f);
-  p++;
-  p2++;
-
-  dest[1] = static_cast<unsigned char>(axn * ayn * p[0] + ax * ayn * p[4] +
-             ax * ay * p2[4] + axn * ay * p2[0] + 0.5f);
-  p++;
-  p2++;
-
-  dest[2] = static_cast<unsigned char>(axn * ayn * p[0] + ax * ayn * p[4] +
-             ax * ay * p2[4] + axn * ay * p2[0] + 0.5f);
-  p++;
-  p2++;
-  dest[3] = 0xFF;
-}
-
-// Wrap circular coordinates around the globe
-inline float wrap(float value, float dimension) {
-  return value - (dimension * floor(value/dimension));
-}
-
-void StereographicProjection(float scale, float angle, unsigned char* input_image,
-                             int input_width, int input_height,
-                             unsigned char* output_image, int output_width,
-                             int output_height) {
-  ImageRGBA input(input_image, input_width, input_height);
-  ImageRGBA output(output_image, output_width, output_height);
-
-  const float image_scale = output_width * scale;
-
-  for (int x = 0; x < output_width; x++) {
-    // Center and scale x
-    float xf = (x - output_width / 2.0f) / image_scale;
-
-    for (int y = 0; y < output_height; y++) {
-      // Center and scale y
-      float yf = (y - output_height / 2.0f) / image_scale;
-
-      // Convert to polar
-      float r = hypotf(xf, yf);
-      float theta = angle+atan2(yf, xf);
-      if (theta>PI_F) theta-=2*PI_F;
-
-      // Project onto plane
-      float phi = 2 * atan(1 / r);
-      // (theta stays the same)
-
-      // Map to panorama image
-      float px = (theta / (2 * PI_F)) * input_width;
-      float py = (phi / PI_F) * input_height;
-
-      // Wrap around the globe
-      px = wrap(px, input_width);
-      py = wrap(py, input_height);
-
-      // Write the interpolated pixel
-      InterpolatePixel(input, px, py, output(x, y));
-    }
-  }
-}
-
-
-void JNIFUNCF(ImageFilterTinyPlanet, nativeApplyFilter, jobject bitmap_in, jint width, jint height, jobject bitmap_out, jint output_size, jfloat scale,jfloat angle)
-{
-    char* source = 0;
-    char* destination = 0;
-    AndroidBitmap_lockPixels(env, bitmap_in, (void**) &source);
-    AndroidBitmap_lockPixels(env, bitmap_out, (void**) &destination);
-    unsigned char * rgb_in = (unsigned char * )source;
-    unsigned char * rgb_out = (unsigned char * )destination;
-
-    StereographicProjection(scale,angle, rgb_in, width, height, rgb_out, output_size, output_size);
-    AndroidBitmap_unlockPixels(env, bitmap_in);
-    AndroidBitmap_unlockPixels(env, bitmap_out);
-}
-
-#ifdef __cplusplus
-}
-#endif
-
-
diff --git a/jni/filters/vibrance.c b/jni/filters/vibrance.c
deleted file mode 100644
index cb5c536..0000000
--- a/jni/filters/vibrance.c
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * 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.
- */
-
-#include <math.h>
-#include "filters.h"
-
-void JNIFUNCF(ImageFilterVibrance, nativeApplyFilter, jobject bitmap, jint width, jint height,  jfloat vibrance)
-{
-    char* destination = 0;
-    AndroidBitmap_lockPixels(env, bitmap, (void**) &destination);
-    int i;
-    int len = width * height * 4;
-    float Rf = 0.2999f;
-    float Gf = 0.587f;
-    float Bf = 0.114f;
-    float Vib = vibrance/100.f;
-    float S  = Vib+1;
-    float MS = 1.0f - S;
-    float Rt = Rf * MS;
-    float Gt = Gf * MS;
-    float Bt = Bf * MS;
-    float R, G, B;
-    for (i = 0; i < len; i+=4)
-    {
-        int r = destination[RED];
-        int g = destination[GREEN];
-        int b = destination[BLUE];
-        float red = (r-MAX(g, b))/256.f;
-        float sx = (float)(Vib/(1+exp(-red*3)));
-        S = sx+1;
-        MS = 1.0f - S;
-        Rt = Rf * MS;
-        Gt = Gf * MS;
-        Bt = Bf * MS;
-        int t = (r + g) / 2;
-        R = r;
-        G = g;
-        B = b;
-
-        float Rc = R * (Rt + S) + G * Gt + B * Bt;
-        float Gc = R * Rt + G * (Gt + S) + B * Bt;
-        float Bc = R * Rt + G * Gt + B * (Bt + S);
-
-        destination[RED] = CLAMP(Rc);
-        destination[GREEN] = CLAMP(Gc);
-        destination[BLUE] = CLAMP(Bc);
-    }
-    AndroidBitmap_unlockPixels(env, bitmap);
-}
diff --git a/jni/filters/vignette.c b/jni/filters/vignette.c
deleted file mode 100644
index b9ee3ff..0000000
--- a/jni/filters/vignette.c
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * 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.
- */
-
-#include "filters.h"
-#include <math.h>
-
-static int* gVignetteMap = 0;
-static int gVignetteWidth = 0;
-static int gVignetteHeight = 0;
-
-void JNIFUNCF(ImageFilterVignette, nativeApplyFilter, jobject bitmap, jint width, jint height, jint centerx, jint centery, jfloat radiusx, jfloat radiusy, jfloat strength)
-{
-    char* destination = 0;
-    AndroidBitmap_lockPixels(env, bitmap, (void**) &destination);
-    int i;
-    int len = width * height * 4;
-    int vignette = 0;
-    float d = centerx;
-    if (radiusx == 0) radiusx = 10;
-    if (radiusy == 0) radiusy = 10;
-    float scalex = 1/radiusx;
-    float scaley = 1/radiusy;
-
-    for (i = 0; i < len; i += 4)
-    {
-        int p = i/4;
-        float x = ((p%width)-centerx)*scalex;
-        float y = ((p/width)-centery)*scaley;
-        float dist = sqrt(x*x+y*y)-1;
-        vignette = (int) (strength*256*MAX(dist,0));
-        destination[RED] = CLAMP(destination[RED] - vignette);
-        destination[GREEN] = CLAMP(destination[GREEN] - vignette);
-        destination[BLUE] = CLAMP(destination[BLUE] - vignette);
-    }
-    AndroidBitmap_unlockPixels(env, bitmap);
-}
diff --git a/jni/filters/wbalance.c b/jni/filters/wbalance.c
deleted file mode 100644
index 2b92b99..0000000
--- a/jni/filters/wbalance.c
+++ /dev/null
@@ -1,169 +0,0 @@
-/*
- * 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.
- */
-
-#include "filters.h"
-
-void estmateWhite(unsigned char *src, int len, int *wr, int *wb, int *wg){
-
-    int STEP = 4;
-    int RANGE = 256;
-    int *histR = (int *) malloc(256*sizeof(int));
-    int *histG = (int *) malloc(256*sizeof(int));
-    int *histB = (int *) malloc(256*sizeof(int));
-    int i;
-    for (i = 0; i < 255; i++) {
-        histR[i] = histG[i] = histB[i] =0;
-    }
-
-    for (i = 0; i < len; i+=STEP) {
-        histR[(src[RED])]++;
-        histG[(src[GREEN])]++;
-        histB[(src[BLUE])]++;
-    }
-    int min_r = -1, min_g = -1,min_b = -1;
-    int max_r = 0, max_g = 0,max_b = 0;
-    int sum_r = 0,sum_g=0,sum_b=0;
-
-    for (i = 1; i < RANGE-1; i++) {
-        int r = histR[i];
-        int g = histG[i];
-        int b = histB[i];
-        sum_r += r;
-        sum_g += g;
-        sum_b += b;
-
-        if (r>0){
-            if (min_r < 0) min_r = i;
-            max_r = i;
-        }
-        if (g>0){
-            if (min_g < 0) min_g = i;
-            max_g = i;
-        }
-        if (b>0){
-            if (min_b < 0) min_b = i;
-            max_b = i;
-        }
-    }
-
-    int sum15r = 0,sum15g=0,sum15b=0;
-    int count15r = 0,count15g=0,count15b=0;
-    int tmp_r = 0,tmp_g=0,tmp_b=0;
-
-    for (i = RANGE-2; i >0; i--) {
-        int r = histR[i];
-        int g = histG[i];
-        int b = histB[i];
-        tmp_r += r;
-        tmp_g += g;
-        tmp_b += b;
-
-        if ((tmp_r > sum_r/20) && (tmp_r < sum_r/5)) {
-            sum15r += r*i;
-            count15r += r;
-        }
-        if ((tmp_g > sum_g/20) && (tmp_g < sum_g/5)) {
-            sum15g += g*i;
-            count15g += g;
-        }
-        if ((tmp_b > sum_b/20) && (tmp_b < sum_b/5)) {
-            sum15b += b*i;
-            count15b += b;
-        }
-
-    }
-    free(histR);
-    free(histG);
-    free(histB);
-
-    if ((count15r>0) && (count15g>0) && (count15b>0) ){
-        *wr = sum15r/count15r;
-        *wb = sum15g/count15g;
-        *wg = sum15b/count15b;
-    }else {
-        *wg  = *wb = *wr=255;
-    }
-}
-
-void estmateWhiteBox(unsigned char *src, int iw, int ih, int x,int y, int *wr, int *wb, int *wg){
-    int r;
-    int g;
-    int b;
-    int sum;
-    int xp,yp;
-    int bounds = 5;
-    if (x<0) x = bounds;
-    if (y<0) y = bounds;
-    if (x>=(iw-bounds)) x = (iw-bounds-1);
-    if (y>=(ih-bounds)) y = (ih-bounds-1);
-    int startx = x - bounds;
-    int starty = y - bounds;
-    int endx = x + bounds;
-    int endy = y + bounds;
-
-    for(yp= starty;yp<endy;yp++) {
-        for(xp= startx;xp<endx;xp++) {
-            int i = 4*(xp+yp*iw);
-            r += src[RED];
-            g += src[GREEN];
-            b += src[BLUE];
-            sum++;
-        }
-    }
-    *wr = r/sum;
-    *wg = g/sum;
-    *wb = b/sum;
-}
-
-void JNIFUNCF(ImageFilterWBalance, nativeApplyFilter, jobject bitmap, jint width, jint height, int locX,int locY)
-{
-    char* destination = 0;
-    AndroidBitmap_lockPixels(env, bitmap, (void**) &destination);
-    int i;
-    int len = width * height * 4;
-    unsigned char * rgb = (unsigned char * )destination;
-    int wr;
-    int wg;
-    int wb;
-
-    if (locX==-1)
-        estmateWhite(rgb,len,&wr,&wg,&wb);
-    else
-        estmateWhiteBox(rgb, width, height,locX,locY,&wr,&wg,&wb);
-
-    int min = MIN(wr, MIN(wg, wb));
-    int max = MAX(wr, MAX(wg, wb));
-    float avg = (min+max)/2.f;
-    float scaleR =  avg/wr;
-    float scaleG =  avg/wg;
-    float scaleB =  avg/wb;
-
-    for (i = 0; i < len; i+=4)
-    {
-        int r = rgb[RED];
-        int g = rgb[GREEN];
-        int b = rgb[BLUE];
-
-        float Rc =  r*scaleR;
-        float Gc =  g*scaleG;
-        float Bc =  b*scaleB;
-
-        rgb[RED]   = clamp(Rc);
-        rgb[GREEN] = clamp(Gc);
-        rgb[BLUE]  = clamp(Bc);
-    }
-    AndroidBitmap_unlockPixels(env, bitmap);
-}
diff --git a/jni/jni_egl_fence.cpp b/jni/jni_egl_fence.cpp
deleted file mode 100644
index cf15e2f..0000000
--- a/jni/jni_egl_fence.cpp
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * 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.
- */
-
-#include "jni_egl_fence.h"
-
-#include <android/log.h>
-#include <EGL/egl.h>
-#include <EGL/eglext.h>
-#include <string.h>
-
-#define  ALOGE(...)  __android_log_print(ANDROID_LOG_ERROR,"egl_fence",__VA_ARGS__)
-
-typedef EGLSyncKHR EGLAPIENTRY (*TypeEglCreateSyncKHR)(EGLDisplay dpy,
-    EGLenum type, const EGLint *attrib_list);
-typedef EGLBoolean EGLAPIENTRY (*TypeEglDestroySyncKHR)(EGLDisplay dpy,
-    EGLSyncKHR sync);
-typedef EGLint EGLAPIENTRY (*TypeEglClientWaitSyncKHR)(EGLDisplay dpy,
-    EGLSyncKHR sync, EGLint flags, EGLTimeKHR timeout);
-static TypeEglCreateSyncKHR FuncEglCreateSyncKHR = NULL;
-static TypeEglClientWaitSyncKHR FuncEglClientWaitSyncKHR = NULL;
-static TypeEglDestroySyncKHR FuncEglDestroySyncKHR = NULL;
-static bool initialized = false;
-static bool egl_khr_fence_sync_supported = false;
-
-bool IsEglKHRFenceSyncSupported() {
-  if (!initialized) {
-    EGLDisplay display = eglGetCurrentDisplay();
-    const char* eglExtensions = eglQueryString(eglGetCurrentDisplay(), EGL_EXTENSIONS);
-    if (eglExtensions && strstr(eglExtensions, "EGL_KHR_fence_sync")) {
-      FuncEglCreateSyncKHR = (TypeEglCreateSyncKHR) eglGetProcAddress("eglCreateSyncKHR");
-      FuncEglClientWaitSyncKHR = (TypeEglClientWaitSyncKHR) eglGetProcAddress("eglClientWaitSyncKHR");
-      FuncEglDestroySyncKHR = (TypeEglDestroySyncKHR) eglGetProcAddress("eglDestroySyncKHR");
-      if (FuncEglCreateSyncKHR != NULL && FuncEglClientWaitSyncKHR != NULL
-          && FuncEglDestroySyncKHR != NULL) {
-        egl_khr_fence_sync_supported = true;
-      }
-    }
-    initialized = true;
-  }
-  return egl_khr_fence_sync_supported;
-}
-
-void
-Java_com_android_gallery3d_photoeditor_FilterStack_nativeEglSetFenceAndWait(JNIEnv* env,
-                                                                          jobject thiz) {
-  if (!IsEglKHRFenceSyncSupported()) return;
-  EGLDisplay display = eglGetCurrentDisplay();
-
-  // Create a egl fence and wait for egl to return it.
-  // Additional reference on egl fence sync can be found in:
-  // http://www.khronos.org/registry/vg/extensions/KHR/EGL_KHR_fence_sync.txt
-  EGLSyncKHR fence = FuncEglCreateSyncKHR(display, EGL_SYNC_FENCE_KHR, NULL);
-  if (fence == EGL_NO_SYNC_KHR) {
-    return;
-  }
-
-  EGLint result = FuncEglClientWaitSyncKHR(display,
-                                       fence,
-                                       EGL_SYNC_FLUSH_COMMANDS_BIT_KHR,
-                                       EGL_FOREVER_KHR);
-  if (result == EGL_FALSE) {
-    ALOGE("EGL FENCE: error waiting for fence: %#x", eglGetError());
-  }
-  FuncEglDestroySyncKHR(display, fence);
-}
diff --git a/jni/jni_egl_fence.h b/jni/jni_egl_fence.h
deleted file mode 100644
index 6b2c20a..0000000
--- a/jni/jni_egl_fence.h
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * 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.
- */
-
-#ifndef COM_ANDROID_GALLERY3D_PHOTOEDITOR_JNI_EGL_FENSE_H
-#define COM_ANDROID_GALLERY3D_PHOTOEDITOR_JNI_EGL_FENSE_H
-
-#include <jni.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-JNIEXPORT void JNICALL
-Java_com_android_gallery3d_photoeditor_FilterStack_nativeEglSetFenceAndWait(JNIEnv* env,
-                                                                            jobject thiz);
-#ifdef __cplusplus
-}
-#endif
-
-#endif  /* COM_ANDROID_GALLERY3D_PHOTOEDITOR_JNI_EGL_FENSE_H */
diff --git a/jni_jpegstream/src/error_codes.h b/jni_jpegstream/src/error_codes.h
deleted file mode 100644
index be55a00..0000000
--- a/jni_jpegstream/src/error_codes.h
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Copyright (C) 2013 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.
- */
-
-#ifndef JPEG_ERROR_CODES_H_
-#define JPEG_ERROR_CODES_H_
-
-#define J_DONE                    -4
-#define J_EXCEPTION               -3
-#define J_ERROR_BAD_ARGS          -2
-#define J_ERROR_FATAL             -1
-#define J_SUCCESS                 0
-
-#endif // JPEG_ERROR_CODES_H_
diff --git a/jni_jpegstream/src/inputstream_wrapper.cpp b/jni_jpegstream/src/inputstream_wrapper.cpp
deleted file mode 100644
index 98721b0..0000000
--- a/jni_jpegstream/src/inputstream_wrapper.cpp
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * Copyright (C) 2013 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.
- */
-
-#include "inputstream_wrapper.h"
-#include "error_codes.h"
-
-jmethodID InputStreamWrapper::sReadID = NULL;
-jmethodID InputStreamWrapper::sSkipID = NULL;
-
-int32_t InputStreamWrapper::read(int32_t length, int32_t offset) {
-    if (offset < 0 || length < 0 || (offset + length) > getBufferSize()) {
-        return J_ERROR_BAD_ARGS;
-    }
-    int32_t bytesRead = 0;
-    mEnv->ReleaseByteArrayElements(mByteArray, mBytes, JNI_COMMIT);
-    mBytes = NULL;
-    if (mEnv->ExceptionCheck()) {
-        return J_EXCEPTION;
-    }
-    bytesRead = static_cast<int32_t>(mEnv->CallIntMethod(mStream, sReadID,
-            mByteArray, offset, length));
-    if (mEnv->ExceptionCheck()) {
-        return J_EXCEPTION;
-    }
-    mBytes = mEnv->GetByteArrayElements(mByteArray, NULL);
-    if (mBytes == NULL || mEnv->ExceptionCheck()) {
-        return J_EXCEPTION;
-    }
-    if (bytesRead == END_OF_STREAM) {
-        return J_DONE;
-    }
-    return bytesRead;
-}
-
-int64_t InputStreamWrapper::skip(int64_t count) {
-    int64_t bytesSkipped = 0;
-    bytesSkipped = static_cast<int64_t>(mEnv->CallLongMethod(mStream, sSkipID,
-            static_cast<jlong>(count)));
-    if (mEnv->ExceptionCheck() || bytesSkipped < 0) {
-        return J_EXCEPTION;
-    }
-    return bytesSkipped;
-}
-
-// Acts like a read call that returns the End Of Image marker for a JPEG file.
-int32_t InputStreamWrapper::forceReadEOI() {
-    mBytes[0] = (jbyte) 0xFF;
-    mBytes[1] = (jbyte) 0xD9;
-    return 2;
-}
-
-void InputStreamWrapper::setReadSkipMethodIDs(jmethodID readID,
-        jmethodID skipID) {
-    sReadID = readID;
-    sSkipID = skipID;
-}
diff --git a/jni_jpegstream/src/inputstream_wrapper.h b/jni_jpegstream/src/inputstream_wrapper.h
deleted file mode 100644
index ed9942b..0000000
--- a/jni_jpegstream/src/inputstream_wrapper.h
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright (C) 2013 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.
- */
-
-#ifndef INPUTSTREAM_WRAPPER_H_
-#define INPUTSTREAM_WRAPPER_H_
-
-#include "jni_defines.h"
-#include "stream_wrapper.h"
-
-#include <stdint.h>
-
-class InputStreamWrapper : public StreamWrapper {
-public:
-    virtual int32_t read(int32_t length, int32_t offset);
-    virtual int64_t skip(int64_t count);
-    virtual int32_t forceReadEOI();
-
-    // Call this in JNI_OnLoad to cache read/skip method IDs
-    static void setReadSkipMethodIDs(jmethodID readID, jmethodID skipID);
-protected:
-    static jmethodID sReadID;
-    static jmethodID sSkipID;
-};
-
-#endif // INPUTSTREAM_WRAPPER_H_
diff --git a/jni_jpegstream/src/jerr_hook.cpp b/jni_jpegstream/src/jerr_hook.cpp
deleted file mode 100644
index f8f864f..0000000
--- a/jni_jpegstream/src/jerr_hook.cpp
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Copyright (C) 2013 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.
- */
-
-
-#include "jerr_hook.h"
-#include "jni_defines.h"
-
-/**
- * Replaces libjpeg's error_exit function, returns control to
- * the point
- */
-void ErrExit(j_common_ptr cinfo) {
-    ErrManager* mgr = reinterpret_cast<ErrManager*>(cinfo->err);
-    (*cinfo->err->output_message) (cinfo);
-    // Returns control to error handling in jpeg_writer
-    longjmp(mgr->setjmp_buf, 1);
-}
-
-/**
- * Replaces libjpeg's output_message function, writes message
- * to logcat's error log.
- */
-void ErrOutput(j_common_ptr cinfo) {
-    ErrManager* mgr = reinterpret_cast<ErrManager*>(cinfo->err);
-    char buf[JMSG_LENGTH_MAX];
-    (*cinfo->err->format_message) (cinfo, buf);
-    buf[JMSG_LENGTH_MAX - 1] = '\0';  // Force null terminator
-    // Output error message in ndk logcat.
-    LOGE("%s\n", buf);
-}
-
-void SetupErrMgr(j_common_ptr cinfo, ErrManager* errMgr) {
-    jpeg_std_error(&(errMgr->mgr));
-    errMgr->mgr.error_exit = ErrExit;
-    errMgr->mgr.output_message = ErrOutput;
-    cinfo->err = reinterpret_cast<struct jpeg_error_mgr*>(errMgr);
-}
-
-
diff --git a/jni_jpegstream/src/jerr_hook.h b/jni_jpegstream/src/jerr_hook.h
deleted file mode 100644
index f2ba7cd..0000000
--- a/jni_jpegstream/src/jerr_hook.h
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Copyright (C) 2013 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.
- */
-
-#ifndef JERR_HOOK_H_
-#define JERR_HOOK_H_
-
-extern "C" {
-#include "jinclude.h"
-#include "jpeglib.h"
-#include "jerror.h"
-}
-
-#include <setjmp.h>
-
-/**
- * ErrManager replaces libjpeg's default error handling with
- * the following behavior:
- * - libjpeg function calls return to the position set by
- *   setjmp for error cleanup.
- * - libjpeg error and warning messages are printed to
- *   logcat's error output.
- */
-typedef struct {
-    struct jpeg_error_mgr mgr;
-    jmp_buf setjmp_buf;
-} ErrManager;
-
-void SetupErrMgr(j_common_ptr cinfo, ErrManager* errMgr);
-
-#endif // JERR_HOOK_H_
diff --git a/jni_jpegstream/src/jni_defines.h b/jni_jpegstream/src/jni_defines.h
deleted file mode 100644
index 8c9bd04..0000000
--- a/jni_jpegstream/src/jni_defines.h
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright (C) 2013 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.
- */
-
-#ifndef JNIDEFINES_H
-#define JNIDEFINES_H
-
-
-#include <jni.h>
-#include <string.h>
-#include <android/log.h>
-
-#define LOGV(msg...) __android_log_print(ANDROID_LOG_VERBOSE, "Native_JPEGStream", msg)
-#define LOGE(msg...) __android_log_print(ANDROID_LOG_ERROR, "Native_JPEGStream", msg)
-#define LOGW(msg...) __android_log_print(ANDROID_LOG_WARN, "Native_JPEGStream", msg)
-
-#endif // JNIDEFINES_H
diff --git a/jni_jpegstream/src/jpeg_config.h b/jni_jpegstream/src/jpeg_config.h
deleted file mode 100644
index a997552..0000000
--- a/jni_jpegstream/src/jpeg_config.h
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright (C) 2013 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.
- */
-
-#ifndef JPEG_CONFIG_H_
-#define JPEG_CONFIG_H_
-namespace Jpeg_Config {
-
-// Pixel format
-enum Format {
-    FORMAT_GRAYSCALE = 0x001, // 1 byte/pixel
-    FORMAT_RGB = 0x003, // 3 bytes/pixel RGBRGBRGBRGB...
-    FORMAT_RGBA = 0x004, // 4 bytes/pixel RGBARGBARGBARGBA...
-    FORMAT_ABGR = 0x104 // 4 bytes/pixel ABGRABGRABGR...
-};
-
-} // end namespace Jpeg_Config
-
-#endif // JPEG_CONFIG_H_
diff --git a/jni_jpegstream/src/jpeg_hook.cpp b/jni_jpegstream/src/jpeg_hook.cpp
deleted file mode 100644
index cca54e4..0000000
--- a/jni_jpegstream/src/jpeg_hook.cpp
+++ /dev/null
@@ -1,198 +0,0 @@
-/*
- * Copyright (C) 2013 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.
- */
-
-#include "error_codes.h"
-#include "jni_defines.h"
-#include "jpeg_hook.h"
-
-#include <stddef.h>
-#include <string.h>
-
-void Mgr_init_destination_fcn(j_compress_ptr cinfo) {
-    DestManager *dst = reinterpret_cast<DestManager*>(cinfo->dest);
-    dst->mgr.next_output_byte = reinterpret_cast<JOCTET*>(dst->outStream->getBufferPtr());
-    dst->mgr.free_in_buffer = dst->outStream->getBufferSize();
-}
-
-boolean Mgr_empty_output_buffer_fcn(j_compress_ptr cinfo) {
-    DestManager *dst = reinterpret_cast<DestManager*>(cinfo->dest);
-    int32_t len = dst->outStream->getBufferSize();
-    if (dst->outStream->write(len, 0) != J_SUCCESS) {
-        ERREXIT(cinfo, JERR_FILE_WRITE);
-    }
-    dst->mgr.next_output_byte = reinterpret_cast<JOCTET*>(dst->outStream->getBufferPtr());
-    dst->mgr.free_in_buffer = len;
-    return TRUE;
-}
-
-void Mgr_term_destination_fcn(j_compress_ptr cinfo) {
-    DestManager *dst = reinterpret_cast<DestManager*>(cinfo->dest);
-    int32_t remaining = dst->outStream->getBufferSize() - dst->mgr.free_in_buffer;
-    if (dst->outStream->write(remaining, 0) != J_SUCCESS) {
-        ERREXIT(cinfo, JERR_FILE_WRITE);
-    }
-}
-
-int32_t MakeDst(j_compress_ptr cinfo, JNIEnv *env, jobject outStream) {
-    if (cinfo->dest != NULL) {
-        LOGE("DestManager already exists, cannot allocate!");
-        return J_ERROR_FATAL;
-    } else {
-        size_t size = sizeof(DestManager);
-        cinfo->dest = (struct jpeg_destination_mgr *) (*cinfo->mem->alloc_small)
-                ((j_common_ptr) cinfo, JPOOL_PERMANENT, size);
-        if (cinfo->dest == NULL) {
-            LOGE("Could not allocate memory for DestManager.");
-            return J_ERROR_FATAL;
-        }
-        memset(cinfo->dest, '0', size);
-    }
-    DestManager *d = reinterpret_cast<DestManager*>(cinfo->dest);
-    d->mgr.init_destination = Mgr_init_destination_fcn;
-    d->mgr.empty_output_buffer = Mgr_empty_output_buffer_fcn;
-    d->mgr.term_destination = Mgr_term_destination_fcn;
-    d->outStream = new OutputStreamWrapper();
-    if(d->outStream->init(env, outStream)) {
-        return J_SUCCESS;
-    }
-    return J_ERROR_FATAL;
-}
-
-void UpdateDstEnv(j_compress_ptr cinfo, JNIEnv* env) {
-    DestManager* d = reinterpret_cast<DestManager*>(cinfo->dest);
-    d->outStream->updateEnv(env);
-}
-
-void CleanDst(j_compress_ptr cinfo) {
-    if (cinfo != NULL && cinfo->dest != NULL) {
-        DestManager *d = reinterpret_cast<DestManager*>(cinfo->dest);
-        if (d->outStream != NULL) {
-            delete d->outStream;
-            d->outStream = NULL;
-        }
-    }
-}
-
-boolean Mgr_fill_input_buffer_fcn(j_decompress_ptr cinfo) {
-    SourceManager *src = reinterpret_cast<SourceManager*>(cinfo->src);
-    int32_t bytesRead = src->inStream->read(src->inStream->getBufferSize(), 0);
-    if (bytesRead == J_DONE) {
-        if (src->start_of_file == TRUE) {
-            ERREXIT(cinfo, JERR_INPUT_EMPTY);
-        }
-        WARNMS(cinfo, JWRN_JPEG_EOF);
-        bytesRead = src->inStream->forceReadEOI();
-    } else if (bytesRead < 0) {
-        ERREXIT(cinfo, JERR_FILE_READ);
-    } else if (bytesRead == 0) {
-        LOGW("read 0 bytes from InputStream.");
-    }
-    src->mgr.next_input_byte = reinterpret_cast<JOCTET*>(src->inStream->getBufferPtr());
-    src->mgr.bytes_in_buffer = bytesRead;
-    if (bytesRead != 0) {
-        src->start_of_file = FALSE;
-    }
-    return TRUE;
-}
-
-void Mgr_init_source_fcn(j_decompress_ptr cinfo) {
-    SourceManager *s = reinterpret_cast<SourceManager*>(cinfo->src);
-    s->start_of_file = TRUE;
-    Mgr_fill_input_buffer_fcn(cinfo);
-}
-
-void Mgr_skip_input_data_fcn(j_decompress_ptr cinfo, long num_bytes) {
-    // Cannot skip negative or 0 bytes.
-    if (num_bytes <= 0) {
-        LOGW("skipping 0 bytes in InputStream");
-        return;
-    }
-    SourceManager *src = reinterpret_cast<SourceManager*>(cinfo->src);
-    if (src->mgr.bytes_in_buffer >= num_bytes) {
-        src->mgr.bytes_in_buffer -= num_bytes;
-        src->mgr.next_input_byte += num_bytes;
-    } else {
-        // if skipping more bytes than remain in buffer, set skip_bytes
-        int64_t skip = num_bytes - src->mgr.bytes_in_buffer;
-        src->mgr.next_input_byte += src->mgr.bytes_in_buffer;
-        src->mgr.bytes_in_buffer = 0;
-        int64_t actual = src->inStream->skip(skip);
-        if (actual < 0) {
-            ERREXIT(cinfo, JERR_FILE_READ);
-        }
-        skip -= actual;
-        while (skip > 0) {
-            actual = src->inStream->skip(skip);
-            if (actual < 0) {
-                ERREXIT(cinfo, JERR_FILE_READ);
-            }
-            skip -= actual;
-            if (actual == 0) {
-                // Multiple zero byte skips, likely EOF
-                WARNMS(cinfo, JWRN_JPEG_EOF);
-                return;
-            }
-        }
-    }
-}
-
-void Mgr_term_source_fcn(j_decompress_ptr cinfo) {
-    //noop
-}
-
-int32_t MakeSrc(j_decompress_ptr cinfo, JNIEnv *env, jobject inStream){
-    if (cinfo->src != NULL) {
-        LOGE("SourceManager already exists, cannot allocate!");
-        return J_ERROR_FATAL;
-    } else {
-        size_t size = sizeof(SourceManager);
-        cinfo->src = (struct jpeg_source_mgr *) (*cinfo->mem->alloc_small)
-                ((j_common_ptr) cinfo, JPOOL_PERMANENT, size);
-        if (cinfo->src == NULL) {
-            // Could not allocate memory.
-            LOGE("Could not allocate memory for SourceManager.");
-            return J_ERROR_FATAL;
-        }
-        memset(cinfo->src, '0', size);
-    }
-    SourceManager *s = reinterpret_cast<SourceManager*>(cinfo->src);
-    s->start_of_file = TRUE;
-    s->mgr.init_source = Mgr_init_source_fcn;
-    s->mgr.fill_input_buffer = Mgr_fill_input_buffer_fcn;
-    s->mgr.skip_input_data = Mgr_skip_input_data_fcn;
-    s->mgr.resync_to_restart = jpeg_resync_to_restart;  // use default restart
-    s->mgr.term_source = Mgr_term_source_fcn;
-    s->inStream = new InputStreamWrapper();
-    if(s->inStream->init(env, inStream)) {
-        return J_SUCCESS;
-    }
-    return J_ERROR_FATAL;
-}
-
-void UpdateSrcEnv(j_decompress_ptr cinfo, JNIEnv* env) {
-    SourceManager* s = reinterpret_cast<SourceManager*>(cinfo->src);
-    s->inStream->updateEnv(env);
-}
-
-void CleanSrc(j_decompress_ptr cinfo) {
-    if (cinfo != NULL && cinfo->src != NULL) {
-        SourceManager *s = reinterpret_cast<SourceManager*>(cinfo->src);
-        if (s->inStream != NULL) {
-            delete s->inStream;
-            s->inStream = NULL;
-        }
-    }
-}
diff --git a/jni_jpegstream/src/jpeg_hook.h b/jni_jpegstream/src/jpeg_hook.h
deleted file mode 100644
index b02bb34..0000000
--- a/jni_jpegstream/src/jpeg_hook.h
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * Copyright (C) 2013 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.
- */
-
-#ifndef LIBJPEG_HOOK_H_
-#define LIBJPEG_HOOK_H_
-
-extern "C" {
-#include "jinclude.h"
-#include "jpeglib.h"
-#include "jerror.h"
-}
-
-#include "inputstream_wrapper.h"
-#include "outputstream_wrapper.h"
-
-#include <stdint.h>
-
-/**
- * DestManager holds the libjpeg destination manager struct and
- * a holder with a java OutputStream.
- */
-typedef struct {
-    struct jpeg_destination_mgr mgr;
-    OutputStreamWrapper *outStream;
-} DestManager;
-
-// Initializes the DestManager struct, sets up the jni refs
-int32_t MakeDst(j_compress_ptr cinfo, JNIEnv *env, jobject outStream);
-
-/**
- * Updates the jni env pointer. This should be called in the beginning of any
- * JNI method in jpegstream.cpp before CleanDst or any of the libjpeg functions
- * that can trigger a call to an OutputStreamWrapper method.
- */
-void UpdateDstEnv(j_compress_ptr cinfo, JNIEnv* env);
-
-// Cleans the jni refs.  To wipe the compress object call jpeg_destroy_compress
-void CleanDst(j_compress_ptr cinfo);
-
-/**
- * SourceManager holds the libjpeg source manager struct and a
- * holder with a java InputStream.
- */
-typedef struct {
-    struct jpeg_source_mgr mgr;
-    boolean start_of_file;
-    InputStreamWrapper *inStream;
-} SourceManager;
-
-// Initializes the SourceManager struct, sets up the jni refs
-int32_t MakeSrc(j_decompress_ptr cinfo, JNIEnv *env, jobject inStream);
-
-/**
- * Updates the jni env pointer. This should be called in the beginning of any
- * JNI method in jpegstream.cpp before CleanSrc or any of the libjpeg functions
- * that can trigger a call to an InputStreamWrapper method.
- */
-void UpdateSrcEnv(j_decompress_ptr cinfo, JNIEnv* env);
-
-// Cleans the jni refs.  To wipe the decompress object, call jpeg_destroy_decompress
-void CleanSrc(j_decompress_ptr cinfo);
-
-#endif // LIBJPEG_HOOK_H_
diff --git a/jni_jpegstream/src/jpeg_reader.cpp b/jni_jpegstream/src/jpeg_reader.cpp
deleted file mode 100644
index 4726b64..0000000
--- a/jni_jpegstream/src/jpeg_reader.cpp
+++ /dev/null
@@ -1,254 +0,0 @@
-/*
- * Copyright (C) 2013 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.
- */
-
-#include "jpeg_reader.h"
-#include "error_codes.h"
-#include "jpeg_hook.h"
-
-#include <setjmp.h>
-
-JpegReader::JpegReader() :
-                mInfo(),
-                mErrorManager(),
-                mScanlineBuf(NULL),
-                mScanlineIter(NULL),
-                mScanlineBuflen(0),
-                mScanlineUnformattedBuflen(0),
-                mScanlineBytesRemaining(0),
-                mFormat(),
-                mFinished(false),
-                mSetup(false) {}
-
-JpegReader::~JpegReader() {
-    if (reset() != J_SUCCESS) {
-        LOGE("Failed to destroy compress object, JpegReader may leak memory.");
-    }
-}
-
-int32_t JpegReader::setup(JNIEnv *env, jobject in, int32_t* width, int32_t* height,
-        Jpeg_Config::Format format) {
-    if (mFinished || mSetup) {
-        return J_ERROR_FATAL;
-    }
-    if (env->ExceptionCheck()) {
-        return J_EXCEPTION;
-    }
-
-    // Setup error handler
-    SetupErrMgr(reinterpret_cast<j_common_ptr>(&mInfo), &mErrorManager);
-    // Set jump address for error handling
-    if (setjmp(mErrorManager.setjmp_buf)) {
-        return J_ERROR_FATAL;
-    }
-
-    // Call libjpeg setup
-    jpeg_create_decompress(&mInfo);
-
-    // Setup our data source object, this allocates java global references
-    int32_t flags = MakeSrc(&mInfo, env, in);
-    if (flags != J_SUCCESS) {
-        LOGE("Failed to make source with error code: %d ", flags);
-        return flags;
-    }
-
-    // Reads jpeg file header
-    jpeg_read_header(&mInfo, TRUE);
-    jpeg_calc_output_dimensions(&mInfo);
-
-    const int components = (static_cast<int>(format) & 0xff);
-
-    // Do setup for input format
-    switch (components) {
-    case 1:
-        mInfo.out_color_space = JCS_GRAYSCALE;
-        mScanlineUnformattedBuflen = mInfo.output_width;
-        break;
-    case 3:
-    case 4:
-        mScanlineUnformattedBuflen = mInfo.output_width * components;
-        if (mInfo.jpeg_color_space == JCS_CMYK
-                || mInfo.jpeg_color_space == JCS_YCCK) {
-            // Always use cmyk for output in a 4 channel jpeg.
-            // libjpeg has a builtin cmyk->rgb decoder.
-            mScanlineUnformattedBuflen = mInfo.output_width * 4;
-            mInfo.out_color_space = JCS_CMYK;
-        } else {
-            mInfo.out_color_space = JCS_RGB;
-        }
-        break;
-    default:
-        return J_ERROR_BAD_ARGS;
-    }
-
-    mScanlineBuflen = mInfo.output_width * components;
-    mScanlineBytesRemaining = mScanlineBuflen;
-    mScanlineBuf = (JSAMPLE *) (mInfo.mem->alloc_small)(
-            reinterpret_cast<j_common_ptr>(&mInfo), JPOOL_PERMANENT,
-            mScanlineUnformattedBuflen * sizeof(JSAMPLE));
-    mScanlineIter = mScanlineBuf;
-    jpeg_start_decompress(&mInfo);
-
-    // Output image dimensions
-    if (width != NULL) {
-        *width = mInfo.output_width;
-    }
-    if (height != NULL) {
-        *height = mInfo.output_height;
-    }
-
-    mFormat = format;
-    mSetup = true;
-    return J_SUCCESS;
-}
-
-int32_t JpegReader::read(int8_t* bytes, int32_t offset, int32_t count) {
-    if (!mSetup) {
-        return J_ERROR_FATAL;
-    }
-    if (mFinished) {
-        return J_DONE;
-    }
-    // Set jump address for error handling
-    if (setjmp(mErrorManager.setjmp_buf)) {
-        return J_ERROR_FATAL;
-    }
-    if (count <= 0) {
-        return J_ERROR_BAD_ARGS;
-    }
-    int32_t total_length = count;
-    while (mInfo.output_scanline < mInfo.output_height) {
-        if (count < mScanlineBytesRemaining) {
-            // read partial scanline and return
-            if (bytes != NULL) {
-                // Treat NULL bytes as a skip
-                memcpy((void*) (bytes + offset), (void*) mScanlineIter,
-                        count * sizeof(int8_t));
-            }
-            mScanlineBytesRemaining -= count;
-            mScanlineIter += count;
-            return total_length;
-        } else if (count > 0) {
-            // read full scanline
-            if (bytes != NULL) {
-                // Treat NULL bytes as a skip
-                memcpy((void*) (bytes + offset), (void*) mScanlineIter,
-                        mScanlineBytesRemaining * sizeof(int8_t));
-                bytes += mScanlineBytesRemaining;
-            }
-            count -= mScanlineBytesRemaining;
-            mScanlineBytesRemaining = 0;
-        }
-        // Scanline buffer exhausted, read next scanline
-        if (jpeg_read_scanlines(&mInfo, &mScanlineBuf, 1) != 1) {
-            // Always read full scanline, no IO suspension
-            return J_ERROR_FATAL;
-        }
-        // Do in-place pixel formatting
-        formatPixels(static_cast<uint8_t*>(mScanlineBuf),
-                mScanlineUnformattedBuflen);
-
-        // Reset iterators
-        mScanlineIter = mScanlineBuf;
-        mScanlineBytesRemaining = mScanlineBuflen;
-    }
-
-    // Read all of the scanlines
-    jpeg_finish_decompress(&mInfo);
-    mFinished = true;
-    return total_length - count;
-}
-
-void JpegReader::updateEnv(JNIEnv *env) {
-    UpdateSrcEnv(&mInfo, env);
-}
-
-// Does in-place pixel formatting
-void JpegReader::formatPixels(uint8_t* buf, int32_t len) {
-    uint8_t *iter = buf;
-
-    // Do cmyk->rgb conversion if necessary
-    switch (mInfo.out_color_space) {
-    case JCS_CMYK:
-        // Convert CMYK to RGB
-        int r, g, b, c, m, y, k;
-        for (int i = 0; i < len; i += 4) {
-            c = buf[i + 0];
-            m = buf[i + 1];
-            y = buf[i + 2];
-            k = buf[i + 3];
-            // Handle fmt for weird photoshop markers
-            if (mInfo.saw_Adobe_marker) {
-                r = (k * c) / 255;
-                g = (k * m) / 255;
-                b = (k * y) / 255;
-            } else {
-                r = (255 - k) * (255 - c) / 255;
-                g = (255 - k) * (255 - m) / 255;
-                b = (255 - k) * (255 - y) / 255;
-            }
-            *iter++ = r;
-            *iter++ = g;
-            *iter++ = b;
-        }
-        break;
-    case JCS_RGB:
-        iter += (len * 3 / 4);
-        break;
-    case JCS_GRAYSCALE:
-    default:
-        return;
-    }
-
-    // Do endianness and alpha for output format
-    if (mFormat == Jpeg_Config::FORMAT_RGBA) {
-        // Set alphas to 255
-        uint8_t* end = buf + len - 1;
-        for (int i = len - 1; i >= 0; i -= 4) {
-            buf[i] = 255;
-            buf[i - 1] = *--iter;
-            buf[i - 2] = *--iter;
-            buf[i - 3] = *--iter;
-        }
-    } else if (mFormat == Jpeg_Config::FORMAT_ABGR) {
-        // Reverse endianness and set alphas to 255
-        uint8_t* end = buf + len - 1;
-        int r, g, b;
-        for (int i = len - 1; i >= 0; i -= 4) {
-            b = *--iter;
-            g = *--iter;
-            r = *--iter;
-            buf[i] = r;
-            buf[i - 1] = g;
-            buf[i - 2] = b;
-            buf[i - 3] = 255;
-        }
-    }
-}
-
-int32_t JpegReader::reset() {
-    // Set jump address for error handling
-    if (setjmp(mErrorManager.setjmp_buf)) {
-        return J_ERROR_FATAL;
-    }
-    // Clean up global java references
-    CleanSrc(&mInfo);
-    // Wipe decompress struct, free memory pools
-    jpeg_destroy_decompress(&mInfo);
-    mFinished = false;
-    mSetup = false;
-    return J_SUCCESS;
-}
-
diff --git a/jni_jpegstream/src/jpeg_reader.h b/jni_jpegstream/src/jpeg_reader.h
deleted file mode 100644
index afde27b..0000000
--- a/jni_jpegstream/src/jpeg_reader.h
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- * Copyright (C) 2013 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.
- */
-#ifndef JPEG_READER_H_
-#define JPEG_READER_H_
-
-#include "jerr_hook.h"
-#include "jni_defines.h"
-#include "jpeg_config.h"
-
-#include <stdint.h>
-
-/**
- * JpegReader wraps libjpeg's decompression functionality and a
- * java InputStream object.  Read calls return data from the
- * InputStream that has been decompressed.
- */
-class JpegReader {
-public:
-    JpegReader();
-    ~JpegReader();
-
-    /**
-     * Call setup with a valid InputStream reference and pixel format.
-     * If this method is successful, the contents of width and height will
-     * be set to the dimensions of the bitmap to be read.
-     *
-     * ***This method will result in the jpeg file header being read
-     * from the InputStream***
-     *
-     * Returns J_SUCCESS on success or a negative error code.
-     */
-    int32_t setup(JNIEnv *env, jobject in, int32_t* width, int32_t* height,
-            Jpeg_Config::Format format);
-
-    /**
-     * Decompresses bytes from the InputStream and writes at most count
-     * bytes into the buffer, bytes, starting at some offset.  Passing a
-     * NULL as the bytes pointer effectively skips those bytes.
-     *
-     * ***This method will result in bytes being read from the InputStream***
-     *
-     * Returns the number of bytes written into the input buffer or a
-     * negative error code.
-     */
-    int32_t read(int8_t * bytes, int32_t offset, int32_t count);
-
-    /**
-     * Updates the environment pointer.  Call this before read or reset
-     * in any jni function call.
-     */
-    void updateEnv(JNIEnv *env);
-
-    /**
-     * Frees any java global references held by the JpegReader, destroys
-     * the decompress structure, and frees allocations in libjpeg's pools.
-     */
-    int32_t reset();
-
-private:
-    void formatPixels(uint8_t* buf, int32_t len);
-    struct jpeg_decompress_struct mInfo;
-    ErrManager mErrorManager;
-
-    JSAMPLE* mScanlineBuf;
-    JSAMPLE* mScanlineIter;
-    int32_t mScanlineBuflen;
-    int32_t mScanlineUnformattedBuflen;
-    int32_t mScanlineBytesRemaining;
-
-    Jpeg_Config::Format mFormat;
-    bool mFinished;
-    bool mSetup;
-};
-
-#endif // JPEG_READER_H_
diff --git a/jni_jpegstream/src/jpeg_writer.cpp b/jni_jpegstream/src/jpeg_writer.cpp
deleted file mode 100644
index 4f78917..0000000
--- a/jni_jpegstream/src/jpeg_writer.cpp
+++ /dev/null
@@ -1,218 +0,0 @@
-/*
- * Copyright (C) 2013 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.
- */
-
-#include "jpeg_hook.h"
-#include "jpeg_writer.h"
-#include "error_codes.h"
-
-#include <setjmp.h>
-#include <assert.h>
-
-JpegWriter::JpegWriter() : mInfo(),
-                           mErrorManager(),
-                           mScanlineBuf(NULL),
-                           mScanlineIter(NULL),
-                           mScanlineBuflen(0),
-                           mScanlineBytesRemaining(0),
-                           mFormat(),
-                           mFinished(false),
-                           mSetup(false) {}
-
-JpegWriter::~JpegWriter() {
-    if (reset() != J_SUCCESS) {
-        LOGE("Failed to destroy compress object, may leak memory.");
-    }
-}
-
-const int32_t JpegWriter::DEFAULT_X_DENSITY = 300;
-const int32_t JpegWriter::DEFAULT_Y_DENSITY = 300;
-const int32_t JpegWriter::DEFAULT_DENSITY_UNIT = 1;
-
-int32_t JpegWriter::setup(JNIEnv *env, jobject out, int32_t width, int32_t height,
-        Jpeg_Config::Format format, int32_t quality) {
-    if (mFinished || mSetup) {
-        return J_ERROR_FATAL;
-    }
-    if (env->ExceptionCheck()) {
-        return J_EXCEPTION;
-    }
-    if (height <= 0 || width <= 0 || quality <= 0 || quality > 100) {
-        return J_ERROR_BAD_ARGS;
-    }
-    // Setup error handler
-    SetupErrMgr(reinterpret_cast<j_common_ptr>(&mInfo), &mErrorManager);
-
-    // Set jump address for error handling
-    if (setjmp(mErrorManager.setjmp_buf)) {
-        return J_ERROR_FATAL;
-    }
-
-    // Setup cinfo struct
-    jpeg_create_compress(&mInfo);
-
-    // Setup global java refs
-    int32_t flags = MakeDst(&mInfo, env, out);
-    if (flags != J_SUCCESS) {
-        return flags;
-    }
-
-    // Initialize width, height, and color space
-    mInfo.image_width = width;
-    mInfo.image_height = height;
-    const int components = (static_cast<int>(format) & 0xff);
-    switch (components) {
-    case 1:
-        mInfo.input_components = 1;
-        mInfo.in_color_space = JCS_GRAYSCALE;
-        break;
-    case 3:
-    case 4:
-        mInfo.input_components = 3;
-        mInfo.in_color_space = JCS_RGB;
-        break;
-    default:
-        return J_ERROR_BAD_ARGS;
-    }
-
-    // Set defaults
-    jpeg_set_defaults(&mInfo);
-    mInfo.density_unit = DEFAULT_DENSITY_UNIT; // JFIF code for pixel size units:
-                             // 1 = in, 2 = cm
-    mInfo.X_density = DEFAULT_X_DENSITY; // Horizontal pixel density
-    mInfo.Y_density = DEFAULT_Y_DENSITY; // Vertical pixel density
-
-    // Set compress quality
-    jpeg_set_quality(&mInfo, quality, TRUE);
-
-    mFormat = format;
-
-    // Setup scanline buffer
-    mScanlineBuflen = width * components;
-    mScanlineBytesRemaining = mScanlineBuflen;
-    mScanlineBuf = (JSAMPLE *) (mInfo.mem->alloc_small)(
-            reinterpret_cast<j_common_ptr>(&mInfo), JPOOL_PERMANENT,
-            mScanlineBuflen * sizeof(JSAMPLE));
-    mScanlineIter = mScanlineBuf;
-
-    // Start compression
-    jpeg_start_compress(&mInfo, TRUE);
-    mSetup = true;
-    return J_SUCCESS;
-}
-
-int32_t JpegWriter::write(int8_t* bytes, int32_t length) {
-    if (!mSetup) {
-        return J_ERROR_FATAL;
-    }
-    if (mFinished) {
-        return 0;
-    }
-    // Set jump address for error handling
-    if (setjmp(mErrorManager.setjmp_buf)) {
-        return J_ERROR_FATAL;
-    }
-    if (length < 0 || bytes == NULL) {
-        return J_ERROR_BAD_ARGS;
-    }
-
-    int32_t total_length = length;
-    JSAMPROW row_pointer[1];
-    while (mInfo.next_scanline < mInfo.image_height) {
-        if (length < mScanlineBytesRemaining) {
-            // read partial scanline and return
-            memcpy((void*) mScanlineIter, (void*) bytes,
-                    length * sizeof(int8_t));
-            mScanlineBytesRemaining -= length;
-            mScanlineIter += length;
-            return total_length;
-        } else if (length > 0) {
-            // read full scanline
-            memcpy((void*) mScanlineIter, (void*) bytes,
-                    mScanlineBytesRemaining * sizeof(int8_t));
-            bytes += mScanlineBytesRemaining;
-            length -= mScanlineBytesRemaining;
-            mScanlineBytesRemaining = 0;
-        }
-        // Do in-place pixel formatting
-        formatPixels(static_cast<uint8_t*>(mScanlineBuf), mScanlineBuflen);
-        row_pointer[0] = mScanlineBuf;
-        // Do compression
-        if (jpeg_write_scanlines(&mInfo, row_pointer, 1) != 1) {
-            return J_ERROR_FATAL;
-        }
-        // Reset scanline buffer
-        mScanlineBytesRemaining = mScanlineBuflen;
-        mScanlineIter = mScanlineBuf;
-    }
-    jpeg_finish_compress(&mInfo);
-    mFinished = true;
-    return total_length - length;
-}
-
-// Does in-place pixel formatting
-void JpegWriter::formatPixels(uint8_t* buf, int32_t len) {
-    //  Assumes len is a multiple of 4 for RGBA and ABGR pixels.
-    assert((len % 4) == 0);
-    uint8_t* d = buf;
-    switch (mFormat) {
-    case Jpeg_Config::FORMAT_RGBA: {
-        // Strips alphas
-        for (int i = 0; i < len / 4; ++i, buf += 4) {
-            *d++ = buf[0];
-            *d++ = buf[1];
-            *d++ = buf[2];
-        }
-        break;
-    }
-    case Jpeg_Config::FORMAT_ABGR: {
-        // Strips alphas and flips endianness
-        if (len / 4 >= 1) {
-            *d++ = buf[3];
-            uint8_t tmp = *d;
-            *d++ = buf[2];
-            *d++ = tmp;
-        }
-        for (int i = 1; i < len / 4; ++i, buf += 4) {
-            *d++ = buf[3];
-            *d++ = buf[2];
-            *d++ = buf[1];
-        }
-        break;
-    }
-    default: {
-        // Do nothing
-        break;
-    }
-    }
-}
-
-void JpegWriter::updateEnv(JNIEnv *env) {
-    UpdateDstEnv(&mInfo, env);
-}
-
-int32_t JpegWriter::reset() {
-    // Set jump address for error handling
-    if (setjmp(mErrorManager.setjmp_buf)) {
-        return J_ERROR_FATAL;
-    }
-    // Clean up global java references
-    CleanDst(&mInfo);
-    // Wipe compress struct, free memory pools
-    jpeg_destroy_compress(&mInfo);
-    mFinished = false;
-    mSetup = false;
-    return J_SUCCESS;
-}
diff --git a/jni_jpegstream/src/jpeg_writer.h b/jni_jpegstream/src/jpeg_writer.h
deleted file mode 100644
index bd9a42d..0000000
--- a/jni_jpegstream/src/jpeg_writer.h
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * Copyright (C) 2013 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.
- */
-#ifndef JPEG_WRITER_H_
-#define JPEG_WRITER_H_
-
-#include "jerr_hook.h"
-#include "jni_defines.h"
-#include "jpeg_config.h"
-
-#include <stdint.h>
-
-/**
- * JpegWriter wraps libjpeg's compression functionality and a
- * java OutputStream object.  Write calls result in input data
- * being compressed and written to the OuputStream.
- */
-class JpegWriter {
-public:
-    JpegWriter();
-    ~JpegWriter();
-
-    /**
-     * Call setup with a valid OutputStream reference, bitmap height and
-     * width, pixel format, and compression quality in range (0, 100].
-     *
-     * Returns J_SUCCESS on success or a negative error code.
-     */
-    int32_t setup(JNIEnv *env, jobject out, int32_t width, int32_t height,
-            Jpeg_Config::Format format, int32_t quality);
-
-    /**
-     * Compresses bytes from the input buffer.
-     *
-     * ***This method will result in bytes being written to the OutputStream***
-     *
-     * Returns J_SUCCESS on success or a negative error code.
-     */
-    int32_t write(int8_t* bytes, int32_t length);
-
-    /**
-     * Updates the environment pointer.  Call this before write or reset
-     * in any jni function call.
-     */
-    void updateEnv(JNIEnv *env);
-
-    /**
-     * Frees any java global references held by the JpegWriter, destroys
-     * the compress structure, and frees allocations in libjpeg's pools.
-     */
-    int32_t reset();
-
-    static const int32_t DEFAULT_X_DENSITY;
-    static const int32_t DEFAULT_Y_DENSITY;
-    static const int32_t DEFAULT_DENSITY_UNIT;
-private:
-    void formatPixels(uint8_t* buf, int32_t len);
-    struct jpeg_compress_struct mInfo;
-    ErrManager mErrorManager;
-
-    JSAMPLE* mScanlineBuf;
-    JSAMPLE* mScanlineIter;
-    int32_t mScanlineBuflen;
-    int32_t mScanlineBytesRemaining;
-
-    Jpeg_Config::Format mFormat;
-    bool mFinished;
-    bool mSetup;
-};
-
-#endif // JPEG_WRITER_H_
diff --git a/jni_jpegstream/src/jpegstream.cpp b/jni_jpegstream/src/jpegstream.cpp
deleted file mode 100644
index 3b9a683..0000000
--- a/jni_jpegstream/src/jpegstream.cpp
+++ /dev/null
@@ -1,377 +0,0 @@
-/*
- * Copyright (C) 2013 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.
- */
-
-#include "error_codes.h"
-#include "jni_defines.h"
-#include "jpeg_writer.h"
-#include "jpeg_reader.h"
-#include "jpeg_config.h"
-#include "outputstream_wrapper.h"
-#include "inputstream_wrapper.h"
-
-#include <stdint.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-static jint OutputStream_setup(JNIEnv* env, jobject thiz, jobject out,
-        jint width, jint height, jint format, jint quality) {
-    // Get a reference to this object's class
-    jclass thisClass = env->GetObjectClass(thiz);
-    if (env->ExceptionCheck() || thisClass == NULL) {
-        return J_EXCEPTION;
-    }
-    // Get field for storing C pointer
-    jfieldID fidNumber = env->GetFieldID(thisClass, "JNIPointer", "J");
-    if (NULL == fidNumber || env->ExceptionCheck()) {
-        return J_EXCEPTION;
-    }
-
-    // Check size
-    if (width <= 0 || height <= 0) {
-        return J_ERROR_BAD_ARGS;
-    }
-    Jpeg_Config::Format fmt = static_cast<Jpeg_Config::Format>(format);
-    // Check format
-    switch (fmt) {
-    case Jpeg_Config::FORMAT_GRAYSCALE:
-    case Jpeg_Config::FORMAT_RGB:
-    case Jpeg_Config::FORMAT_RGBA:
-    case Jpeg_Config::FORMAT_ABGR:
-        break;
-    default:
-        return J_ERROR_BAD_ARGS;
-    }
-
-    uint32_t w = static_cast<uint32_t>(width);
-    uint32_t h = static_cast<uint32_t>(height);
-    int32_t q = static_cast<int32_t>(quality);
-    // Clamp quality to (0, 100]
-    q = (q > 100) ? 100 : ((q < 1) ? 1 : q);
-
-    JpegWriter* w_ptr = new JpegWriter();
-
-    // Do JpegWriter setup.
-    int32_t errorFlag = w_ptr->setup(env, out, w, h, fmt, q);
-    if (env->ExceptionCheck() || errorFlag != J_SUCCESS) {
-        delete w_ptr;
-        return errorFlag;
-    }
-
-    // Store C pointer for writer
-    env->SetLongField(thiz, fidNumber, reinterpret_cast<jlong>(w_ptr));
-    if (env->ExceptionCheck()) {
-        delete w_ptr;
-        return J_EXCEPTION;
-    }
-    return J_SUCCESS;
-}
-
-static jint InputStream_setup(JNIEnv* env, jobject thiz, jobject dimens,
-        jobject in, jint format) {
-    // Get a reference to this object's class
-    jclass thisClass = env->GetObjectClass(thiz);
-    if (env->ExceptionCheck() || thisClass == NULL) {
-        return J_EXCEPTION;
-    }
-    jmethodID setMethod = NULL;
-
-    // Get dimensions object setter method
-    if (dimens != NULL) {
-        jclass pointClass = env->GetObjectClass(dimens);
-        if (env->ExceptionCheck() || pointClass == NULL) {
-            return J_EXCEPTION;
-        }
-        setMethod = env->GetMethodID(pointClass, "set", "(II)V");
-        if (env->ExceptionCheck() || setMethod == NULL) {
-            return J_EXCEPTION;
-        }
-    }
-    // Get field for storing C pointer
-    jfieldID fidNumber = env->GetFieldID(thisClass, "JNIPointer", "J");
-    if (NULL == fidNumber || env->ExceptionCheck()) {
-        return J_EXCEPTION;
-    }
-    Jpeg_Config::Format fmt = static_cast<Jpeg_Config::Format>(format);
-    // Check format
-    switch (fmt) {
-    case Jpeg_Config::FORMAT_GRAYSCALE:
-    case Jpeg_Config::FORMAT_RGB:
-    case Jpeg_Config::FORMAT_RGBA:
-    case Jpeg_Config::FORMAT_ABGR:
-        break;
-    default:
-        return J_ERROR_BAD_ARGS;
-    }
-
-    JpegReader* r_ptr = new JpegReader();
-    int32_t w = 0, h = 0;
-    // Do JpegReader setup.
-    int32_t errorFlag = r_ptr->setup(env, in, &w, &h, fmt);
-    if (env->ExceptionCheck() || errorFlag != J_SUCCESS) {
-        delete r_ptr;
-        return errorFlag;
-    }
-
-    // Set dimensions to return
-    if (dimens != NULL) {
-        env->CallVoidMethod(dimens, setMethod, static_cast<jint>(w),
-                static_cast<jint>(h));
-        if (env->ExceptionCheck()) {
-            delete r_ptr;
-            return J_EXCEPTION;
-        }
-    }
-    // Store C pointer for reader
-    env->SetLongField(thiz, fidNumber, reinterpret_cast<jlong>(r_ptr));
-    if (env->ExceptionCheck()) {
-        delete r_ptr;
-        return J_EXCEPTION;
-    }
-    return J_SUCCESS;
-}
-
-static JpegWriter* getWPtr(JNIEnv* env, jobject thiz, jfieldID* fid) {
-    jclass thisClass = env->GetObjectClass(thiz);
-    if (env->ExceptionCheck() || thisClass == NULL) {
-        return NULL;
-    }
-    jfieldID fidNumber = env->GetFieldID(thisClass, "JNIPointer", "J");
-    if (NULL == fidNumber || env->ExceptionCheck()) {
-        return NULL;
-    }
-    jlong ptr = env->GetLongField(thiz, fidNumber);
-    if (env->ExceptionCheck()) {
-        return NULL;
-    }
-    // Get writer C pointer out of java field.
-    JpegWriter* w_ptr = reinterpret_cast<JpegWriter*>(ptr);
-    if (fid != NULL) {
-        *fid = fidNumber;
-    }
-    return w_ptr;
-}
-
-static JpegReader* getRPtr(JNIEnv* env, jobject thiz, jfieldID* fid) {
-    jclass thisClass = env->GetObjectClass(thiz);
-    if (env->ExceptionCheck() || thisClass == NULL) {
-        return NULL;
-    }
-    jfieldID fidNumber = env->GetFieldID(thisClass, "JNIPointer", "J");
-    if (NULL == fidNumber || env->ExceptionCheck()) {
-        return NULL;
-    }
-    jlong ptr = env->GetLongField(thiz, fidNumber);
-    if (env->ExceptionCheck()) {
-        return NULL;
-    }
-    // Get reader C pointer out of java field.
-    JpegReader* r_ptr = reinterpret_cast<JpegReader*>(ptr);
-    if (fid != NULL) {
-        *fid = fidNumber;
-    }
-    return r_ptr;
-}
-
-static void OutputStream_cleanup(JNIEnv* env, jobject thiz) {
-    jfieldID fidNumber = NULL;
-    JpegWriter* w_ptr = getWPtr(env, thiz, &fidNumber);
-    if (w_ptr == NULL) {
-        return;
-    }
-    // Update environment
-    w_ptr->updateEnv(env);
-    // Destroy writer object
-    delete w_ptr;
-    w_ptr = NULL;
-    // Set the java field to null
-    env->SetLongField(thiz, fidNumber, reinterpret_cast<jlong>(w_ptr));
-}
-
-static void InputStream_cleanup(JNIEnv* env, jobject thiz) {
-    jfieldID fidNumber = NULL;
-    JpegReader* r_ptr = getRPtr(env, thiz, &fidNumber);
-    if (r_ptr == NULL) {
-        return;
-    }
-    // Update environment
-    r_ptr->updateEnv(env);
-    // Destroy the reader object
-    delete r_ptr;
-    r_ptr = NULL;
-    // Set the java field to null
-    env->SetLongField(thiz, fidNumber, reinterpret_cast<jlong>(r_ptr));
-}
-
-static jint OutputStream_writeInputBytes(JNIEnv* env, jobject thiz,
-        jbyteArray inBuffer, jint offset, jint inCount) {
-    JpegWriter* w_ptr = getWPtr(env, thiz, NULL);
-    if (w_ptr == NULL) {
-        return J_EXCEPTION;
-    }
-    // Pin input buffer
-    jbyte* in_buf = (jbyte*) env->GetByteArrayElements(inBuffer, 0);
-    if (env->ExceptionCheck() || in_buf == NULL) {
-        return J_EXCEPTION;
-    }
-
-    int8_t* in_bytes = static_cast<int8_t*>(in_buf);
-    int32_t in_len = static_cast<int32_t>(inCount);
-    int32_t off = static_cast<int32_t>(offset);
-    in_bytes += off;
-    int32_t written = 0;
-
-    // Update environment
-    w_ptr->updateEnv(env);
-    // Write out and unpin buffer.
-    written = w_ptr->write(in_bytes, in_len);
-    env->ReleaseByteArrayElements(inBuffer, in_buf, JNI_ABORT);
-    return written;
-}
-
-static jint InputStream_readDecodedBytes(JNIEnv* env, jobject thiz,
-        jbyteArray inBuffer, jint offset, jint inCount) {
-    JpegReader* r_ptr = getRPtr(env, thiz, NULL);
-    if (r_ptr == NULL) {
-        return J_EXCEPTION;
-    }
-    // Pin input buffer
-    jbyte* in_buf = (jbyte*) env->GetByteArrayElements(inBuffer, 0);
-    if (env->ExceptionCheck() || in_buf == NULL) {
-        return J_EXCEPTION;
-    }
-    int8_t* in_bytes = static_cast<int8_t*>(in_buf);
-    int32_t in_len = static_cast<int32_t>(inCount);
-    int32_t off = static_cast<int32_t>(offset);
-    int32_t read = 0;
-
-    // Update environment
-    r_ptr->updateEnv(env);
-    // Read into buffer
-    read = r_ptr->read(in_bytes, off, in_len);
-
-    // Unpin buffer
-    if (read < 0) {
-        env->ReleaseByteArrayElements(inBuffer, in_buf, JNI_ABORT);
-    } else {
-        env->ReleaseByteArrayElements(inBuffer, in_buf, JNI_COMMIT);
-    }
-    return read;
-}
-
-static jint InputStream_skipDecodedBytes(JNIEnv* env, jobject thiz,
-        jint bytes) {
-    if (bytes <= 0) {
-        return J_ERROR_BAD_ARGS;
-    }
-    JpegReader* r_ptr = getRPtr(env, thiz, NULL);
-    if (r_ptr == NULL) {
-        return J_EXCEPTION;
-    }
-
-    // Update environment
-    r_ptr->updateEnv(env);
-    int32_t skip = 0;
-    // Read with null buffer to skip
-    skip = r_ptr->read(NULL, 0, bytes);
-    return skip;
-}
-
-static const char *outClassPathName =
-        "com/android/gallery3d/jpegstream/JPEGOutputStream";
-static const char *inClassPathName =
-        "com/android/gallery3d/jpegstream/JPEGInputStream";
-
-static JNINativeMethod writeMethods[] = { { "setup",
-        "(Ljava/io/OutputStream;IIII)I", (void*) OutputStream_setup }, {
-        "cleanup", "()V", (void*) OutputStream_cleanup }, { "writeInputBytes",
-        "([BII)I", (void*) OutputStream_writeInputBytes } };
-
-static JNINativeMethod readMethods[] = { { "setup",
-        "(Landroid/graphics/Point;Ljava/io/InputStream;I)I",
-        (void*) InputStream_setup }, { "cleanup", "()V",
-        (void*) InputStream_cleanup }, { "readDecodedBytes", "([BII)I",
-        (void*) InputStream_readDecodedBytes }, { "skipDecodedBytes", "(I)I",
-        (void*) InputStream_skipDecodedBytes } };
-
-static int registerNativeMethods(JNIEnv* env, const char* className,
-        JNINativeMethod* gMethods, int numMethods) {
-    jclass clazz;
-    clazz = env->FindClass(className);
-    if (clazz == NULL) {
-        LOGE("Native registration unable to find class '%s'", className);
-        return JNI_FALSE;
-    }
-    if (env->RegisterNatives(clazz, gMethods, numMethods) < 0) {
-        LOGE("RegisterNatives failed for '%s'", className);
-        return JNI_FALSE;
-    }
-    return JNI_TRUE;
-}
-
-jint JNI_OnLoad(JavaVM* vm, void* reserved) {
-    JNIEnv* env;
-    if (vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK) {
-        LOGE("Error: GetEnv failed in JNI_OnLoad");
-        return -1;
-    }
-    if (!registerNativeMethods(env, outClassPathName, writeMethods,
-            sizeof(writeMethods) / sizeof(writeMethods[0]))) {
-        LOGE("Error: could not register native methods for JPEGOutputStream");
-        return -1;
-    }
-    if (!registerNativeMethods(env, inClassPathName, readMethods,
-            sizeof(readMethods) / sizeof(readMethods[0]))) {
-        LOGE("Error: could not register native methods for JPEGInputStream");
-        return -1;
-    }
-    // cache method IDs for OutputStream
-    jclass outCls = env->FindClass("java/io/OutputStream");
-    if (outCls == NULL) {
-        LOGE("Unable to find class 'OutputStream'");
-        return -1;
-    }
-    jmethodID cachedWriteFun = env->GetMethodID(outCls, "write", "([BII)V");
-    if (cachedWriteFun == NULL) {
-        LOGE("Unable to find write function in class 'OutputStream'");
-        return -1;
-    }
-    OutputStreamWrapper::setWriteMethodID(cachedWriteFun);
-
-    // cache method IDs for InputStream
-    jclass inCls = env->FindClass("java/io/InputStream");
-    if (inCls == NULL) {
-        LOGE("Unable to find class 'InputStream'");
-        return -1;
-    }
-    jmethodID cachedReadFun = env->GetMethodID(inCls, "read", "([BII)I");
-    if (cachedReadFun == NULL) {
-        LOGE("Unable to find read function in class 'InputStream'");
-        return -1;
-    }
-    jmethodID cachedSkipFun = env->GetMethodID(inCls, "skip", "(J)J");
-    if (cachedSkipFun == NULL) {
-        LOGE("Unable to find skip function in class 'InputStream'");
-        return -1;
-    }
-    InputStreamWrapper::setReadSkipMethodIDs(cachedReadFun, cachedSkipFun);
-    return JNI_VERSION_1_6;
-}
-
-#ifdef __cplusplus
-}
-#endif
diff --git a/jni_jpegstream/src/outputstream_wrapper.cpp b/jni_jpegstream/src/outputstream_wrapper.cpp
deleted file mode 100644
index 0639b6e..0000000
--- a/jni_jpegstream/src/outputstream_wrapper.cpp
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Copyright (C) 2013 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.
- */
-
-#include "outputstream_wrapper.h"
-#include "error_codes.h"
-
-jmethodID OutputStreamWrapper::sWriteID = NULL;
-
-int32_t OutputStreamWrapper::write(int32_t length, int32_t offset) {
-    if (offset < 0 || length < 0 || (offset + length) > getBufferSize()) {
-        return J_ERROR_BAD_ARGS;
-    }
-    mEnv->ReleaseByteArrayElements(mByteArray, mBytes, JNI_COMMIT);
-    mBytes = NULL;
-    if (mEnv->ExceptionCheck()) {
-        return J_EXCEPTION;
-    }
-    if (sWriteID == NULL) {
-        LOGE("Uninitialized method ID for OutputStream write function.");
-        return J_ERROR_FATAL;
-    }
-    // Call OutputStream write with byte array.
-    mEnv->CallVoidMethod(mStream, sWriteID, mByteArray, offset, length);
-    if (mEnv->ExceptionCheck()) {
-        return J_EXCEPTION;
-    }
-    mBytes = mEnv->GetByteArrayElements(mByteArray, NULL);
-    if (mBytes == NULL || mEnv->ExceptionCheck()) {
-        return J_EXCEPTION;
-    }
-    return J_SUCCESS;
-}
-
-void OutputStreamWrapper::setWriteMethodID(jmethodID id) {
-    sWriteID = id;
-}
diff --git a/jni_jpegstream/src/outputstream_wrapper.h b/jni_jpegstream/src/outputstream_wrapper.h
deleted file mode 100644
index 9b8b007..0000000
--- a/jni_jpegstream/src/outputstream_wrapper.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright (C) 2013 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.
- */
-
-#ifndef OUTPUTSTREAM_WRAPPER_H_
-#define OUTPUTSTREAM_WRAPPER_H_
-
-#include "jni_defines.h"
-#include "stream_wrapper.h"
-
-#include <stdint.h>
-
-class OutputStreamWrapper : public StreamWrapper {
-public:
-    virtual int32_t write(int32_t length, int32_t offset);
-
-    // Call this in JNI_OnLoad to cache write method
-    static void setWriteMethodID(jmethodID id);
-protected:
-    static jmethodID sWriteID;
-};
-
-#endif // OUTPUTSTREAM_WRAPPER_H_
diff --git a/jni_jpegstream/src/stream_wrapper.cpp b/jni_jpegstream/src/stream_wrapper.cpp
deleted file mode 100644
index 049d84f..0000000
--- a/jni_jpegstream/src/stream_wrapper.cpp
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- * Copyright (C) 2013 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.
- */
-
-#include "stream_wrapper.h"
-
-const int32_t StreamWrapper::END_OF_STREAM = -1;
-const int32_t StreamWrapper::DEFAULT_BUFFER_SIZE = 1 << 16;  // 64Kb
-
-StreamWrapper::StreamWrapper() : mEnv(NULL),
-                                 mStream(NULL),
-                                 mByteArray(NULL),
-                                 mBytes(NULL),
-                                 mByteArrayLen(0) {}
-
-StreamWrapper::~StreamWrapper() {
-    cleanup();
-}
-
-void StreamWrapper::updateEnv(JNIEnv *env) {
-    if (env == NULL) {
-        LOGE("Cannot update StreamWrapper with a null JNIEnv pointer!");
-        return;
-    }
-    mEnv = env;
-}
-
-bool StreamWrapper::init(JNIEnv *env, jobject stream) {
-    if (mEnv != NULL) {
-        LOGW("StreamWrapper already initialized!");
-        return false;
-    }
-    mEnv = env;
-    mStream = env->NewGlobalRef(stream);
-    if (mStream == NULL || env->ExceptionCheck()) {
-        cleanup();
-        return false;
-    }
-    mByteArrayLen = DEFAULT_BUFFER_SIZE;
-    jbyteArray tmp = env->NewByteArray(getBufferSize());
-    if (tmp == NULL || env->ExceptionCheck()){
-        cleanup();
-        return false;
-    }
-    mByteArray = reinterpret_cast<jbyteArray>(env->NewGlobalRef(tmp));
-    if (mByteArray == NULL || env->ExceptionCheck()){
-        cleanup();
-        return false;
-    }
-    mBytes = env->GetByteArrayElements(mByteArray, NULL);
-    if (mBytes == NULL || env->ExceptionCheck()){
-        cleanup();
-        return false;
-    }
-    return true;
-}
-
-void StreamWrapper::cleanup() {
-    if (mEnv != NULL) {
-        if (mStream != NULL) {
-            mEnv->DeleteGlobalRef(mStream);
-            mStream = NULL;
-        }
-        if (mByteArray != NULL) {
-            if (mBytes != NULL) {
-                mEnv->ReleaseByteArrayElements(mByteArray, mBytes, JNI_ABORT);
-                mBytes = NULL;
-            }
-            mEnv->DeleteGlobalRef(mByteArray);
-            mByteArray = NULL;
-        } else {
-            mBytes = NULL;
-        }
-        mByteArrayLen = 0;
-        mEnv = NULL;
-    }
-}
-
-int32_t StreamWrapper::getBufferSize() {
-    return mByteArrayLen;
-}
-
-jbyte* StreamWrapper::getBufferPtr() {
-    return mBytes;
-}
diff --git a/jni_jpegstream/src/stream_wrapper.h b/jni_jpegstream/src/stream_wrapper.h
deleted file mode 100644
index e036a91..0000000
--- a/jni_jpegstream/src/stream_wrapper.h
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Copyright (C) 2013 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.
- */
-
-#ifndef STREAM_WRAPPER_H_
-#define STREAM_WRAPPER_H_
-
-#include "jni_defines.h"
-
-#include <stdint.h>
-
-class StreamWrapper {
-public:
-    StreamWrapper();
-    virtual ~StreamWrapper();
-    virtual void updateEnv(JNIEnv *env);
-    virtual bool init(JNIEnv *env, jobject stream);
-    virtual void cleanup();
-    virtual int32_t getBufferSize();
-    virtual jbyte* getBufferPtr();
-
-    const static int32_t DEFAULT_BUFFER_SIZE;
-    const static int32_t END_OF_STREAM;
-protected:
-    JNIEnv *mEnv;
-    jobject mStream;
-    jbyteArray mByteArray;
-    jbyte* mBytes;
-    int32_t mByteArrayLen;
-};
-
-#endif // STREAM_WRAPPER_H_
diff --git a/proguard-project.txt b/proguard-project.txt
new file mode 100644
index 0000000..f2fe155
--- /dev/null
+++ b/proguard-project.txt
@@ -0,0 +1,20 @@
+# To enable ProGuard in your project, edit project.properties
+# to define the proguard.config property as described in that file.
+#
+# Add project specific ProGuard rules here.
+# By default, the flags in this file are appended to flags specified
+# in ${sdk.dir}/tools/proguard/proguard-android.txt
+# You can edit the include path and order by changing the ProGuard
+# include property in project.properties.
+#
+# For more details, see
+#   http://developer.android.com/guide/developing/tools/proguard.html
+
+# Add any project specific keep options here:
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+#   public *;
+#}
diff --git a/proguard.flags b/proguard.flags
deleted file mode 100644
index 65104ec..0000000
--- a/proguard.flags
+++ /dev/null
@@ -1,86 +0,0 @@
-# Disable the warnings of using dynamic method call in common library.
--dontnote com.android.gallery3d.common.*
-
-# Keep all classes extended from com.android.gallery3d.common.Entry
-# Since we annotate on the fields and use reflection to create SQL
-# according to those field.
-
--keep class * extends com.android.gallery3d.common.Entry {
-    @com.android.gallery3d.common.Entry$Column <fields>;
-}
-
-# ctors of subclasses of CameraPreference are called with Java reflection.
--keep class * extends com.android.camera.CameraPreference {
-  <init>(...);
-}
-
--keep class com.android.camera.CameraActivity {
-  public boolean isRecording();
-  public long getAutoFocusTime();
-  public long getShutterLag();
-  public long getShutterToPictureDisplayedTime();
-  public long getPictureDisplayedToJpegCallbackTime();
-  public long getJpegCallbackFinishTime();
-  public long getCaptureStartTime();
-}
-
--keep class com.android.camera.VideoModule {
-  public void onCancelBgTraining(...);
-  public void onProtectiveCurtainClick(...);
-}
-
--keep class * extends android.app.Activity {
-  @com.android.camera.OnClickAttr <methods>;
-}
-
--keep class com.android.camera.CameraHolder {
-  public static void injectMockCamera(...);
-}
-
-# Disable the warnings of using dynamic method calls in EffectsRecorder
--dontnote com.android.camera.EffectsRecorder
-
--keep class android.support.v8.renderscript.** { *; }
-
-# Required for ActionBarSherlock
--keep class android.support.v4.app.** { *; }
--keep interface android.support.v4.app.** { *; }
--keep class com.actionbarsherlock.** { *; }
--keep interface com.actionbarsherlock.** { *; }
--keepattributes *Annotation*
-
-# Required for mp4parser
--keep public class * implements com.coremedia.iso.boxes.Box
-
-#-assumenosideeffects junit.framework.Assert {
-#*;
-#}
-
-# For unit testing:
-
-# - Required for running exif tests on userdebug
--keep class com.android.gallery3d.exif.ExifTag { *; }
--keep class com.android.gallery3d.exif.ExifData { *; }
--keep class com.android.gallery3d.exif.ExifInterface { *; }
--keepclassmembers class com.android.gallery3d.exif.Util {
-  *** closeSilently(...);
-}
-
-# - Required for running blobcache tests on userdebug
--keep class com.android.gallery3d.common.BlobCache { *; }
-
-# - Required for running glcanvas tests on userdebug
--keep class com.android.gallery3d.ui.GLPaint { *; }
--keep class com.android.gallery3d.ui.GLCanvas { *; }
--keep class com.android.gallery3d.glrenderer.GLPaint { *; }
--keep class com.android.gallery3d.glrenderer.GLCanvas { *; }
--keep class com.android.gallery3d.ui.GLView { *; }
--keepclassmembers class com.android.gallery3d.util.IntArray {
-  *** toArray(...);
-}
--keep class com.android.gallery3d.util.ProfileData { *; }
-
-# - Required for running jpeg stream tests on userdebug
--keep class com.android.gallery3d.jpegstream.JPEGOutputStream { *; }
--keep class com.android.gallery3d.jpegstream.JPEGInputStream { *; }
--keep class com.android.gallery3d.jpegstream.StreamUtils { *; }
diff --git a/project.properties b/project.properties
new file mode 100644
index 0000000..ce39f2d
--- /dev/null
+++ b/project.properties
@@ -0,0 +1,14 @@
+# This file is automatically generated by Android Tools.
+# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
+#
+# This file must be checked in Version Control Systems.
+#
+# To customize properties used by the Ant build system edit
+# "ant.properties", and override values to adapt the script to your
+# project structure.
+#
+# To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home):
+#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
+
+# Project target.
+target=android-18
diff --git a/res/drawable/action_bar_two_line_background.xml b/res/drawable/action_bar_two_line_background.xml
deleted file mode 100644
index a5a1855..0000000
--- a/res/drawable/action_bar_two_line_background.xml
+++ /dev/null
@@ -1,21 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- 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.
--->
-
-<selector xmlns:android="http://schemas.android.com/apk/res/android">
-    <item android:state_activated="true"
-        android:drawable="@drawable/list_selector_background_selected" />
-    <item android:drawable="@android:color/transparent" />
-</selector>
diff --git a/res/drawable/border_photo_frame_widget.xml b/res/drawable/border_photo_frame_widget.xml
deleted file mode 100644
index 5d25de5..0000000
--- a/res/drawable/border_photo_frame_widget.xml
+++ /dev/null
@@ -1,22 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2010 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.
--->
-
-<selector xmlns:android="http://schemas.android.com/apk/res/android">
-    <item android:state_focused="true" android:state_pressed="true" android:drawable="@drawable/border_photo_frame_widget_focused_holo" />
-    <item android:state_focused="true" android:drawable="@drawable/border_photo_frame_widget_focused_holo" />
-    <item android:state_pressed="true" android:drawable="@drawable/border_photo_frame_widget_pressed_holo" />
-    <item android:drawable="@drawable/border_photo_frame_widget_holo" />
-</selector>
diff --git a/res/drawable/btn_shutter_video_recording.xml b/res/drawable/btn_shutter_video_recording.xml
deleted file mode 100644
index 55967a1..0000000
--- a/res/drawable/btn_shutter_video_recording.xml
+++ /dev/null
@@ -1,21 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2011 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.
--->
-
-<selector xmlns:android="http://schemas.android.com/apk/res/android">
-    <item android:state_pressed="true" android:drawable="@drawable/btn_video_shutter_recording_pressed_holo" />
-    <item android:drawable="@drawable/btn_video_shutter_recording_holo" />
-</selector>
-
diff --git a/res/drawable/filtershow_addpoint.png b/res/drawable/filtershow_addpoint.png
deleted file mode 100644
index 5abfc74..0000000
--- a/res/drawable/filtershow_addpoint.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable/filtershow_background.png b/res/drawable/filtershow_background.png
deleted file mode 100644
index 22e1641..0000000
--- a/res/drawable/filtershow_background.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable/filtershow_border_4x5.9.png b/res/drawable/filtershow_border_4x5.9.png
deleted file mode 100644
index 4cddf15..0000000
--- a/res/drawable/filtershow_border_4x5.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable/filtershow_border_black.9.png b/res/drawable/filtershow_border_black.9.png
deleted file mode 100755
index 24bb5e1..0000000
--- a/res/drawable/filtershow_border_black.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable/filtershow_border_brush.9.png b/res/drawable/filtershow_border_brush.9.png
deleted file mode 100644
index db51d24..0000000
--- a/res/drawable/filtershow_border_brush.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable/filtershow_border_film.png b/res/drawable/filtershow_border_film.png
deleted file mode 100755
index 9fbd637..0000000
--- a/res/drawable/filtershow_border_film.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable/filtershow_border_grunge.9.png b/res/drawable/filtershow_border_grunge.9.png
deleted file mode 100644
index fa2d474..0000000
--- a/res/drawable/filtershow_border_grunge.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable/filtershow_border_rounded_black.9.png b/res/drawable/filtershow_border_rounded_black.9.png
deleted file mode 100755
index 590a343..0000000
--- a/res/drawable/filtershow_border_rounded_black.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable/filtershow_border_rounded_white.9.png b/res/drawable/filtershow_border_rounded_white.9.png
deleted file mode 100755
index 4ddc97a..0000000
--- a/res/drawable/filtershow_border_rounded_white.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable/filtershow_border_sumi_e.9.png b/res/drawable/filtershow_border_sumi_e.9.png
deleted file mode 100644
index 45f1094..0000000
--- a/res/drawable/filtershow_border_sumi_e.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable/filtershow_border_tape.9.png b/res/drawable/filtershow_border_tape.9.png
deleted file mode 100644
index 3837c5d..0000000
--- a/res/drawable/filtershow_border_tape.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable/filtershow_border_white.9.png b/res/drawable/filtershow_border_white.9.png
deleted file mode 100755
index d8c8826..0000000
--- a/res/drawable/filtershow_border_white.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable/filtershow_button_background.xml b/res/drawable/filtershow_button_background.xml
deleted file mode 100644
index ee8a92d..0000000
--- a/res/drawable/filtershow_button_background.xml
+++ /dev/null
@@ -1,8 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<selector xmlns:android="http://schemas.android.com/apk/res/android">
-
-    <item android:drawable="@android:color/holo_blue_light" android:state_pressed="true"/>
-    <item android:drawable="@drawable/filtershow_button_selected_background" android:state_selected="true"/>
-    <item android:drawable="@android:color/transparent" android:state_selected="false"/>
-
-</selector>
\ No newline at end of file
diff --git a/res/drawable/filtershow_button_border.png b/res/drawable/filtershow_button_border.png
deleted file mode 100644
index 69195a9..0000000
--- a/res/drawable/filtershow_button_border.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable/filtershow_button_colors.png b/res/drawable/filtershow_button_colors.png
deleted file mode 100644
index 566773d..0000000
--- a/res/drawable/filtershow_button_colors.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable/filtershow_button_colors_contrast.png b/res/drawable/filtershow_button_colors_contrast.png
deleted file mode 100644
index ccb2dc6..0000000
--- a/res/drawable/filtershow_button_colors_contrast.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable/filtershow_button_colors_vignette.png b/res/drawable/filtershow_button_colors_vignette.png
deleted file mode 100644
index ac3d53f..0000000
--- a/res/drawable/filtershow_button_colors_vignette.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable/filtershow_button_current.png b/res/drawable/filtershow_button_current.png
deleted file mode 100644
index 8c4b379..0000000
--- a/res/drawable/filtershow_button_current.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable/filtershow_button_fx.png b/res/drawable/filtershow_button_fx.png
deleted file mode 100644
index c887fe4..0000000
--- a/res/drawable/filtershow_button_fx.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable/filtershow_button_geometry.png b/res/drawable/filtershow_button_geometry.png
deleted file mode 100644
index 4b8f3b8..0000000
--- a/res/drawable/filtershow_button_geometry.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable/filtershow_button_geometry_crop.png b/res/drawable/filtershow_button_geometry_crop.png
deleted file mode 100644
index eb7da1b..0000000
--- a/res/drawable/filtershow_button_geometry_crop.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable/filtershow_button_geometry_flip.png b/res/drawable/filtershow_button_geometry_flip.png
deleted file mode 100644
index dd74813..0000000
--- a/res/drawable/filtershow_button_geometry_flip.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable/filtershow_button_geometry_rotate.png b/res/drawable/filtershow_button_geometry_rotate.png
deleted file mode 100644
index fa50ce2..0000000
--- a/res/drawable/filtershow_button_geometry_rotate.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable/filtershow_button_geometry_straighten.png b/res/drawable/filtershow_button_geometry_straighten.png
deleted file mode 100644
index 309eb5a..0000000
--- a/res/drawable/filtershow_button_geometry_straighten.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable/filtershow_button_operations.png b/res/drawable/filtershow_button_operations.png
deleted file mode 100644
index 79e9a44..0000000
--- a/res/drawable/filtershow_button_operations.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable/filtershow_button_origin.png b/res/drawable/filtershow_button_origin.png
deleted file mode 100644
index 0cd0bc2..0000000
--- a/res/drawable/filtershow_button_origin.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable/filtershow_button_redo.png b/res/drawable/filtershow_button_redo.png
deleted file mode 100644
index 9daa01c..0000000
--- a/res/drawable/filtershow_button_redo.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable/filtershow_button_selected_background.9.png b/res/drawable/filtershow_button_selected_background.9.png
deleted file mode 100644
index bb41245..0000000
--- a/res/drawable/filtershow_button_selected_background.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable/filtershow_button_settings.png b/res/drawable/filtershow_button_settings.png
deleted file mode 100644
index df3925a..0000000
--- a/res/drawable/filtershow_button_settings.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable/filtershow_button_show_original.png b/res/drawable/filtershow_button_show_original.png
deleted file mode 100644
index 925954b..0000000
--- a/res/drawable/filtershow_button_show_original.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable/filtershow_button_undo.png b/res/drawable/filtershow_button_undo.png
deleted file mode 100644
index 0a7e0d1..0000000
--- a/res/drawable/filtershow_button_undo.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable/filtershow_color_picker_circle.xml b/res/drawable/filtershow_color_picker_circle.xml
deleted file mode 100644
index 4444e0f..0000000
--- a/res/drawable/filtershow_color_picker_circle.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2013 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.
--->
-
-<shape xmlns:android="http://schemas.android.com/apk/res/android"
-    android:shape="oval" >
-    <size android:width="20dp" android:height="20dp"/>
-    <corners
-        android:radius="10dp" />
-    <solid android:color="@color/red"/>
-</shape>
-
diff --git a/res/drawable/filtershow_color_picker_roundrect.xml b/res/drawable/filtershow_color_picker_roundrect.xml
deleted file mode 100644
index 89add5e..0000000
--- a/res/drawable/filtershow_color_picker_roundrect.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2013 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.
--->
-
-<shape xmlns:android="http://schemas.android.com/apk/res/android"
-    android:shape="rectangle" >
-
-    <size android:width="20dp" android:height="20dp"/>
-    <corners android:radius="10dp" />
-    <solid android:color="@color/red"/>
-
-</shape>
-
diff --git a/res/drawable/filtershow_delpoint.png b/res/drawable/filtershow_delpoint.png
deleted file mode 100644
index 84f2e5b..0000000
--- a/res/drawable/filtershow_delpoint.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable/filtershow_drawing.png b/res/drawable/filtershow_drawing.png
deleted file mode 100644
index 566773d..0000000
--- a/res/drawable/filtershow_drawing.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable/filtershow_fx_0000_vintage.png b/res/drawable/filtershow_fx_0000_vintage.png
deleted file mode 100644
index 6783bb6..0000000
--- a/res/drawable/filtershow_fx_0000_vintage.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable/filtershow_fx_0001_instant.png b/res/drawable/filtershow_fx_0001_instant.png
deleted file mode 100644
index 1652a4b..0000000
--- a/res/drawable/filtershow_fx_0001_instant.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable/filtershow_fx_0002_bleach.png b/res/drawable/filtershow_fx_0002_bleach.png
deleted file mode 100644
index afb8a82..0000000
--- a/res/drawable/filtershow_fx_0002_bleach.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable/filtershow_fx_0003_blue_crush.png b/res/drawable/filtershow_fx_0003_blue_crush.png
deleted file mode 100644
index 2b238e3..0000000
--- a/res/drawable/filtershow_fx_0003_blue_crush.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable/filtershow_fx_0004_bw_contrast.png b/res/drawable/filtershow_fx_0004_bw_contrast.png
deleted file mode 100644
index 40eb397..0000000
--- a/res/drawable/filtershow_fx_0004_bw_contrast.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable/filtershow_fx_0005_punch.png b/res/drawable/filtershow_fx_0005_punch.png
deleted file mode 100644
index e7e0803..0000000
--- a/res/drawable/filtershow_fx_0005_punch.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable/filtershow_fx_0006_x_process.png b/res/drawable/filtershow_fx_0006_x_process.png
deleted file mode 100644
index 5de9bb4..0000000
--- a/res/drawable/filtershow_fx_0006_x_process.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable/filtershow_fx_0007_washout.png b/res/drawable/filtershow_fx_0007_washout.png
deleted file mode 100644
index 20dfb5e..0000000
--- a/res/drawable/filtershow_fx_0007_washout.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable/filtershow_fx_0008_washout_color.png b/res/drawable/filtershow_fx_0008_washout_color.png
deleted file mode 100644
index bb6602b..0000000
--- a/res/drawable/filtershow_fx_0008_washout_color.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable/filtershow_grad_button.xml b/res/drawable/filtershow_grad_button.xml
deleted file mode 100644
index 4bf84c1..0000000
--- a/res/drawable/filtershow_grad_button.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-     Copyright (C) 2013 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.
--->
-
-<selector xmlns:android="http://schemas.android.com/apk/res/android">
-
-    <item android:state_checked="false" android:drawable="@android:color/transparent"  />
-    <item android:state_checked="true" android:drawable="@android:color/holo_blue_light"  />
-
-</selector>
\ No newline at end of file
diff --git a/res/drawable/filtershow_menu_marker.png b/res/drawable/filtershow_menu_marker.png
deleted file mode 100644
index 1537a71..0000000
--- a/res/drawable/filtershow_menu_marker.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable/filtershow_scrubber.xml b/res/drawable/filtershow_scrubber.xml
deleted file mode 100644
index 744d1da..0000000
--- a/res/drawable/filtershow_scrubber.xml
+++ /dev/null
@@ -1,22 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-     Copyright (C) 2013 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.
--->
-<selector xmlns:android="http://schemas.android.com/apk/res/android">
-    <item android:state_enabled="false" android:drawable="@drawable/filtershow_scrubber_control_disabled" />
-    <item android:state_pressed="true" android:drawable="@drawable/filtershow_scrubber_control_pressed" />
-    <item android:state_selected="true" android:drawable="@drawable/filtershow_scrubber_control_focused" />
-    <item android:drawable="@drawable/filtershow_scrubber_control_normal" />
-</selector>
\ No newline at end of file
diff --git a/res/drawable/filtershow_slider.xml b/res/drawable/filtershow_slider.xml
deleted file mode 100644
index 23457a6..0000000
--- a/res/drawable/filtershow_slider.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-     Copyright (C) 2013 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.
--->
-<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
-    <item android:id="@android:id/background"
-          android:drawable="@drawable/filtershow_scrubber_track" />
-    <item android:id="@android:id/secondaryProgress">
-        <scale android:scaleWidth="100%"
-               android:drawable="@drawable/filtershow_scrubber_secondary" />
-    </item>
-    <item android:id="@android:id/progress">
-        <scale android:scaleWidth="100%"
-               android:drawable="@drawable/filtershow_scrubber_primary" />
-    </item>
-</layer-list>
\ No newline at end of file
diff --git a/res/drawable/filtershow_state_button_background b/res/drawable/filtershow_state_button_background
deleted file mode 100644
index e69de29..0000000
--- a/res/drawable/filtershow_state_button_background
+++ /dev/null
diff --git a/res/drawable/filtershow_tiled_background.xml b/res/drawable/filtershow_tiled_background.xml
deleted file mode 100644
index 055fbcd..0000000
--- a/res/drawable/filtershow_tiled_background.xml
+++ /dev/null
@@ -1,21 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-     Copyright (C) 2013 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.
--->
-<bitmap
-        xmlns:android="http://schemas.android.com/apk/res/android"
-        android:src="@drawable/filtershow_background"
-        android:tileMode="repeat"
-        android:dither="false" />
\ No newline at end of file
diff --git a/res/drawable/filtershow_vertical_bar.png b/res/drawable/filtershow_vertical_bar.png
deleted file mode 100644
index 5ac0a9f..0000000
--- a/res/drawable/filtershow_vertical_bar.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable/filtershow_vertical_line.xml b/res/drawable/filtershow_vertical_line.xml
deleted file mode 100644
index 611c7e0..0000000
--- a/res/drawable/filtershow_vertical_line.xml
+++ /dev/null
@@ -1,22 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- 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.
--->
-
-<shape xmlns:android="http://schemas.android.com/apk/res/android"
-    android:shape="rectangle" >
-    <size android:width="1dp" android:height="20dp"/>
-    <corners android:radius="0dp" />
-    <solid android:color="@color/toolbar_separation_line"/>
-</shape>
\ No newline at end of file
diff --git a/res/drawable/icn_media_pause.xml b/res/drawable/icn_media_pause.xml
deleted file mode 100644
index cb5014f..0000000
--- a/res/drawable/icn_media_pause.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2010 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.
--->
-
-<selector xmlns:android="http://schemas.android.com/apk/res/android">
-    <item android:state_pressed="true"
-          android:drawable="@drawable/icn_media_pause_pressed_holo_dark" />
-    <item android:state_focused="true"
-          android:drawable="@drawable/icn_media_pause_focused_holo_dark" />
-    <item android:drawable="@drawable/icn_media_pause_normal_holo_dark" />
-</selector>
diff --git a/res/drawable/icn_media_play.xml b/res/drawable/icn_media_play.xml
deleted file mode 100644
index a21e082..0000000
--- a/res/drawable/icn_media_play.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2010 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.
--->
-
-<selector xmlns:android="http://schemas.android.com/apk/res/android">
-    <item android:state_pressed="true"
-          android:drawable="@drawable/icn_media_play_pressed_holo_dark" />
-    <item android:state_focused="true"
-          android:drawable="@drawable/icn_media_play_focused_holo_dark" />
-    <item android:drawable="@drawable/icn_media_play_normal_holo_dark" />
-</selector>
diff --git a/res/drawable/ingest_item_list_selector.xml b/res/drawable/ingest_item_list_selector.xml
deleted file mode 100644
index 1a4541f..0000000
--- a/res/drawable/ingest_item_list_selector.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2013 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.
--->
-<selector xmlns:android="http://schemas.android.com/apk/res/android">
-    <item android:drawable="@color/ingest_highlight_semitransparent"
-        android:state_checked="true" />
-    <item android:drawable="@color/ingest_highlight_semitransparent"
-        android:state_selected="true" />
-    <item android:drawable="@color/ingest_highlight_semitransparent"
-        android:state_pressed="true" />
-</selector>
\ No newline at end of file
diff --git a/res/drawable/menu_save_photo.xml b/res/drawable/menu_save_photo.xml
deleted file mode 100644
index 0b92ac9..0000000
--- a/res/drawable/menu_save_photo.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2010 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.
--->
-
-<selector xmlns:android="http://schemas.android.com/apk/res/android">
-    <item android:state_enabled="true" android:drawable="@drawable/ic_menu_savephoto" />
-    <item android:state_enabled="false" android:drawable="@drawable/ic_menu_savephoto_disabled" />
-</selector>
diff --git a/res/drawable/photoeditor_effect_redeye.png b/res/drawable/photoeditor_effect_redeye.png
deleted file mode 100644
index ba845b5..0000000
--- a/res/drawable/photoeditor_effect_redeye.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable/photopage_bottom_button_background.xml b/res/drawable/photopage_bottom_button_background.xml
deleted file mode 100644
index 0c772ad..0000000
--- a/res/drawable/photopage_bottom_button_background.xml
+++ /dev/null
@@ -1,5 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<selector xmlns:android="http://schemas.android.com/apk/res/android">
-    <item android:drawable="@android:color/holo_blue_light" android:state_pressed="true"/>
-    <item android:drawable="@color/button_dark_transparent_background" android:state_selected="false"/>
-</selector>
diff --git a/res/drawable/white_text_bg_gradient.xml b/res/drawable/white_text_bg_gradient.xml
deleted file mode 100644
index c355ce5..0000000
--- a/res/drawable/white_text_bg_gradient.xml
+++ /dev/null
@@ -1,22 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2013 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.
--->
-<shape xmlns:android="http://schemas.android.com/apk/res/android">
-    <gradient
-        android:startColor="#DD000000"
-        android:endColor="#00FFFFFF"
-        android:angle="90"
-     />
-</shape>
\ No newline at end of file
diff --git a/res/interpolator/decelerate_cubic.xml b/res/interpolator/decelerate_cubic.xml
deleted file mode 100644
index 0bdd01d..0000000
--- a/res/interpolator/decelerate_cubic.xml
+++ /dev/null
@@ -1,17 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- 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.
--->
-<decelerateInterpolator xmlns:android="http://schemas.android.com/apk/res/android"
-        android:factor="1.5" />
diff --git a/res/interpolator/decelerate_quint.xml b/res/interpolator/decelerate_quint.xml
deleted file mode 100644
index 1939141..0000000
--- a/res/interpolator/decelerate_quint.xml
+++ /dev/null
@@ -1,17 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- 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.
--->
-<decelerateInterpolator xmlns:android="http://schemas.android.com/apk/res/android"
-        android:factor="2.5" />
diff --git a/res/layout-land/filtershow_activity.xml b/res/layout-land/filtershow_activity.xml
deleted file mode 100644
index 4d098e6..0000000
--- a/res/layout-land/filtershow_activity.xml
+++ /dev/null
@@ -1,85 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-     Copyright (C) 2013 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.
--->
-
-<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
-             android:layout_width="match_parent"
-             android:layout_height="match_parent"
-             android:id="@+id/mainView"
-             android:background="@drawable/filtershow_tiled_background">
-
-    <LinearLayout
-            android:layout_width="match_parent"
-            android:layout_height="match_parent"
-            android:orientation="horizontal"
-            android:animateLayoutChanges="true">
-
-        <LinearLayout
-                android:layout_weight="1"
-                android:layout_width="wrap_content"
-                android:layout_height="match_parent"
-                android:orientation="horizontal">
-
-            <FrameLayout
-                    android:id="@+id/editorContainer"
-                    android:layout_width="match_parent"
-                    android:layout_height="wrap_content"
-                    android:layout_weight="1"/>
-
-            <com.android.gallery3d.filtershow.imageshow.ImageShow
-                    android:id="@+id/imageShow"
-                    android:layout_width="match_parent"
-                    android:layout_height="wrap_content"
-                    android:layout_weight="1" />
-
-        </LinearLayout>
-
-        <LinearLayout
-                android:id="@+id/mainPanel"
-                android:layout_width="350dip"
-                android:layout_height="match_parent"
-                android:orientation="vertical"
-                android:animateLayoutChanges="true" >
-
-            <FrameLayout android:id="@+id/main_panel_container"
-                         android:layout_width="350dip"
-                         android:layout_height="0dip"
-                         android:layout_weight="1" />
-
-            <FrameLayout
-                    android:layout_gravity="bottom"
-                    android:layout_width="match_parent"
-                    android:layout_height="wrap_content"
-                    android:visibility="gone">
-
-
-                <ProgressBar
-                        android:id="@+id/loading"
-                        style="@android:style/Widget.Holo.ProgressBar.Large"
-                        android:layout_width="wrap_content"
-                        android:layout_height="wrap_content"
-                        android:layout_gravity="center"
-                        android:indeterminate="true"
-                        android:indeterminateOnly="true"
-                        android:background="@color/background_screen"/>
-
-            </FrameLayout>
-
-        </LinearLayout>
-
-    </LinearLayout>
-
-</FrameLayout>
diff --git a/res/layout-land/filtershow_category_panel_new.xml b/res/layout-land/filtershow_category_panel_new.xml
deleted file mode 100644
index 10a6c97..0000000
--- a/res/layout-land/filtershow_category_panel_new.xml
+++ /dev/null
@@ -1,32 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-     Copyright (C) 2013 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.
--->
-
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-              android:orientation="horizontal"
-              android:layout_width="match_parent"
-              android:layout_height="match_parent">
-
-    <ListView
-            android:id="@+id/listItems"
-            android:orientation="vertical"
-            android:layout_width="match_parent"
-            android:layout_height="match_parent"
-            android:layout_margin="8dip"
-            android:divider="@android:color/transparent"
-            android:dividerHeight="8dip" />
-
-</LinearLayout>
\ No newline at end of file
diff --git a/res/layout-land/filtershow_editor_panel.xml b/res/layout-land/filtershow_editor_panel.xml
deleted file mode 100644
index 015fa26..0000000
--- a/res/layout-land/filtershow_editor_panel.xml
+++ /dev/null
@@ -1,127 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-     Copyright (C) 2013 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.
--->
-
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-              android:id="@+id/top"
-              android:layout_width="match_parent"
-              android:layout_height="match_parent"
-              android:orientation="vertical"
-              android:visibility="visible">
-
-    <Button
-            android:id="@+id/toggle_state"
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:text="@string/imageState"
-            android:background="@color/background_main_toolbar"
-            />
-
-    <FrameLayout android:id="@+id/state_panel_container"
-                 android:layout_width="match_parent"
-                 android:layout_height="0dip"
-                 android:visibility="visible"
-                 android:layout_gravity="top"
-                 android:layout_weight="1" />
-
-    <LinearLayout
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:orientation="vertical"
-            android:layout_gravity="bottom">
-
-        <LinearLayout
-                android:id="@+id/controlArea"
-                android:layout_width="match_parent"
-                android:layout_height="wrap_content"
-                android:orientation="horizontal"
-                android:layout_alignParentBottom="true"
-                android:visibility="visible">
-
-            <SeekBar
-                    android:id="@+id/primarySeekBar"
-                    android:layout_width="match_parent"
-                    android:layout_height="wrap_content"
-                    android:layout_gravity="center_vertical"
-                    style="@style/FilterShowSlider"/>
-
-        </LinearLayout>
-
-        <LinearLayout
-                android:layout_width="match_parent"
-                android:layout_height="56dip"
-                android:background="@color/background_main_toolbar"
-                android:orientation="horizontal"
-                android:baselineAligned="false"
-                android:visibility="visible">
-
-            <ImageButton
-                    android:id="@+id/cancelFilter"
-                    android:layout_width="wrap_content"
-                    android:layout_height="fill_parent"
-                    android:layout_gravity="left|center_vertical"
-                    android:background="@android:color/transparent"
-                    android:layout_weight=".1"
-                    android:gravity="center"
-                    android:src="@drawable/ic_menu_cancel_holo_light"
-                    android:textSize="18dip"/>
-
-            <ImageView
-                    android:layout_width="2dp"
-                    android:layout_height="fill_parent"
-                    android:src="@drawable/filtershow_vertical_bar"/>
-
-            <LinearLayout
-                    android:id="@+id/panelAccessoryViewList"
-                    android:layout_width="wrap_content"
-                    android:layout_height="match_parent"
-                    android:layout_weight="1"
-                    android:orientation="horizontal"
-                    android:visibility="visible">
-
-                <com.android.gallery3d.filtershow.editors.SwapButton
-                        android:id="@+id/applyEffect"
-                        android:layout_width="fill_parent"
-                        android:layout_height="fill_parent"
-                        android:layout_gravity="center"
-                        android:background="@android:color/transparent"
-                        android:gravity="center"
-                        android:text="@string/apply_effect"
-                        android:textSize="18dip"
-                        android:drawableRight="@drawable/filtershow_menu_marker"
-                        android:textAllCaps="true" />
-
-            </LinearLayout>
-
-            <ImageView
-                    android:layout_width="2dp"
-                    android:layout_height="fill_parent"
-                    android:src="@drawable/filtershow_vertical_bar"/>
-
-            <ImageButton
-                    android:id="@+id/applyFilter"
-                    android:layout_width="wrap_content"
-                    android:layout_height="fill_parent"
-                    android:layout_gravity="right|center_vertical"
-                    android:layout_weight=".1"
-                    android:background="@android:color/transparent"
-                    android:gravity="center"
-                    android:src="@drawable/ic_menu_done_holo_light"
-                    android:textSize="18dip"/>
-        </LinearLayout>
-    </LinearLayout>
-
-</LinearLayout>
diff --git a/res/layout-land/filtershow_main_panel.xml b/res/layout-land/filtershow_main_panel.xml
deleted file mode 100644
index 705eb69..0000000
--- a/res/layout-land/filtershow_main_panel.xml
+++ /dev/null
@@ -1,98 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-     Copyright (C) 2013 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.
--->
-
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-              android:layout_width="match_parent"
-              android:layout_height="match_parent"
-              android:baselineAligned="false"
-              android:orientation="vertical"
-              android:animateLayoutChanges="true"
-              android:visibility="visible" >
-
-    <FrameLayout android:id="@+id/state_panel_container"
-                 android:layout_width="match_parent"
-                 android:layout_height="0dip"
-                 android:visibility="visible"
-                 android:layout_gravity="top"
-                 android:layout_weight="1" />
-
-    <FrameLayout android:id="@+id/category_panel_container"
-                 android:layout_width="match_parent"
-                 android:layout_height="0dip"
-                 android:layout_weight="1"/>
-
-    <View
-            android:background="@color/toolbar_separation_line"
-            android:layout_height="1dip"
-            android:layout_width="match_parent"/>
-
-    <com.android.gallery3d.filtershow.CenteredLinearLayout
-            xmlns:custom="http://schemas.android.com/apk/res/com.android.gallery3d"
-            android:layout_width="match_parent"
-            android:layout_height="48dip"
-            android:layout_gravity="center|bottom"
-            custom:max_width="400dip"
-            android:orientation="vertical">
-
-        <LinearLayout android:layout_width="wrap_content"
-                      android:layout_height="match_parent"
-                      android:background="@color/background_main_toolbar">
-
-            <ImageButton
-                    android:id="@+id/fxButton"
-                    android:layout_width="@dimen/thumbnail_size"
-                    android:layout_height="match_parent"
-                    android:layout_weight="1"
-                    android:background="@drawable/filtershow_button_background"
-                    android:scaleType="centerInside"
-                    android:src="@drawable/ic_photoeditor_effects"/>
-
-            <ImageButton
-                    android:id="@+id/borderButton"
-                    android:layout_width="@dimen/thumbnail_size"
-                    android:layout_height="match_parent"
-                    android:layout_weight="1"
-                    android:background="@drawable/filtershow_button_background"
-                    android:padding="2dip"
-                    android:scaleType="centerInside"
-                    android:src="@drawable/ic_photoeditor_border"/>
-
-            <ImageButton
-                    android:id="@+id/geometryButton"
-                    android:layout_width="@dimen/thumbnail_size"
-                    android:layout_height="match_parent"
-                    android:layout_weight="1"
-                    android:background="@drawable/filtershow_button_background"
-                    android:padding="2dip"
-                    android:scaleType="centerInside"
-                    android:src="@drawable/ic_photoeditor_fix"/>
-
-            <ImageButton
-                    android:id="@+id/colorsButton"
-                    android:layout_width="@dimen/thumbnail_size"
-                    android:layout_height="match_parent"
-                    android:layout_weight="1"
-                    android:background="@drawable/filtershow_button_background"
-                    android:padding="2dip"
-                    android:scaleType="centerInside"
-                    android:src="@drawable/ic_photoeditor_color"/>
-
-        </LinearLayout>
-
-    </com.android.gallery3d.filtershow.CenteredLinearLayout>
-
-</LinearLayout>
\ No newline at end of file
diff --git a/res/layout-land/filtershow_state_panel_new.xml b/res/layout-land/filtershow_state_panel_new.xml
deleted file mode 100644
index c83cd88..0000000
--- a/res/layout-land/filtershow_state_panel_new.xml
+++ /dev/null
@@ -1,33 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-              xmlns:custom="http://schemas.android.com/apk/res/com.android.gallery3d"
-              android:orientation="vertical"
-              android:layout_width="match_parent"
-              android:layout_height="match_parent">
-
-    <ScrollView
-            android:layout_width="match_parent"
-            android:layout_height="0dip"
-            android:layout_weight="1"
-            android:scrollbars="none">
-
-        <com.android.gallery3d.filtershow.state.StatePanelTrack
-                android:id="@+id/listStates"
-                android:orientation="vertical"
-                android:layout_width="match_parent"
-                android:layout_height="match_parent"
-                custom:elemSize="72dip"
-                custom:elemEndSize="32dip"
-                android:layout_margin="8dip"
-                android:animateLayoutChanges="true" />
-
-    </ScrollView>
-
-    <View
-            android:background="@color/state_panel_separation_line"
-            android:layout_height="6dip"
-            android:layout_width="match_parent"
-            android:paddingTop="8dip"/>
-
-</LinearLayout>
diff --git a/res/layout/action_bar_text.xml b/res/layout/action_bar_text.xml
deleted file mode 100644
index a332647..0000000
--- a/res/layout/action_bar_text.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2006 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.
--->
-
-<TextView xmlns:android="http://schemas.android.com/apk/res/android"
-    android:id="@android:id/text1"
-    android:background="?android:attr/activatedBackgroundIndicator"
-    android:layout_width="match_parent"
-    android:layout_height="wrap_content"
-    android:textAppearance="?android:attr/textAppearanceMedium"
-    android:gravity="center_vertical"
-    android:paddingLeft="18dp"
-    android:paddingRight="18dp"
-    android:singleLine="true"
-    android:minHeight="?attr/listPreferredItemHeightSmall"
-/>
diff --git a/res/layout/action_bar_two_line_text.xml b/res/layout/action_bar_two_line_text.xml
deleted file mode 100644
index 92a4af9..0000000
--- a/res/layout/action_bar_two_line_text.xml
+++ /dev/null
@@ -1,42 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2006 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.
--->
-<TwoLineListItem xmlns:android="http://schemas.android.com/apk/res/android"
-        style="@style/ActionBarTwoLineItem"
-        android:layout_height="match_parent"
-        android:orientation="vertical"
-        android:gravity="center_vertical"
-        android:duplicateParentState="false"
-        android:layout_alignParentLeft="true"
-        android:layout_width="wrap_content" >
-        <TextView
-            android:id="@android:id/text1"
-            style="@style/ActionBarTwoLinePrimary"
-            android:singleLine="true"
-            android:ellipsize="end"
-            android:includeFontPadding="false"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content" />
-        <TextView
-            android:id="@android:id/text2"
-            style="@style/ActionBarTwoLineSecondary"
-            android:singleLine="true"
-            android:ellipsize="end"
-            android:includeFontPadding="false"
-            android:layout_marginRight="4dp"
-            android:layout_below="@android:id/text1"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content" />
-</TwoLineListItem>
diff --git a/res/layout/action_mode.xml b/res/layout/action_mode.xml
deleted file mode 100644
index 6c516e6..0000000
--- a/res/layout/action_mode.xml
+++ /dev/null
@@ -1,48 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2010 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.
--->
-
-<LinearLayout
-        xmlns:android="http://schemas.android.com/apk/res/android"
-        android:id="@+id/navigation_bar"
-        android:layout_width="match_parent"
-        android:layout_height="match_parent"
-        android:orientation="horizontal">
-
-    <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
-            android:layout_width="wrap_content"
-            android:layout_height="match_parent">
-        <ImageView android:layout_gravity="right"
-                android:layout_width="wrap_content"
-                android:layout_height="match_parent"
-                android:src="@drawable/dropdown_ic_arrow_normal_holo_dark" />
-        <Button android:id="@+id/selection_menu"
-                style="?android:attr/actionButtonStyle"
-                android:divider="?android:attr/listDividerAlertDialog"
-                android:textAppearance="?android:attr/textAppearanceLargePopupMenu"
-                android:textColor="?android:attr/actionMenuTextColor"
-                android:singleLine="true"
-                android:gravity="left|center_vertical"
-                android:paddingRight="25dip"
-                android:layout_width="wrap_content"
-                android:layout_height="match_parent" />
-    </FrameLayout>
-    <ImageView android:layout_marginLeft="16dip"
-            android:layout_marginRight="8dip"
-            android:layout_width="wrap_content"
-            android:layout_height="match_parent"
-            android:gravity="bottom"
-            android:src="@drawable/cab_divider_vertical_dark" />
-</LinearLayout>
diff --git a/res/layout/album_content.xml b/res/layout/album_content.xml
deleted file mode 100644
index 97509fd..0000000
--- a/res/layout/album_content.xml
+++ /dev/null
@@ -1,57 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2013 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.
--->
-<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
-        android:layout_width="match_parent"
-        android:layout_height="match_parent">
-
-    <LinearLayout android:id="@+id/progressContainer"
-            android:orientation="vertical"
-            android:layout_width="match_parent"
-            android:layout_height="match_parent"
-            android:visibility="gone"
-            android:gravity="center">
-
-        <ProgressBar style="?android:attr/progressBarStyleLarge"
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content" />
-        <TextView android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
-                android:textAppearance="?android:attr/textAppearanceSmall"
-                android:text="@string/loading"
-                android:paddingTop="4dip"
-                android:singleLine="true" />
-
-    </LinearLayout>
-
-    <FrameLayout android:id="@+id/gridContainer"
-            android:layout_width="match_parent"
-            android:layout_height="match_parent">
-
-        <com.android.photos.views.HeaderGridView android:id="@android:id/list"
-                android:layout_width="match_parent"
-                android:layout_height="match_parent"
-                android:choiceMode="multipleChoiceModal"
-                android:numColumns="auto_fit"
-                android:stretchMode="columnWidth"
-                android:drawSelectorOnTop="true" />
-        <TextView android:id="@android:id/empty"
-                android:layout_width="match_parent"
-                android:layout_height="match_parent"
-                android:gravity="center"
-                android:textAppearance="?android:attr/textAppearanceMedium" />
-    </FrameLayout>
-
-</FrameLayout>
\ No newline at end of file
diff --git a/res/layout/album_header.xml b/res/layout/album_header.xml
deleted file mode 100644
index 76c9a45..0000000
--- a/res/layout/album_header.xml
+++ /dev/null
@@ -1,54 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2013 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.
--->
-<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    android:layout_width="match_parent"
-    android:layout_height="wrap_content" >
-
-    <ImageView
-        android:id="@+id/album_header_image"
-        android:layout_width="match_parent"
-        android:layout_height="match_parent"
-        android:scaleType="centerCrop" />
-
-    <LinearLayout
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:layout_alignParentBottom="true"
-        android:layout_alignParentLeft="true"
-        android:paddingLeft="15dip"
-        android:paddingBottom="10dip"
-        android:paddingTop="20dip"
-        android:background="@drawable/white_text_bg_gradient"
-        android:layout_gravity="bottom"
-        android:orientation="vertical" >
-
-        <TextView
-            android:id="@+id/album_header_title"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:textColor="@android:color/white"
-            android:textAppearance="?android:attr/textAppearanceLarge" />
-
-        <TextView
-            android:id="@+id/album_header_subtitle"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:textColor="@android:color/white"
-            android:textAppearance="?android:attr/textAppearanceSmall" />
-
-    </LinearLayout>
-
-</FrameLayout>
\ No newline at end of file
diff --git a/res/layout/album_set_item.xml b/res/layout/album_set_item.xml
deleted file mode 100644
index ad0e0db..0000000
--- a/res/layout/album_set_item.xml
+++ /dev/null
@@ -1,39 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    android:layout_height="wrap_content"
-    android:layout_width="match_parent"
-    android:orientation="vertical"
-    android:background="?android:attr/activatedBackgroundIndicator"
-    android:padding="2dp" >
-
-    <LinearLayout
-        android:layout_height="wrap_content"
-        android:layout_width="match_parent"
-        android:orientation="vertical"
-        android:padding="10dp"
-        android:background="#FFF" >
-
-        <TextView
-            android:id="@+id/album_set_item_title"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:ellipsize="end"
-            android:singleLine="true"
-            android:textAppearance="?android:attr/textAppearanceMedium" />
-
-        <TextView
-            android:id="@+id/album_set_item_count"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:ellipsize="end"
-            android:singleLine="true"
-            android:textAppearance="?android:attr/textAppearanceSmall"
-            android:textColor="#AAA" />
-    </LinearLayout>
-
-    <ImageView
-        android:id="@+id/album_set_item_image"
-        android:layout_width="match_parent"
-        android:layout_height="@dimen/album_set_item_image_height"
-        android:scaleType="centerCrop" />
-</LinearLayout>
\ No newline at end of file
diff --git a/res/layout/appwidget_loading_item.xml b/res/layout/appwidget_loading_item.xml
deleted file mode 100644
index ee8a206..0000000
--- a/res/layout/appwidget_loading_item.xml
+++ /dev/null
@@ -1,30 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2011 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.
--->
-<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:background="@drawable/appwidget_photo_border">
-    <RelativeLayout
-            android:layout_width="@dimen/stack_photo_width"
-            android:layout_height="@dimen/stack_photo_height"
-            android:background="@android:color/darker_gray">
-        <ProgressBar
-                android:id="@+id/appwidget_loading_item"
-                android:layout_centerInParent="true"
-                android:layout_height="wrap_content"
-                android:layout_width="wrap_content" />
-    </RelativeLayout>
-</FrameLayout>
diff --git a/res/layout/appwidget_main.xml b/res/layout/appwidget_main.xml
deleted file mode 100644
index 0accabb..0000000
--- a/res/layout/appwidget_main.xml
+++ /dev/null
@@ -1,42 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2011 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.
--->
-<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
-        android:layout_width="match_parent"
-        android:layout_height="match_parent">
-    <RelativeLayout
-            android:id="@+id/appwidget_empty_view"
-            android:layout_width="match_parent"
-            android:layout_height="match_parent"
-            android:visibility="gone">
-        <FrameLayout
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
-                android:layout_centerInParent="true"
-                android:background="@drawable/appwidget_photo_border">
-            <TextView
-                    android:id="@+id/appwidget_photo_item"
-                    android:layout_width="@dimen/stack_photo_width"
-                    android:layout_height="@dimen/stack_photo_height"
-                    android:gravity="center"
-                    android:text="@string/appwidget_empty_text"/>
-        </FrameLayout>
-    </RelativeLayout>
-    <StackView
-            android:id="@+id/appwidget_stack_view"
-            android:layout_width="match_parent"
-            android:layout_height="match_parent"
-            android:loopViews="true" />
-</FrameLayout>
diff --git a/res/layout/appwidget_photo_item.xml b/res/layout/appwidget_photo_item.xml
deleted file mode 100644
index a56a6d7..0000000
--- a/res/layout/appwidget_photo_item.xml
+++ /dev/null
@@ -1,27 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2011 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.
--->
-<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:layout_centerHorizontal="true"
-        android:background="@drawable/appwidget_photo_border">
-    <ImageView
-            android:id="@+id/appwidget_photo_item"
-            android:layout_height="wrap_content"
-            android:layout_width="wrap_content"
-            android:scaleType="fitCenter"
-            android:adjustViewBounds="true" />
-</FrameLayout>
diff --git a/res/layout/bg_replacement_training_message.xml b/res/layout/bg_replacement_training_message.xml
deleted file mode 100644
index 8d881d6..0000000
--- a/res/layout/bg_replacement_training_message.xml
+++ /dev/null
@@ -1,56 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2011 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.
--->
-
-<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
-        android:id="@+id/bg_replace_message_frame"
-        android:layout_height="match_parent"
-        android:layout_width="match_parent"
-        android:visibility="gone"
-        android:onClick="onProtectiveCurtainClick"
-        android:background="#77000000">
-    <com.android.camera.ui.RotateLayout
-            android:id="@+id/bg_replace_message"
-            android:layout_height="wrap_content"
-            android:layout_width="wrap_content"
-            android:layout_centerInParent="true">
-        <LinearLayout
-                android:layout_height="wrap_content"
-                android:layout_width="wrap_content"
-                android:orientation="vertical"
-                android:background="@drawable/dialog_full_holo_dark">
-            <TextView
-                    android:layout_width="wrap_content"
-                    android:layout_height="wrap_content"
-                    android:textAppearance="?android:attr/textAppearanceMedium"
-                    android:text="@string/bg_replacement_message"
-                    android:padding="32dp" />
-
-            <View
-                    android:layout_width="match_parent"
-                    android:layout_height="1dp"
-                    android:background="#aaaaaa" />
-
-            <Button android:layout_width="match_parent"
-                    android:layout_height="48dip"
-                    android:layout_gravity="center"
-                    android:textAppearance="?android:attr/textAppearanceMedium"
-                    style="?android:attr/borderlessButtonStyle"
-                    android:text="@android:string/cancel"
-                    android:onClick="onCancelBgTraining"
-                    android:contentDescription="@android:string/cancel" />
-        </LinearLayout>
-    </com.android.camera.ui.RotateLayout>
-</RelativeLayout>
diff --git a/res/layout/choose_widget_type.xml b/res/layout/choose_widget_type.xml
deleted file mode 100644
index 5f1739a..0000000
--- a/res/layout/choose_widget_type.xml
+++ /dev/null
@@ -1,54 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2011 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.
--->
-
-<RadioGroup xmlns:android="http://schemas.android.com/apk/res/android"
-        android:id="@+id/widget_type"
-        android:paddingLeft="32dp"
-        android:paddingRight="32dp"
-        android:layout_width="match_parent"
-        android:layout_height="match_parent"
-        android:orientation="vertical">
-    <RadioButton android:id="@+id/widget_type_album"
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:layout_weight="1"
-            android:minHeight="48dp"
-            android:text="@string/widget_type_album"/>
-    <RadioButton android:id="@+id/widget_type_photo"
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:layout_weight="1"
-            android:minHeight="48dp"
-            android:text="@string/widget_type_photo"/>
-    <RadioButton android:id="@+id/widget_type_shuffle"
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:layout_weight="1"
-            android:minHeight="48dp"
-            android:text="@string/widget_type_shuffle"/>
-    <View android:layout_width="match_parent"
-            android:layout_height="1dp"
-            android:layout_weight="0"
-            android:layout_marginLeft="16dp"
-            android:layout_marginRight="16dp"
-            android:background="?android:attr/dividerHorizontal" />
-    <Button style="?android:attr/buttonBarButtonStyle"
-            android:id="@+id/cancel"
-            android:layout_weight="0"
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:text="@android:string/cancel" />
-</RadioGroup>
diff --git a/res/layout/crop_activity.xml b/res/layout/crop_activity.xml
deleted file mode 100644
index 9ff223f..0000000
--- a/res/layout/crop_activity.xml
+++ /dev/null
@@ -1,55 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-     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.
--->
-
-<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    android:layout_width="match_parent"
-    android:layout_height="match_parent"
-    android:id="@+id/mainView"
-    android:background="@drawable/filtershow_tiled_background">
-
-    <LinearLayout
-        android:id="@+id/mainPanel"
-        android:layout_width="wrap_content"
-        android:layout_height="match_parent"
-        android:layout_weight="1"
-        android:orientation="vertical" >
-
-        <FrameLayout
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:layout_weight="1" >
-
-            <com.android.gallery3d.filtershow.crop.CropView
-                android:id="@+id/cropView"
-                android:layout_width="match_parent"
-                android:layout_height="wrap_content" />
-
-            <ProgressBar
-                android:id="@+id/loading"
-                style="@android:style/Widget.Holo.ProgressBar.Large"
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
-                android:layout_gravity="center"
-                android:indeterminate="true"
-                android:indeterminateOnly="true"
-                android:background="@android:color/transparent" />
-
-        </FrameLayout>
-
-    </LinearLayout>
-
-</FrameLayout>
diff --git a/res/layout/cropimage.xml b/res/layout/cropimage.xml
deleted file mode 100644
index c434fb6..0000000
--- a/res/layout/cropimage.xml
+++ /dev/null
@@ -1,21 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2007 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.
--->
-
-<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
-        android:layout_width="match_parent"
-        android:layout_height="match_parent">
-    <include layout="@layout/gl_root_group"/>
-</FrameLayout>
diff --git a/res/layout/details.xml b/res/layout/details.xml
deleted file mode 100644
index dfda0ee..0000000
--- a/res/layout/details.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2006 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.
--->
-
-<TextView xmlns:android="http://schemas.android.com/apk/res/android"
-    android:id="@android:id/text1"
-    android:layout_width="match_parent"
-    android:layout_height="wrap_content"
-    android:textAppearance="?android:attr/textAppearanceMedium"
-    android:gravity="left"
-/>
diff --git a/res/layout/details_list.xml b/res/layout/details_list.xml
deleted file mode 100644
index b80ab6c..0000000
--- a/res/layout/details_list.xml
+++ /dev/null
@@ -1,22 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2011 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.
--->
-
-<ListView xmlns:android="http://schemas.android.com/apk/res/android"
-    android:layout_width="match_parent"
-    android:layout_height="wrap_content"
-    android:padding="16dp"
-    android:dividerHeight="8dp"
-/>
diff --git a/res/layout/dialog_picker.xml b/res/layout/dialog_picker.xml
deleted file mode 100644
index ccc5121..0000000
--- a/res/layout/dialog_picker.xml
+++ /dev/null
@@ -1,38 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2010 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.
--->
-
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-        android:orientation="vertical"
-        android:layout_width="match_parent"
-        android:layout_height="match_parent">
-    <FrameLayout
-            android:layout_weight="1"
-            android:layout_width="match_parent"
-            android:layout_height="0dp">
-        <include layout="@layout/gl_root_group" />
-    </FrameLayout>
-    <ImageView android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:layout_marginLeft="16dp"
-            android:layout_marginRight="16dp"
-            android:background="@drawable/list_divider_holo_dark" />
-    <Button style="?android:attr/buttonBarButtonStyle"
-            android:id="@+id/cancel"
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:text="@android:string/cancel"
-            android:visibility="gone" />
-</LinearLayout>
diff --git a/res/layout/editor_grad_button.xml b/res/layout/editor_grad_button.xml
deleted file mode 100644
index 4d1b10b..0000000
--- a/res/layout/editor_grad_button.xml
+++ /dev/null
@@ -1,48 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-     Copyright (C) 2013 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.
--->
-
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    android:layout_width="wrap_content"
-    android:layout_height="wrap_content"
-    android:layout_weight="1"
-    android:layout_alignParentTop="true"
-    android:layout_marginLeft="26dp"
-    android:layout_marginTop="21dp"
-    android:orientation="horizontal" >
-
-  <com.android.gallery3d.filtershow.ui.FramedTextButton
-      android:id="@+id/editorGradButton"
-      android:layout_width="84dip"
-      android:layout_height="84dip"
-      android:layout_gravity="center_vertical|left"
-      android:background="@drawable/filtershow_button_background"
-      android:scaleType="centerInside"
-      android:visibility="visible"
-      android:text="@string/editor_grad_style" />
-
-  <ToggleButton
-      android:id="@+id/editor_grad_new"
-      android:layout_width="84dip"
-      android:layout_height="84dip"
-      android:layout_gravity="center_vertical|left"
-      android:background="@drawable/filtershow_grad_button"
-      android:scaleType="centerInside"
-      android:visibility="visible"
-      android:textOff="@string/editor_grad_new"
-      android:textOn="@string/editor_grad_new" />
-
-</LinearLayout>
\ No newline at end of file
diff --git a/res/layout/filtershow_actionbar.xml b/res/layout/filtershow_actionbar.xml
deleted file mode 100644
index 5f0aa3f..0000000
--- a/res/layout/filtershow_actionbar.xml
+++ /dev/null
@@ -1,27 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-     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.
--->
-<TextView xmlns:android="http://schemas.android.com/apk/res/android"
-    android:layout_width="wrap_content"
-    android:layout_height="match_parent"
-    android:background="@drawable/filtershow_button_background"
-    android:id="@+id/filtershow_done"
-    android:textAllCaps="true"
-    android:text="@string/save"
-    android:gravity="center_vertical"
-    android:textSize="14sp"
-    android:drawableLeft="@drawable/menu_save_photo"
-    android:drawablePadding="8dip" />
\ No newline at end of file
diff --git a/res/layout/filtershow_activity.xml b/res/layout/filtershow_activity.xml
deleted file mode 100644
index f5684ff..0000000
--- a/res/layout/filtershow_activity.xml
+++ /dev/null
@@ -1,87 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-     Copyright (C) 2013 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.
--->
-
-<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
-             android:layout_width="match_parent"
-             android:layout_height="match_parent"
-             android:id="@+id/mainView"
-             android:background="@drawable/filtershow_tiled_background">
-
-    <LinearLayout
-            android:layout_width="match_parent"
-            android:layout_height="match_parent"
-            android:orientation="vertical">
-
-        <LinearLayout
-                android:layout_weight="1"
-                android:layout_width="match_parent"
-                android:layout_height="wrap_content"
-                android:orientation="horizontal">
-
-            <FrameLayout
-                    android:id="@+id/editorContainer"
-                    android:layout_width="match_parent"
-                    android:layout_height="wrap_content"
-                    android:layout_weight="1"/>
-
-            <com.android.gallery3d.filtershow.imageshow.ImageShow
-                    android:id="@+id/imageShow"
-                    android:layout_width="match_parent"
-                    android:layout_height="wrap_content"
-                    android:layout_weight="1" />
-
-        </LinearLayout>
-
-        <com.android.gallery3d.filtershow.CenteredLinearLayout
-                xmlns:custom="http://schemas.android.com/apk/res/com.android.gallery3d"
-                android:id="@+id/mainPanel"
-                android:layout_width="match_parent"
-                android:layout_height="wrap_content"
-                android:layout_gravity="center|bottom"
-                custom:max_width="650dip"
-                android:orientation="vertical" >
-
-            <FrameLayout android:id="@+id/main_panel_container"
-                         android:layout_gravity="center"
-                         android:layout_width="match_parent"
-                         android:layout_height="0dip"
-                         android:layout_weight="1" />
-
-            <FrameLayout
-                    android:layout_gravity="bottom"
-                    android:layout_width="match_parent"
-                    android:layout_height="wrap_content"
-                    android:visibility="gone">
-
-
-                <ProgressBar
-                        android:id="@+id/loading"
-                        style="@android:style/Widget.Holo.ProgressBar.Large"
-                        android:layout_width="wrap_content"
-                        android:layout_height="wrap_content"
-                        android:layout_gravity="center"
-                        android:indeterminate="true"
-                        android:indeterminateOnly="true"
-                        android:background="@color/background_screen"/>
-
-            </FrameLayout>
-
-        </com.android.gallery3d.filtershow.CenteredLinearLayout>
-
-    </LinearLayout>
-
-</FrameLayout>
diff --git a/res/layout/filtershow_category_panel.xml b/res/layout/filtershow_category_panel.xml
deleted file mode 100644
index c1b8bbe..0000000
--- a/res/layout/filtershow_category_panel.xml
+++ /dev/null
@@ -1,62 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-     Copyright (C) 2013 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.
--->
-
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    android:layout_width="match_parent"
-    android:layout_height="48dip"
-    android:background="@color/background_main_toolbar" >
-
-    <ImageButton
-        android:id="@+id/fxButton"
-        android:layout_width="@dimen/thumbnail_size"
-        android:layout_height="match_parent"
-        android:layout_weight="1"
-        android:background="@drawable/filtershow_button_background"
-        android:scaleType="centerInside"
-        android:src="@drawable/ic_photoeditor_effects" />
-
-    <ImageButton
-        android:id="@+id/borderButton"
-        android:layout_width="@dimen/thumbnail_size"
-        android:layout_height="match_parent"
-        android:layout_weight="1"
-        android:background="@drawable/filtershow_button_background"
-        android:padding="2dip"
-        android:scaleType="centerInside"
-        android:src="@drawable/ic_photoeditor_border" />
-
-    <ImageButton
-        android:id="@+id/geometryButton"
-        android:layout_width="@dimen/thumbnail_size"
-        android:layout_height="match_parent"
-        android:layout_weight="1"
-        android:background="@drawable/filtershow_button_background"
-        android:padding="2dip"
-        android:scaleType="centerInside"
-        android:src="@drawable/ic_photoeditor_fix" />
-
-    <ImageButton
-        android:id="@+id/colorsButton"
-        android:layout_width="@dimen/thumbnail_size"
-        android:layout_height="match_parent"
-        android:layout_weight="1"
-        android:background="@drawable/filtershow_button_background"
-        android:padding="2dip"
-        android:scaleType="centerInside"
-        android:src="@drawable/ic_photoeditor_color" />
-
-</LinearLayout>
\ No newline at end of file
diff --git a/res/layout/filtershow_category_panel_new.xml b/res/layout/filtershow_category_panel_new.xml
deleted file mode 100644
index e98f29e..0000000
--- a/res/layout/filtershow_category_panel_new.xml
+++ /dev/null
@@ -1,41 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-     Copyright (C) 2013 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.
--->
-
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-              xmlns:custom="http://schemas.android.com/apk/res/com.android.gallery3d"
-              android:orientation="horizontal"
-              android:layout_width="match_parent"
-              android:layout_height="wrap_content">
-
-    <HorizontalScrollView
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:scrollbars="none"
-            android:background="@color/background_main_toolbar" >
-
-        <com.android.gallery3d.filtershow.category.CategoryTrack
-                android:id="@+id/listItems"
-                android:layout_width="match_parent"
-                android:layout_height="@dimen/category_panel_height"
-                custom:iconSize="@dimen/category_panel_icon_size"
-                android:divider="@android:color/transparent"
-                android:dividerPadding="8dip"
-                />
-
-    </HorizontalScrollView>
-
-</LinearLayout>
\ No newline at end of file
diff --git a/res/layout/filtershow_color_gird.xml b/res/layout/filtershow_color_gird.xml
deleted file mode 100644
index 2dbbc5f..0000000
--- a/res/layout/filtershow_color_gird.xml
+++ /dev/null
@@ -1,203 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-     Copyright (C) 2013 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.
--->
-
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    android:layout_width="match_parent"
-    android:layout_height="match_parent"
-    android:orientation="vertical" >
-
-    <TextView
-        android:id="@+id/textView1"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content" />
-
-    <TableLayout
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content" >
-
-        <TableRow
-            android:id="@+id/tableRow1"
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content" >
-
-            <Button
-                android:id="@+id/cp_grid_button01"
-                android:layout_width="0dip"
-                android:layout_height="wrap_content"
-                android:layout_weight="1"
-                android:background="@drawable/filtershow_color_picker_circle" />
-
-            <Button
-                android:id="@+id/button2"
-                android:layout_width="0dip"
-                android:layout_height="wrap_content"
-                android:layout_weight="1"
-                android:background="@drawable/filtershow_color_picker_circle" />
-
-            <Button
-                android:id="@+id/button03"
-                android:layout_width="0dip"
-                android:layout_height="wrap_content"
-                android:layout_weight="1"
-                android:background="@drawable/filtershow_color_picker_circle" />
-
-            <Button
-                android:id="@+id/button04"
-                android:layout_width="0dip"
-                android:layout_height="wrap_content"
-                android:layout_weight="1"
-                android:background="@drawable/filtershow_color_picker_circle" />
-
-            <Button
-                android:id="@+id/button05"
-                android:layout_width="0dip"
-                android:layout_height="wrap_content"
-                android:layout_weight="1"
-                android:background="@drawable/filtershow_color_picker_circle" />
-        </TableRow>
-
-        <TableRow
-            android:id="@+id/tableRow2"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content" >
-
-            <Button
-                android:id="@+id/Button06"
-                android:layout_width="0dip"
-                android:layout_height="wrap_content"
-                android:layout_weight="1"
-                android:background="@drawable/filtershow_color_picker_circle" />
-
-            <Button
-                android:id="@+id/button07"
-                android:layout_width="0dip"
-                android:layout_height="wrap_content"
-                android:layout_weight="1"
-                android:background="@drawable/filtershow_color_picker_circle" />
-
-            <Button
-                android:id="@+id/button08"
-                android:layout_width="0dip"
-                android:layout_height="wrap_content"
-                android:layout_weight="1"
-                android:background="@drawable/filtershow_color_picker_circle" />
-
-            <Button
-                android:id="@+id/button09"
-                android:layout_width="0dip"
-                android:layout_height="wrap_content"
-                android:layout_weight="1"
-                android:background="@drawable/filtershow_color_picker_circle" />
-
-            <Button
-                android:id="@+id/button10"
-                android:layout_width="0dip"
-                android:layout_height="wrap_content"
-                android:layout_weight="1"
-                android:background="@drawable/filtershow_color_picker_circle" />
-        </TableRow>
-
-        <TableRow
-            android:id="@+id/tableRow3"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content" >
-
-            <Button
-                android:id="@+id/Button11"
-                android:layout_width="0dip"
-                android:layout_height="wrap_content"
-                android:layout_weight="1"
-                android:background="@drawable/filtershow_color_picker_circle" />
-
-            <Button
-                android:id="@+id/button12"
-                android:layout_width="0dip"
-                android:layout_height="wrap_content"
-                android:layout_weight="1"
-                android:background="@drawable/filtershow_color_picker_circle" />
-
-            <Button
-                android:id="@+id/button13"
-                android:layout_width="0dip"
-                android:layout_height="wrap_content"
-                android:layout_weight="1"
-                android:background="@drawable/filtershow_color_picker_circle" />
-
-            <Button
-                android:id="@+id/button14"
-                android:layout_width="0dip"
-                android:layout_height="wrap_content"
-                android:layout_weight="1"
-                android:background="@drawable/filtershow_color_picker_circle" />
-
-            <Button
-                android:id="@+id/button15"
-                android:layout_width="0dip"
-                android:layout_height="wrap_content"
-                android:layout_weight="1"
-                android:background="@drawable/filtershow_color_picker_circle" />
-        </TableRow>
-
-        <TableRow
-            android:id="@+id/tableRow4"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content" >
-
-            <Button
-                android:id="@+id/Button16"
-                android:layout_width="0dip"
-                android:layout_height="wrap_content"
-                android:layout_weight="1"
-                android:background="@drawable/filtershow_color_picker_circle" />
-
-            <Button
-                android:id="@+id/button17"
-                android:layout_width="0dip"
-                android:layout_height="wrap_content"
-                android:layout_weight="1"
-                android:background="@drawable/filtershow_color_picker_circle" />
-
-            <Button
-                android:id="@+id/button18"
-                android:layout_width="0dip"
-                android:layout_height="wrap_content"
-                android:layout_weight="1"
-                android:background="@drawable/filtershow_color_picker_circle" />
-
-            <Button
-                android:id="@+id/button19"
-                android:layout_width="0dip"
-                android:layout_height="wrap_content"
-                android:layout_weight="1"
-                android:background="@drawable/filtershow_color_picker_circle" />
-
-            <Button
-                android:id="@+id/button20"
-                android:layout_width="0dip"
-                android:layout_height="wrap_content"
-                android:layout_weight="1"
-                android:background="@drawable/filtershow_color_picker_circle" />
-        </TableRow>
-    </TableLayout>
-
-    <Button
-        android:id="@+id/filtershow_cp_custom"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:text="@string/color_pick_select" />
-
-</LinearLayout>
\ No newline at end of file
diff --git a/res/layout/filtershow_color_picker.xml b/res/layout/filtershow_color_picker.xml
deleted file mode 100644
index fc49729..0000000
--- a/res/layout/filtershow_color_picker.xml
+++ /dev/null
@@ -1,58 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-     Copyright (C) 2013 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.
--->
-
-<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:tools="http://schemas.android.com/tools"
-    android:id="@+id/RelativeLayout1"
-    android:layout_width="match_parent"
-    android:layout_height="match_parent"
-    android:background="@color/default_background"
-    tools:context=".ColorPickerActivity" >
-
-    <com.android.gallery3d.filtershow.colorpicker.ColorRectView
-        android:id="@+id/colorRectView"
-        android:layout_width="fill_parent"
-        android:layout_height="fill_parent"
-        android:layout_marginLeft="10dp"
-        android:layout_marginTop="10dp"
-        android:layout_marginBottom="10dp"
-        android:layout_marginRight="1dp"
-        android:layout_above="@+id/colorOpacityView"
-        android:layout_toLeftOf="@+id/colorValueView" />
-
-    <com.android.gallery3d.filtershow.colorpicker.ColorValueView
-        android:id="@+id/colorValueView"
-               android:layout_width="90dp"
-        android:layout_height="fill_parent"
-        android:layout_alignParentRight = "true"
-        android:layout_above="@+id/colorOpacityView"  />
-
-    <com.android.gallery3d.filtershow.colorpicker.ColorOpacityView
-        android:id="@+id/colorOpacityView"
-       android:layout_width="match_parent"
-        android:layout_height="90dp"
-         android:layout_above="@+id/btnSelect" />
-
-    <Button
-        android:id="@+id/btnSelect"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:text="@string/color_pick_select"
-        android:layout_alignParentBottom = "true"
-        />
-
-</RelativeLayout>
\ No newline at end of file
diff --git a/res/layout/filtershow_control_action_slider.xml b/res/layout/filtershow_control_action_slider.xml
deleted file mode 100644
index a3ef3ed..0000000
--- a/res/layout/filtershow_control_action_slider.xml
+++ /dev/null
@@ -1,55 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-     Copyright (C) 2013 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.
--->
-
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:app="http://schemas.android.com/apk/res/com.example.imagefilterharness"
-    android:layout_width="match_parent"
-    android:layout_height="match_parent"
-    android:orientation="horizontal" >
-
-    <ImageButton
-        android:id="@+id/leftActionButton"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:layout_gravity="left|center_vertical"
-        android:scaleType="centerInside"
-        android:layout_weight="0"
-        android:background="@drawable/filtershow_button_background"
-        android:src="@drawable/filtershow_addpoint"
-        android:paddingBottom="8dp"  />
-
-    <SeekBar
-        android:id="@+id/controlValueSeekBar"
-        android:layout_width="0dip"
-        android:layout_height="wrap_content"
-        android:layout_gravity="center_vertical"
-        android:layout_weight="1"
-        style="@style/FilterShowSlider" />
-
-    <ImageButton
-        android:id="@+id/rightActionButton"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:layout_gravity="left|center_vertical"
-        android:scaleType="centerInside"
-        android:layout_weight="0"
-        android:background="@drawable/filtershow_button_background"
-        android:src="@drawable/ic_menu_trash_holo_light"
-        android:paddingBottom="8dp"  />
-
-</LinearLayout>
-
diff --git a/res/layout/filtershow_control_style_chooser.xml b/res/layout/filtershow_control_style_chooser.xml
deleted file mode 100644
index a5bc984..0000000
--- a/res/layout/filtershow_control_style_chooser.xml
+++ /dev/null
@@ -1,37 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-     Copyright (C) 2013 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.
--->
-
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:app="http://schemas.android.com/apk/res/com.example.imagefilterharness"
-    android:layout_width="match_parent"
-    android:layout_height="match_parent"
-    android:orientation="horizontal" >
-            <HorizontalScrollView
-                android:id="@+id/scrollList"
-                android:layout_width="match_parent"
-                android:layout_height="match_parent"
-                android:scrollbars="none" >
-
-                <LinearLayout
-                    android:id="@+id/listStyles"
-                    android:layout_width="wrap_content"
-                    android:layout_height="match_parent"
-                    android:orientation="horizontal" >
-                </LinearLayout>
-            </HorizontalScrollView>
-</LinearLayout>
-
diff --git a/res/layout/filtershow_control_title_slider.xml b/res/layout/filtershow_control_title_slider.xml
deleted file mode 100644
index 584e015..0000000
--- a/res/layout/filtershow_control_title_slider.xml
+++ /dev/null
@@ -1,43 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-     Copyright (C) 2013 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.
--->
-
-<GridLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    android:layout_width="match_parent"
-    android:layout_height="wrap_content"
-    android:columnCount="2"
-    android:orientation="horizontal" >
-
-    <TextView
-        android:id="@+id/controlName"
-        android:layout_gravity="left"
-        android:layout_marginLeft="8dip" />
-
-    <TextView
-        android:id="@+id/controlValue"
-        android:layout_gravity="right"
-        android:layout_marginRight="8dip"
-        android:textStyle="bold" />
-
-    <SeekBar
-        android:id="@+id/controlValueSeekBar"
-        android:layout_width="match_parent"
-        android:layout_column="0"
-        android:layout_columnSpan="2"
-        android:layout_gravity="fill_horizontal"
-        style="@style/FilterShowSlider" />
-</GridLayout>
-
diff --git a/res/layout/filtershow_cp_custom_title.xml b/res/layout/filtershow_cp_custom_title.xml
deleted file mode 100644
index cef8b6c..0000000
--- a/res/layout/filtershow_cp_custom_title.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-     Copyright (C) 2013 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.
--->
-
-<TextView xmlns:android="http://schemas.android.com/apk/res/android"
-    android:id="@+id/customTitle"
-    android:text="@string/color_pick_title"
-    android:layout_width="match_parent"
-    android:layout_height="match_parent"
-    android:gravity="center"
-    android:layout_marginLeft="20dp"
-    android:layout_marginRight="20dp" >
-</TextView>
\ No newline at end of file
diff --git a/res/layout/filtershow_crop_button.xml b/res/layout/filtershow_crop_button.xml
deleted file mode 100644
index b42d6b6..0000000
--- a/res/layout/filtershow_crop_button.xml
+++ /dev/null
@@ -1,27 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-     Copyright (C) 2013 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.
--->
-
-<com.android.gallery3d.filtershow.ui.FramedTextButton
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    android:id="@+id/cropUtilityButton"
-    android:layout_width="84dip"
-    android:layout_height="84dip"
-    android:layout_gravity="center_vertical|left"
-    android:background="@drawable/filtershow_button_background"
-    android:scaleType="centerInside"
-    android:visibility="gone"
-    android:text="@string/aspectNone_effect" />
\ No newline at end of file
diff --git a/res/layout/filtershow_curves_button.xml b/res/layout/filtershow_curves_button.xml
deleted file mode 100644
index 31e8aed..0000000
--- a/res/layout/filtershow_curves_button.xml
+++ /dev/null
@@ -1,27 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-     Copyright (C) 2013 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.
--->
-
-<com.android.gallery3d.filtershow.ui.FramedTextButton
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    android:id="@+id/curvesUtilityButton"
-    android:layout_width="84dip"
-    android:layout_height="84dip"
-    android:layout_gravity="center_vertical|left"
-    android:background="@drawable/filtershow_button_background"
-    android:scaleType="centerInside"
-    android:visibility="gone"
-    android:text="@string/curves_channel_rgb" />
diff --git a/res/layout/filtershow_default_editor.xml b/res/layout/filtershow_default_editor.xml
deleted file mode 100644
index b261ea3..0000000
--- a/res/layout/filtershow_default_editor.xml
+++ /dev/null
@@ -1,30 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-     Copyright (C) 2013 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.
--->
-
-<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:iconbutton="http://schemas.android.com/apk/res/com.android.gallery3d"
-    android:id="@+id/basicEditor"
-    android:layout_width="match_parent"
-    android:layout_height="wrap_content"
-    android:layout_weight="1" >
-
-    <com.android.gallery3d.filtershow.imageshow.ImageShow
-        android:id="@+id/imageShow"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content" />
-
- </FrameLayout>
\ No newline at end of file
diff --git a/res/layout/filtershow_draw_button.xml b/res/layout/filtershow_draw_button.xml
deleted file mode 100644
index dba8100..0000000
--- a/res/layout/filtershow_draw_button.xml
+++ /dev/null
@@ -1,27 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-     Copyright (C) 2013 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.
--->
-
-<com.android.gallery3d.filtershow.ui.FramedTextButton
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    android:id="@+id/drawUtilityButton"
-    android:layout_width="84dip"
-    android:layout_height="84dip"
-    android:layout_gravity="center_vertical|left"
-    android:background="@drawable/filtershow_button_background"
-    android:scaleType="centerInside"
-    android:visibility="gone"
-    android:text="@string/draw_style" />
diff --git a/res/layout/filtershow_draw_size.xml b/res/layout/filtershow_draw_size.xml
deleted file mode 100644
index 068493e..0000000
--- a/res/layout/filtershow_draw_size.xml
+++ /dev/null
@@ -1,36 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-     Copyright (C) 2013 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.
--->
-
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    android:layout_width="match_parent"
-    android:layout_height="match_parent"
-    android:dividerPadding="20dp"
-    android:gravity="center_horizontal"
-    android:orientation="vertical" >
-
-    <SeekBar
-        android:id="@+id/sizeSeekBar"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content" />
-
-    <Button
-        android:id="@+id/sizeAcceptButton"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:text="@string/draw_size_accept" />
-
-</LinearLayout>
\ No newline at end of file
diff --git a/res/layout/filtershow_editor_panel.xml b/res/layout/filtershow_editor_panel.xml
deleted file mode 100644
index a6da46a..0000000
--- a/res/layout/filtershow_editor_panel.xml
+++ /dev/null
@@ -1,117 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-     Copyright (C) 2013 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.
--->
-
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    android:id="@+id/top"
-    android:layout_width="match_parent"
-    android:layout_height="wrap_content"
-    android:orientation="vertical"
-    android:visibility="visible" >
-
-    <LinearLayout
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:orientation="vertical">
-
-        <LinearLayout
-                android:id="@+id/controlArea"
-                android:layout_width="match_parent"
-                android:layout_height="wrap_content"
-                android:orientation="horizontal"
-                android:layout_alignParentBottom="true"
-                android:visibility="visible">
-
-            <SeekBar
-                    android:id="@+id/primarySeekBar"
-                    android:layout_width="match_parent"
-                    android:layout_height="wrap_content"
-                    android:layout_gravity="center_vertical"
-                    style="@style/FilterShowSlider"/>
-
-        </LinearLayout>
-
-        <LinearLayout
-                android:layout_width="match_parent"
-                android:layout_height="56dip"
-                android:background="@color/background_main_toolbar"
-                android:orientation="horizontal"
-                android:baselineAligned="false"
-                android:visibility="visible">
-
-            <ImageButton
-                    android:id="@+id/cancelFilter"
-                    android:layout_width="wrap_content"
-                    android:layout_height="fill_parent"
-                    android:layout_gravity="left|center_vertical"
-                    android:background="@android:color/transparent"
-                    android:layout_weight=".1"
-                    android:gravity="center"
-                    android:src="@drawable/ic_menu_cancel_holo_light"
-                    android:textSize="18dip"/>
-
-            <ImageView
-                    android:layout_width="2dp"
-                    android:layout_height="fill_parent"
-                    android:src="@drawable/filtershow_vertical_bar"/>
-
-            <LinearLayout
-                    android:id="@+id/panelAccessoryViewList"
-                    android:layout_width="wrap_content"
-                    android:layout_height="match_parent"
-                    android:layout_weight="1"
-                    android:orientation="horizontal"
-                    android:visibility="visible">
-
-                <com.android.gallery3d.filtershow.editors.SwapButton
-                        android:id="@+id/applyEffect"
-                        android:layout_width="fill_parent"
-                        android:layout_height="fill_parent"
-                        android:layout_gravity="center"
-                        android:background="@android:color/transparent"
-                        android:gravity="center"
-                        android:text="@string/apply_effect"
-                        android:textSize="18dip"
-                        android:drawableRight="@drawable/filtershow_menu_marker"
-                        android:textAllCaps="true" />
-
-            </LinearLayout>
-
-            <ImageView
-                    android:layout_width="2dp"
-                    android:layout_height="fill_parent"
-                    android:src="@drawable/filtershow_vertical_bar"/>
-
-            <ImageButton
-                    android:id="@+id/applyFilter"
-                    android:layout_width="wrap_content"
-                    android:layout_height="fill_parent"
-                    android:layout_gravity="right|center_vertical"
-                    android:layout_weight=".1"
-                    android:background="@android:color/transparent"
-                    android:gravity="center"
-                    android:src="@drawable/ic_menu_done_holo_light"
-                    android:textSize="18dip"/>
-        </LinearLayout>
-
-        <FrameLayout android:id="@+id/state_panel_container"
-                     android:layout_width="match_parent"
-                     android:layout_height="wrap_content"
-                     android:visibility="visible" />
-
-    </LinearLayout>
-
-</LinearLayout>
diff --git a/res/layout/filtershow_export_dialog.xml b/res/layout/filtershow_export_dialog.xml
deleted file mode 100644
index 2021075..0000000
--- a/res/layout/filtershow_export_dialog.xml
+++ /dev/null
@@ -1,80 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-     Copyright (C) 2013 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.
--->
-
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-              android:orientation="vertical"
-              android:layout_width="match_parent"
-              android:layout_height="wrap_content"
-              android:divider="?android:dividerVertical"
-              android:showDividers="middle">
-
-    <TextView
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:layout_gravity="center_horizontal|center_vertical"
-        android:layout_margin="7dp"
-        android:text="@string/select_compression"/>
-
-    <LinearLayout
-            android:orientation="horizontal"
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content">
-
-        <SeekBar
-                android:id="@+id/qualitySeekBar"
-                android:layout_width="0dp"
-                android:layout_height="wrap_content"
-                android:layout_weight="3"
-                android:layout_margin="7dp"
-                android:max="100"
-                android:progress="100"/>
-
-        <TextView
-                android:id="@+id/qualityTextView"
-                android:layout_width="0dp"
-                android:layout_height="wrap_content"
-                android:layout_weight="1"
-                android:layout_marginLeft="7dp"
-                android:layout_gravity="center_vertical|center_horizontal"/>
-
-    </LinearLayout>
-
-    <LinearLayout
-            android:orientation="horizontal"
-            android:layout_width="match_parent"
-            android:layout_height="48dp"
-            style="?android:attr/buttonBarStyle">
-
-        <Button
-                android:id="@+id/cancel"
-                android:layout_width="0dp"
-                android:layout_height="match_parent"
-                android:layout_weight="1"
-                android:text="@string/cancel"
-                style="?android:attr/buttonBarButtonStyle" />
-
-        <Button
-                android:id="@+id/done"
-                android:layout_width="0dp"
-                android:layout_height="match_parent"
-                android:layout_weight="1"
-                android:text="@string/done"
-                style="?android:attr/buttonBarButtonStyle"/>
-
-    </LinearLayout>
-
-</LinearLayout>
diff --git a/res/layout/filtershow_grad_editor.xml b/res/layout/filtershow_grad_editor.xml
deleted file mode 100644
index 6c4721e..0000000
--- a/res/layout/filtershow_grad_editor.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-     Copyright (C) 2013 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.
--->
-
-<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    android:id="@+id/gradEditor"
-    android:layout_width="match_parent"
-    android:layout_height="wrap_content"
-    android:layout_weight="1" >
-
-    <com.android.gallery3d.filtershow.imageshow.ImageGrad
-        android:id="@+id/imageShow"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content" />
-
- </FrameLayout>
\ No newline at end of file
diff --git a/res/layout/filtershow_history_operation_row.xml b/res/layout/filtershow_history_operation_row.xml
deleted file mode 100644
index 25a0d26..0000000
--- a/res/layout/filtershow_history_operation_row.xml
+++ /dev/null
@@ -1,47 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- 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.
--->
-
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:tools="http://schemas.android.com/tools"
-    android:layout_width="match_parent"
-    android:layout_height="120dip"
-    android:gravity="center_horizontal"
-    android:orientation="horizontal"
-    android:padding="0dip"
-    android:background="@color/background_main_toolbar">
-
-    <ImageView
-            android:id="@+id/preview"
-            android:layout_width="180dip"
-            android:layout_height="120dip"
-            android:scaleType="centerCrop"
-            android:cropToPadding="true"
-            android:visibility="visible"
-            />
-
-    <TextView
-            xmlns:android="http://schemas.android.com/apk/res/android"
-            android:id="@+id/rowTextView"
-            android:layout_width="wrap_content"
-            android:layout_height="match_parent"
-            android:layout_weight="1"
-            android:gravity="bottom|right"
-            android:padding="10dip"
-            android:textSize="16dip"
-            android:textStyle="bold">
-    </TextView>
-
-</LinearLayout>
\ No newline at end of file
diff --git a/res/layout/filtershow_history_panel.xml b/res/layout/filtershow_history_panel.xml
deleted file mode 100644
index 392e39c..0000000
--- a/res/layout/filtershow_history_panel.xml
+++ /dev/null
@@ -1,64 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-     Copyright (C) 2013 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.
--->
-
-<LinearLayout
-        xmlns:android="http://schemas.android.com/apk/res/android"
-        android:id="@+id/historyPanel"
-        android:layout_width="match_parent"
-        android:layout_height="match_parent"
-        android:orientation="vertical"
-        android:layout_weight="1"
-        android:visibility="gone" >
-
-    <TextView
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:background="@android:color/transparent"
-            android:gravity="center"
-            android:padding="2dip"
-            android:text="@string/history"
-            android:textColor="@android:color/white"
-            android:textSize="24sp"
-            android:textStyle="bold" />
-
-    <ListView
-            android:id="@+id/operationsList"
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:layout_weight="1"
-            android:padding="10dip"
-            android:divider="@android:color/transparent"
-            android:dividerHeight="10dip" />
-
-    <LinearLayout
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:orientation="horizontal" >
-
-        <Button
-                android:id="@+id/resetOperationsButton"
-                style="@style/FilterShowHistoryButton"
-                android:gravity="center"
-                android:text="@string/reset" />
-
-        <Button
-                android:id="@+id/saveOperationsButton"
-                style="@style/FilterShowHistoryButton"
-                android:text="@string/save"
-                android:visibility="gone" />
-    </LinearLayout>
-</LinearLayout>
diff --git a/res/layout/filtershow_main_panel.xml b/res/layout/filtershow_main_panel.xml
deleted file mode 100644
index 53691d3..0000000
--- a/res/layout/filtershow_main_panel.xml
+++ /dev/null
@@ -1,102 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-     Copyright (C) 2013 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.
--->
-
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-              android:layout_width="match_parent"
-              android:layout_height="wrap_content"
-              android:baselineAligned="false"
-              android:orientation="vertical"
-              android:animateLayoutChanges="false"
-              android:visibility="visible"
-              android:background="@color/background_main_toolbar" >
-
-    <FrameLayout android:id="@+id/state_panel_container"
-                 android:layout_width="match_parent"
-                 android:layout_height="wrap_content"
-                 android:visibility="visible"
-                 android:layout_gravity="top"
-                 android:layout_weight="1" />
-
-    <FrameLayout android:id="@+id/category_panel_container"
-                 android:layout_width="wrap_content"
-                 android:visibility="visible"
-                 android:layout_height="0dip"
-                 android:layout_gravity="center"
-                 android:layout_weight="1"/>
-
-    <View
-            android:background="@color/toolbar_separation_line"
-            android:layout_height="1dip"
-            android:layout_width="match_parent"/>
-
-    <com.android.gallery3d.filtershow.CenteredLinearLayout
-            xmlns:custom="http://schemas.android.com/apk/res/com.android.gallery3d"
-            android:id="@+id/bottom_panel"
-            android:layout_width="match_parent"
-            android:layout_height="48dip"
-            android:layout_gravity="center|bottom"
-            custom:max_width="400dip"
-            android:orientation="vertical">
-
-        <LinearLayout android:layout_width="wrap_content"
-                      android:layout_height="match_parent"
-                      android:background="@color/background_main_toolbar">
-
-            <ImageButton
-                    android:id="@+id/fxButton"
-                    android:layout_width="@dimen/thumbnail_size"
-                    android:layout_height="match_parent"
-                    android:layout_weight="1"
-                    android:background="@drawable/filtershow_button_background"
-                    android:scaleType="centerInside"
-                    android:src="@drawable/ic_photoeditor_effects"/>
-
-            <ImageButton
-                    android:id="@+id/borderButton"
-                    android:layout_width="@dimen/thumbnail_size"
-                    android:layout_height="match_parent"
-                    android:layout_weight="1"
-                    android:background="@drawable/filtershow_button_background"
-                    android:padding="2dip"
-                    android:scaleType="centerInside"
-                    android:src="@drawable/ic_photoeditor_border"/>
-
-            <ImageButton
-                    android:id="@+id/geometryButton"
-                    android:layout_width="@dimen/thumbnail_size"
-                    android:layout_height="match_parent"
-                    android:layout_weight="1"
-                    android:background="@drawable/filtershow_button_background"
-                    android:padding="2dip"
-                    android:scaleType="centerInside"
-                    android:src="@drawable/ic_photoeditor_fix"/>
-
-            <ImageButton
-                    android:id="@+id/colorsButton"
-                    android:layout_width="@dimen/thumbnail_size"
-                    android:layout_height="match_parent"
-                    android:layout_weight="1"
-                    android:background="@drawable/filtershow_button_background"
-                    android:padding="2dip"
-                    android:scaleType="centerInside"
-                    android:src="@drawable/ic_photoeditor_color"/>
-
-        </LinearLayout>
-
-    </com.android.gallery3d.filtershow.CenteredLinearLayout>
-
-</LinearLayout>
\ No newline at end of file
diff --git a/res/layout/filtershow_presets_management_dialog.xml b/res/layout/filtershow_presets_management_dialog.xml
deleted file mode 100644
index f6c6fb7..0000000
--- a/res/layout/filtershow_presets_management_dialog.xml
+++ /dev/null
@@ -1,66 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-     Copyright (C) 2013 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.
--->
-
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-              android:orientation="vertical"
-              android:layout_width="match_parent"
-              android:layout_height="wrap_content"
-              android:divider="?android:dividerVertical"
-              android:showDividers="middle">
-
-    <ListView
-            android:id="@+id/listItems"
-            android:orientation="vertical"
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:layout_margin="8dip"
-            android:divider="@android:color/transparent"
-            android:dividerHeight="8dip"/>
-
-    <LinearLayout
-            android:orientation="horizontal"
-            android:layout_width="match_parent"
-            android:layout_height="48dp"
-            style="?android:attr/buttonBarStyle">
-
-        <Button
-                android:id="@+id/cancel"
-                android:layout_width="0dp"
-                android:layout_height="match_parent"
-                android:layout_weight="1"
-                android:text="@string/cancel"
-                style="?android:attr/buttonBarButtonStyle" />
-
-        <Button
-                android:id="@+id/addpreset"
-                android:layout_width="0dp"
-                android:layout_height="match_parent"
-                android:layout_weight="1"
-                android:text="@string/filtershow_save_preset"
-                style="?android:attr/buttonBarButtonStyle"/>
-
-        <Button
-                android:id="@+id/ok"
-                android:layout_width="0dp"
-                android:layout_height="match_parent"
-                android:layout_weight="1"
-                android:text="@string/ok"
-                style="?android:attr/buttonBarButtonStyle"/>
-
-    </LinearLayout>
-
-</LinearLayout>
\ No newline at end of file
diff --git a/res/layout/filtershow_presets_management_row.xml b/res/layout/filtershow_presets_management_row.xml
deleted file mode 100644
index 648e874..0000000
--- a/res/layout/filtershow_presets_management_row.xml
+++ /dev/null
@@ -1,51 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-     Copyright (C) 2013 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.
--->
-
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-              android:orientation="horizontal"
-              android:layout_width="match_parent"
-              android:layout_height="match_parent">
-
-    <ImageView
-            android:id="@+id/imageView"
-            android:layout_weight=".1"
-            android:layout_width="80dip"
-            android:layout_height="80dip"
-            android:scaleType="fitCenter"
-            android:layout_gravity="left|center_vertical"/>
-
-    <EditText
-            android:id="@+id/editView"
-            android:gravity="center"
-            android:textSize="18sp"
-            android:layout_weight="1"
-            android:layout_width="match_parent"
-            android:layout_height="match_parent"
-            android:focusable="true"
-            android:imeOptions="actionDone"
-            android:singleLine="true"/>
-
-    <ImageButton
-            android:id="@+id/deleteUserPreset"
-            android:layout_width="wrap_content"
-            android:layout_height="match_parent"
-            android:layout_gravity="right|center_vertical"
-            android:background="@android:color/transparent"
-            android:layout_weight=".1"
-            android:gravity="center"
-            android:src="@drawable/ic_menu_trash_holo_light"/>
-</LinearLayout>
\ No newline at end of file
diff --git a/res/layout/filtershow_seekbar.xml b/res/layout/filtershow_seekbar.xml
deleted file mode 100644
index 6463ca8..0000000
--- a/res/layout/filtershow_seekbar.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-     Copyright (C) 2013 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.
--->
-
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    android:id="@+id/top"
-    android:layout_width="match_parent"
-    android:layout_height="wrap_content"
-    android:orientation="vertical"
-    android:visibility="visible" >
-
-    <SeekBar
-        android:id="@+id/primarySeekBar"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        style="@style/FilterShowSlider" />
-
-</LinearLayout>
diff --git a/res/layout/filtershow_state_panel.xml b/res/layout/filtershow_state_panel.xml
deleted file mode 100644
index 1f9f970..0000000
--- a/res/layout/filtershow_state_panel.xml
+++ /dev/null
@@ -1,45 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-     Copyright (C) 2013 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.
--->
-
-<LinearLayout
-        xmlns:android="http://schemas.android.com/apk/res/android"
-        android:id="@+id/imageStatePanel"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:orientation="vertical"
-        android:layout_weight="1"
-        android:visibility="visible" >
-
-    <TextView
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:background="@android:color/transparent"
-            android:gravity="center"
-            android:padding="2dip"
-            android:text="@string/imageState"
-            android:textColor="@android:color/white"
-            android:textSize="24sp"
-            android:textStyle="bold" />
-
-    <ListView
-            android:id="@+id/imageStateList"
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:layout_weight="1" >
-    </ListView>
-
-</LinearLayout>
\ No newline at end of file
diff --git a/res/layout/filtershow_state_panel_new.xml b/res/layout/filtershow_state_panel_new.xml
deleted file mode 100644
index d2d59ab..0000000
--- a/res/layout/filtershow_state_panel_new.xml
+++ /dev/null
@@ -1,32 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-              xmlns:custom="http://schemas.android.com/apk/res/com.android.gallery3d"
-              android:orientation="vertical"
-              android:layout_width="match_parent"
-              android:layout_height="wrap_content"
-              android:background="@color/background_main_toolbar">
-
-    <View
-            android:background="@color/toolbar_separation_line"
-            android:layout_height="1dip"
-            android:layout_width="match_parent"/>
-
-    <HorizontalScrollView
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:scrollbars="none">
-
-        <com.android.gallery3d.filtershow.state.StatePanelTrack
-                android:id="@+id/listStates"
-                android:orientation="horizontal"
-                android:layout_width="match_parent"
-                android:layout_height="48dip"
-                custom:elemEndSize="128dip"
-                custom:elemSize="128dip"
-                android:layout_margin="8dip"
-                android:animateLayoutChanges="true" />
-
-    </HorizontalScrollView>
-
-</LinearLayout>
diff --git a/res/layout/filtershow_tiny_planet_editor.xml b/res/layout/filtershow_tiny_planet_editor.xml
deleted file mode 100644
index fd89f99..0000000
--- a/res/layout/filtershow_tiny_planet_editor.xml
+++ /dev/null
@@ -1,30 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-     Copyright (C) 2013 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.
--->
-
-<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:iconbutton="http://schemas.android.com/apk/res/com.android.gallery3d"
-    android:id="@+id/tinyPlanetEditor"
-    android:layout_width="match_parent"
-    android:layout_height="wrap_content"
-    android:layout_weight="1" >
-
-    <com.android.gallery3d.filtershow.imageshow.ImageTinyPlanet
-        android:id="@+id/imageTinyPlanet"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content" />
-
- </FrameLayout>
\ No newline at end of file
diff --git a/res/layout/filtershow_vignette_editor.xml b/res/layout/filtershow_vignette_editor.xml
deleted file mode 100644
index 9c9b4cb..0000000
--- a/res/layout/filtershow_vignette_editor.xml
+++ /dev/null
@@ -1,30 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-     Copyright (C) 2013 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.
--->
-
-<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:iconbutton="http://schemas.android.com/apk/res/com.android.gallery3d"
-    android:id="@+id/vignetteEditor"
-    android:layout_width="match_parent"
-    android:layout_height="wrap_content"
-    android:layout_weight="1" >
-
-    <com.android.gallery3d.filtershow.imageshow.ImageVignette
-        android:id="@+id/imageVignette"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content" />
-
- </FrameLayout>
\ No newline at end of file
diff --git a/res/layout/filtershow_zoom_editor.xml b/res/layout/filtershow_zoom_editor.xml
deleted file mode 100644
index 9813a28..0000000
--- a/res/layout/filtershow_zoom_editor.xml
+++ /dev/null
@@ -1,30 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-     Copyright (C) 2013 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.
--->
-
-<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:iconbutton="http://schemas.android.com/apk/res/com.android.gallery3d"
-    android:id="@+id/basicEditor"
-    android:layout_width="match_parent"
-    android:layout_height="wrap_content"
-    android:layout_weight="1" >
-
-    <com.android.gallery3d.filtershow.imageshow.ImageShow
-        android:id="@+id/imageZoom"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content" />
-
- </FrameLayout>
diff --git a/res/layout/gl_root_group.xml b/res/layout/gl_root_group.xml
deleted file mode 100644
index 76ff33b..0000000
--- a/res/layout/gl_root_group.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- 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.
--->
-
-<merge xmlns:android="http://schemas.android.com/apk/res/android">
-    <com.android.gallery3d.ui.GLRootView
-            android:id="@+id/gl_root_view"
-            android:layout_width="match_parent"
-            android:layout_height="match_parent"/>
-    <View android:id="@+id/gl_root_cover"
-            android:layout_width="match_parent"
-            android:layout_height="match_parent"
-            android:background="@android:color/black"/>
-</merge>
diff --git a/res/layout/ingest_activity_item_list.xml b/res/layout/ingest_activity_item_list.xml
deleted file mode 100644
index f0e91e8..0000000
--- a/res/layout/ingest_activity_item_list.xml
+++ /dev/null
@@ -1,59 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2013 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.
--->
-<merge xmlns:android="http://schemas.android.com/apk/res/android">
-    <com.android.gallery3d.ingest.ui.IngestGridView
-        android:id="@+id/ingest_gridview"
-        android:layout_width="match_parent"
-        android:layout_height="match_parent"
-        android:columnWidth="120dip"
-        android:numColumns="auto_fit"
-        android:fastScrollEnabled="true"
-        android:background="@android:color/background_dark"
-        android:choiceMode="multipleChoiceModal"
-        android:stretchMode="columnWidth"  />
-
-    <android.support.v4.view.ViewPager
-        android:id="@+id/ingest_view_pager"
-        android:layout_width="match_parent"
-        android:layout_height="match_parent"
-        android:background="@android:color/background_dark"
-        android:visibility="invisible" />
-
-    <LinearLayout
-        android:id="@+id/ingest_warning_view"
-        android:layout_width="match_parent"
-        android:layout_height="match_parent"
-        android:layout_margin="20dip"
-        android:gravity="center"
-        android:orientation="horizontal"
-        android:visibility="invisible" >
-
-        <ImageView
-            android:id="@+id/ingest_warning_view_icon"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:layout_gravity="center"
-            android:src="@android:drawable/ic_dialog_alert" />
-
-        <TextView
-            android:id="@+id/ingest_warning_view_text"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:layout_marginLeft="10dip"
-            android:textAppearance="?android:attr/textAppearanceSmall" />
-    </LinearLayout>
-</merge>
-
diff --git a/res/layout/ingest_date_tile.xml b/res/layout/ingest_date_tile.xml
deleted file mode 100644
index 6b5e934..0000000
--- a/res/layout/ingest_date_tile.xml
+++ /dev/null
@@ -1,63 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2013 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.
--->
-<com.android.gallery3d.ingest.ui.DateTileView xmlns:android="http://schemas.android.com/apk/res/android"
-    android:layout_width="match_parent"
-    android:layout_height="match_parent"
-    android:background="@android:color/black" >
-    <GridLayout
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:layout_gravity="center" >
-        <TextView
-            android:id="@+id/date_tile_month"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:layout_column="0"
-            android:layout_row="0"
-            android:layout_gravity="bottom|right"
-            android:layout_marginTop="7sp"
-            android:includeFontPadding="false"
-            android:textSize="16sp"
-            android:textAllCaps="true"
-            android:fontFamily="sans-serif"
-            android:textColor="@color/ingest_date_tile_text" />
-        <TextView
-            android:id="@+id/date_tile_year"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:layout_column="0"
-            android:layout_row="1"
-            android:layout_gravity="top|right"
-            android:includeFontPadding="false"
-            android:textSize="13sp"
-            android:fontFamily="sans-serif-light"
-            android:textColor="@color/ingest_date_tile_text" />
-        <TextView
-            android:id="@+id/date_tile_day"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:layout_column="1"
-            android:layout_row="0"
-            android:layout_rowSpan="2"
-            android:layout_gravity="top|left"
-            android:layout_marginLeft="5sp"
-            android:includeFontPadding="false"
-            android:textSize="44sp"
-            android:textStyle="bold"
-            android:fontFamily="sans-serif"
-            android:textColor="@color/ingest_date_tile_text" />
-    </GridLayout>
-</com.android.gallery3d.ingest.ui.DateTileView>
\ No newline at end of file
diff --git a/res/layout/ingest_fullsize.xml b/res/layout/ingest_fullsize.xml
deleted file mode 100644
index fad596c..0000000
--- a/res/layout/ingest_fullsize.xml
+++ /dev/null
@@ -1,43 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2013 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.
--->
-<com.android.gallery3d.ingest.ui.MtpFullscreenView xmlns:android="http://schemas.android.com/apk/res/android"
-    android:layout_width="match_parent"
-    android:layout_height="match_parent" >
-
-    <ProgressBar
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:layout_centerHorizontal="true"
-        android:layout_centerVertical="true"
-        android:progress="1"
-        android:indeterminate="true"
-        android:indeterminateOnly="true" />
-
-    <com.android.gallery3d.ingest.ui.MtpImageView
-        android:id="@+id/ingest_fullsize_image"
-        android:layout_width="fill_parent"
-        android:layout_height="fill_parent"
-        android:scaleType="matrix" />
-
-    <CheckBox
-        android:id="@+id/ingest_fullsize_image_checkbox"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:layout_alignParentBottom="true"
-        android:layout_alignParentRight="true"
-        android:text="@string/Import" />
-
-</com.android.gallery3d.ingest.ui.MtpFullscreenView>
\ No newline at end of file
diff --git a/res/layout/ingest_thumbnail.xml b/res/layout/ingest_thumbnail.xml
deleted file mode 100644
index 6907149..0000000
--- a/res/layout/ingest_thumbnail.xml
+++ /dev/null
@@ -1,22 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2013 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.
--->
-<com.android.gallery3d.ingest.ui.MtpThumbnailTileView
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    android:layout_width="match_parent"
-    android:layout_height="match_parent"
-    android:scaleType="centerCrop"
-    android:background="@drawable/ingest_item_list_selector">
-</com.android.gallery3d.ingest.ui.MtpThumbnailTileView>
\ No newline at end of file
diff --git a/res/layout/main.xml b/res/layout/main.xml
deleted file mode 100644
index 08e5959..0000000
--- a/res/layout/main.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
-        android:id="@+id/gallery_root"
-        android:orientation="vertical"
-        android:layout_width="match_parent"
-        android:layout_height="match_parent">
-    <include layout="@layout/gl_root_group"/>
-    <FrameLayout android:id="@+id/header"
-            android:visibility="gone"
-            android:layout_alignParentTop="true"
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"/>
-    <FrameLayout android:id="@+id/footer"
-            android:visibility="gone"
-            android:layout_alignParentBottom="true"
-            android:layout_alignParentLeft="true"
-            android:layout_alignParentRight="true"
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"/>
-</RelativeLayout>
diff --git a/res/layout/manage_offline_bar.xml b/res/layout/manage_offline_bar.xml
deleted file mode 100644
index 5c71613..0000000
--- a/res/layout/manage_offline_bar.xml
+++ /dev/null
@@ -1,61 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2011 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.
--->
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-        android:orientation="vertical"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content">
-    <RelativeLayout
-            android:layout_width="fill_parent"
-            android:layout_height="40dp">
-        <TextView android:id="@+id/status"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:layout_centerVertical="true"
-            android:layout_centerHorizontal="true" />
-        <ProgressBar android:id="@+id/progress"
-            style="?android:attr/progressBarStyleHorizontal"
-            android:max="100"
-            android:progress="30"
-            android:secondaryProgress="65"
-            android:layout_marginTop="2dp"
-            android:layout_marginBottom="2dp"
-            android:layout_width="130dp"
-            android:layout_height="4dp"
-            android:layout_below="@id/status"
-            android:layout_centerHorizontal="true"/>
-    </RelativeLayout>
-    <RelativeLayout android:layout_width="fill_parent"
-                android:layout_height="@dimen/manage_cache_bottom_height"
-                android:paddingLeft="16dp"
-                android:paddingRight="16dp"
-                android:background="#1f1f1f">
-        <TextView android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:text="@string/make_available_offline"
-            android:textSize="14sp"
-            android:layout_alignParentLeft="true"
-            android:layout_centerVertical="true"
-            android:gravity="center_vertical"
-            android:drawableLeft="@drawable/ic_menu_make_offline"
-            android:drawablePadding="3dp"/>
-        <Button android:id="@+id/done"
-            android:layout_width="74dp"
-            android:layout_height="match_parent"
-            android:text="@string/done"
-            android:textSize="14sp"
-            android:layout_alignParentRight="true"/>
-    </RelativeLayout>
-</LinearLayout>
diff --git a/res/layout/movie_view.xml b/res/layout/movie_view.xml
deleted file mode 100644
index 75b8dfd..0000000
--- a/res/layout/movie_view.xml
+++ /dev/null
@@ -1,27 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2007 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.
--->
-
-<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
-        android:id="@+id/movie_view_root"
-        android:background="@android:color/black"
-        android:layout_width="match_parent"
-        android:layout_height="match_parent">
-    <VideoView android:id="@+id/surface_view"
-            android:visibility="invisible"
-            android:layout_width="match_parent"
-            android:layout_height="match_parent"
-            android:layout_centerInParent="true" />
-</RelativeLayout>
diff --git a/res/layout/multigrid_content.xml b/res/layout/multigrid_content.xml
deleted file mode 100644
index b1cb145..0000000
--- a/res/layout/multigrid_content.xml
+++ /dev/null
@@ -1,57 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2013 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.
--->
-<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
-        android:layout_width="match_parent"
-        android:layout_height="match_parent">
-
-    <LinearLayout android:id="@+id/progressContainer"
-            android:orientation="vertical"
-            android:layout_width="match_parent"
-            android:layout_height="match_parent"
-            android:visibility="gone"
-            android:gravity="center">
-
-        <ProgressBar style="?android:attr/progressBarStyleLarge"
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content" />
-        <TextView android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
-                android:textAppearance="?android:attr/textAppearanceSmall"
-                android:text="@string/loading"
-                android:paddingTop="4dip"
-                android:singleLine="true" />
-
-    </LinearLayout>
-
-    <FrameLayout android:id="@+id/gridContainer"
-            android:layout_width="match_parent"
-            android:layout_height="match_parent">
-
-        <GridView android:id="@android:id/list"
-                android:layout_width="match_parent"
-                android:layout_height="match_parent"
-                android:choiceMode="multipleChoiceModal"
-                android:numColumns="auto_fit"
-                android:stretchMode="columnWidth"
-                android:drawSelectorOnTop="true" />
-        <TextView android:id="@android:id/empty"
-                android:layout_width="match_parent"
-                android:layout_height="match_parent"
-                android:gravity="center"
-                android:textAppearance="?android:attr/textAppearanceMedium" />
-    </FrameLayout>
-
-</FrameLayout>
\ No newline at end of file
diff --git a/res/layout/photo_frame.xml b/res/layout/photo_frame.xml
deleted file mode 100755
index deadaeb..0000000
--- a/res/layout/photo_frame.xml
+++ /dev/null
@@ -1,32 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2009 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.
--->
-
-<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
-        android:layout_width="match_parent"
-        android:layout_height="match_parent"
-        android:paddingTop="4dp"
-        android:paddingBottom="23dp"
-        android:paddingLeft="12dp"
-        android:paddingRight="12dp">
-    <ImageView android:id="@+id/photo"
-            android:layout_gravity="center"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:adjustViewBounds="true"
-            android:scaleType="fitCenter"
-            android:cropToPadding="true"
-            android:background="@drawable/border_photo_frame_widget"/>
-</FrameLayout>
diff --git a/res/layout/photo_set_item.xml b/res/layout/photo_set_item.xml
deleted file mode 100644
index 0f740fa..0000000
--- a/res/layout/photo_set_item.xml
+++ /dev/null
@@ -1,14 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<FrameLayout
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    android:layout_width="match_parent"
-    android:layout_height="wrap_content"
-    android:background="?android:attr/activatedBackgroundIndicator"
-    android:padding="2dip">
-
-    <com.android.photos.views.SquareImageView
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:id="@+id/thumbnail" />
-
-</FrameLayout>
\ No newline at end of file
diff --git a/res/layout/photopage_bottom_controls.xml b/res/layout/photopage_bottom_controls.xml
deleted file mode 100644
index f3226e6..0000000
--- a/res/layout/photopage_bottom_controls.xml
+++ /dev/null
@@ -1,50 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
-        android:id="@+id/photopage_bottom_controls"
-        android:padding="10dp"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:layout_alignParentBottom="true"
-        android:layout_alignParentLeft="true"
-        android:orientation="horizontal"
-        android:visibility="gone">
-        <ImageButton
-                android:id="@+id/photopage_bottom_control_edit"
-                android:src="@drawable/ic_menu_edit_holo_dark"
-                android:background="@drawable/photopage_bottom_button_background"
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
-                android:layout_alignParentLeft="true"
-                android:layout_alignParentBottom="true"
-                android:paddingTop="5dp"
-                android:paddingBottom="5dp"
-                android:paddingLeft="15dp"
-                android:paddingRight="15dp"
-                android:visibility="gone"/>
-        <ImageButton
-                android:id="@+id/photopage_bottom_control_panorama"
-                android:src="@drawable/ic_view_photosphere"
-                android:background="@drawable/transparent_button_background"
-                android:layout_width="70dp"
-                android:layout_height="70dp"
-                android:layout_centerHorizontal="true"
-                android:layout_alignParentBottom="true"
-                android:paddingTop="5dp"
-                android:paddingBottom="5dp"
-                android:paddingLeft="5dp"
-                android:paddingRight="5dp"
-                android:visibility="gone"/>
-        <ImageButton
-                android:id="@+id/photopage_bottom_control_tiny_planet"
-                android:src="@drawable/ic_menu_tiny_planet"
-                android:background="@drawable/photopage_bottom_button_background"
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
-                android:layout_alignParentRight="true"
-                android:layout_alignParentBottom="true"
-                android:paddingTop="5dp"
-                android:paddingBottom="5dp"
-                android:paddingLeft="15dp"
-                android:paddingRight="15dp"
-                android:visibility="gone"/>
-</RelativeLayout>
diff --git a/res/layout/photopage_progress_bar.xml b/res/layout/photopage_progress_bar.xml
deleted file mode 100644
index 778feb3..0000000
--- a/res/layout/photopage_progress_bar.xml
+++ /dev/null
@@ -1,40 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
-        android:id="@+id/photopage_progress_bar"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:layout_alignParentBottom="true"
-        android:layout_alignParentLeft="true"
-        android:padding="25dp"
-        android:visibility="invisible">
-        <View
-                android:id="@+id/photopage_progress_background"
-                android:background="#ff000000"
-                android:layout_width="match_parent"
-                android:layout_height="8dp"
-                android:layout_alignParentBottom="true"
-                android:visibility="visible"/>
-        <View
-                android:id="@+id/photopage_progress_foreground"
-                android:background="#ff33b5e5"
-                android:layout_width="10dp"
-                android:layout_height="8dp"
-                android:layout_alignParentLeft="true"
-                android:layout_alignParentBottom="true"
-                android:visibility="visible"/>
-        <TextView
-                android:id="@+id/photopage_progress_bar_text"
-                android:text="@string/pano_progress_text"
-                android:textColor="#ffffffff"
-                android:textSize="14dp"
-                android:shadowColor="#ff000000"
-                android:shadowDx="0"
-                android:shadowDy="0"
-                android:shadowRadius="2"
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
-                android:layout_alignParentRight="true"
-                android:layout_above="@id/photopage_progress_background"
-                android:paddingBottom="8dp"
-                android:visibility="visible"/>
-</RelativeLayout>
diff --git a/res/layout/popup_list_item.xml b/res/layout/popup_list_item.xml
deleted file mode 100644
index 5a87af7..0000000
--- a/res/layout/popup_list_item.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- 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.
--->
-
-<TextView xmlns:android="http://schemas.android.com/apk/res/android"
-    android:id="@android:id/text1"
-    android:layout_width="match_parent"
-    android:layout_height="wrap_content"
-    android:textAppearance="?android:attr/textAppearanceLargePopupMenu"
-    android:singleLine="true"
-    android:gravity="center_vertical"
-    android:paddingLeft="16dp"
-    android:paddingRight="16dp"
-    android:minHeight="?android:attr/listPreferredItemHeight"
-    android:minWidth="196dp"
-/>
diff --git a/res/layout/trim_menu.xml b/res/layout/trim_menu.xml
deleted file mode 100644
index e233392..0000000
--- a/res/layout/trim_menu.xml
+++ /dev/null
@@ -1,32 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- 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.
--->
-
-<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
-        android:layout_width="match_parent"
-        android:layout_height="match_parent"
-        android:layout_centerVertical="true">
-    <TextView
-        android:id="@+id/start_trim"
-        android:layout_marginLeft="8dp"
-        android:layout_width="wrap_content"
-        android:layout_height="match_parent"
-        android:text="@string/save"
-        android:textAllCaps="true"
-        android:textSize="14sp"
-        android:gravity="left|center_vertical"
-        android:drawableLeft="@drawable/menu_save_photo"
-        android:drawablePadding="8dp" />
-</FrameLayout>
diff --git a/res/layout/trim_view.xml b/res/layout/trim_view.xml
deleted file mode 100644
index c95c719..0000000
--- a/res/layout/trim_view.xml
+++ /dev/null
@@ -1,27 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- 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.
--->
-
-<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
-        android:id="@+id/trim_view_root"
-        android:background="@android:color/black"
-        android:layout_width="match_parent"
-        android:layout_height="match_parent">
-    <VideoView android:id="@+id/surface_view"
-            android:visibility="visible"
-            android:layout_width="match_parent"
-            android:layout_height="match_parent"
-            android:layout_centerInParent="true" />
-</RelativeLayout>
\ No newline at end of file
diff --git a/res/layout/undo_bar.xml b/res/layout/undo_bar.xml
deleted file mode 100644
index 33ec91d..0000000
--- a/res/layout/undo_bar.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2013 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.
--->
-<!-- This layout is shared by phone and tablet in portrait or landscape orientation. -->
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-        android:orientation="horizontal"
-        style="@style/UndoBar">
-    <TextView android:text="@string/deleted"
-            style="@style/UndoBarTextAppearance"
-            android:layout_width="0dp"
-            android:layout_height="match_parent"
-            android:layout_weight="1"
-            android:gravity="left|center_vertical" />
-    <View style="@style/UndoBarSeparator" />
-    <TextView android:id="@+id/undo_button"
-            style="@style/UndoButton"
-            android:text="@string/undo"
-            android:drawableLeft="@drawable/ic_menu_revert_holo_dark"/>
-</LinearLayout>
diff --git a/res/menu/album.xml b/res/menu/album.xml
deleted file mode 100644
index 4db0e51..0000000
--- a/res/menu/album.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2010 Google Inc.
-
-     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.
--->
-<menu xmlns:android="http://schemas.android.com/apk/res/android">
-    <item android:id="@+id/action_camera"
-            android:icon="@drawable/ic_menu_camera_holo_light"
-            android:title="@string/switch_to_camera"
-            android:showAsAction="ifRoom" />
-    <item android:id="@+id/action_slideshow"
-            android:icon="@drawable/ic_menu_slideshow_holo_light"
-            android:title="@string/slideshow"
-            android:showAsAction="never" />
-    <item android:id="@+id/action_select"
-            android:title="@string/select_item"
-            android:showAsAction="never" />
-    <item android:id="@+id/action_group_by"
-            android:title="@string/group_by"
-            android:showAsAction="never"/>
-</menu>
diff --git a/res/menu/albumset.xml b/res/menu/albumset.xml
deleted file mode 100644
index 8ac8cbb..0000000
--- a/res/menu/albumset.xml
+++ /dev/null
@@ -1,37 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2010 Google Inc.
-
-     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.
--->
-<menu xmlns:android="http://schemas.android.com/apk/res/android">
-    <item android:id="@+id/action_camera"
-            android:icon="@drawable/ic_menu_camera_holo_light"
-            android:title="@string/switch_to_camera"
-            android:showAsAction="ifRoom" />
-    <item android:id="@+id/action_select"
-            android:title="@string/select_album"
-            android:showAsAction="never" />
-    <item android:id="@+id/action_manage_offline"
-            android:title="@string/make_available_offline"
-            android:showAsAction="never" />
-    <item android:id="@+id/action_sync_picasa_albums"
-            android:title="@string/sync_picasa_albums"
-            android:showAsAction="never" />
-    <item android:id="@+id/action_settings"
-            android:title="@string/settings"
-            android:showAsAction="never" />
-    <item android:id="@+id/action_general_help"
-            android:title="@string/help"
-            android:visible="false"
-            android:showAsAction="never" />
-</menu>
diff --git a/res/menu/crop.xml b/res/menu/crop.xml
deleted file mode 100644
index aa0e035..0000000
--- a/res/menu/crop.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2010 Google Inc.
-
-     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.
--->
-<menu xmlns:android="http://schemas.android.com/apk/res/android">
-    <item android:id="@+id/cancel"
-            android:title="@android:string/cancel"
-            android:showAsAction="always|withText">
-    </item>
-    <item android:id="@+id/save"
-            android:title="@string/crop_save_text"
-            android:showAsAction="always|withText">
-    </item>
-</menu>
diff --git a/res/menu/filterby.xml b/res/menu/filterby.xml
deleted file mode 100644
index 3a72c57..0000000
--- a/res/menu/filterby.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2010 Google Inc.
-
-     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.
--->
-<menu xmlns:android="http://schemas.android.com/apk/res/android">
-    <item android:id="@+id/action_filter_all"
-            android:title="@string/show_all" />
-    <item android:id="@+id/action_filter_image"
-            android:title="@string/show_images_only" />
-    <item android:id="@+id/action_filter_video"
-            android:title="@string/show_videos_only" />
-</menu>
diff --git a/res/menu/filtershow_activity_menu.xml b/res/menu/filtershow_activity_menu.xml
deleted file mode 100644
index 09c6ffe..0000000
--- a/res/menu/filtershow_activity_menu.xml
+++ /dev/null
@@ -1,37 +0,0 @@
-<menu xmlns:android="http://schemas.android.com/apk/res/android" >
-    <item
-        android:id="@+id/menu_share"
-        android:actionProviderClass="android.widget.ShareActionProvider"
-        android:showAsAction="never"
-        android:enabled="false"
-        android:visible="false"
-        android:title="@string/share"/>
-    <item
-        android:id="@+id/undoButton"
-        android:icon="@drawable/filtershow_button_undo"
-        android:showAsAction="always"
-        android:title="@string/filtershow_undo"/>
-    <item
-        android:id="@+id/redoButton"
-        android:icon="@drawable/filtershow_button_redo"
-        android:showAsAction="always"
-        android:title="@string/filtershow_redo"/>
-    <item
-        android:id="@+id/resetHistoryButton"
-        android:title="@string/reset"/>
-    <item
-        android:id="@+id/showImageStateButton"
-        android:showAsAction="never"
-        android:visible="true"
-        android:title="@string/show_imagestate_panel" />
-    <item
-        android:id="@+id/manageUserPresets"
-        android:showAsAction="never"
-        android:visible="true"
-        android:title="@string/filtershow_manage_preset" />
-    <item
-        android:id="@+id/exportFlattenButton"
-        android:showAsAction="never"
-        android:visible="true"
-        android:title="@string/export_flattened" />
-</menu>
diff --git a/res/menu/filtershow_menu_chan_sat.xml b/res/menu/filtershow_menu_chan_sat.xml
deleted file mode 100644
index eae559d..0000000
--- a/res/menu/filtershow_menu_chan_sat.xml
+++ /dev/null
@@ -1,43 +0,0 @@
-<!--
-     Copyright (C) 2013 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.
--->
-
-<menu xmlns:android="http://schemas.android.com/apk/res/android" >
-
-    <group android:id="@+id/grunge_popupmenu" >
-        <item
-            android:id="@+id/editor_chan_sat_main"
-            android:title="@string/editor_chan_sat_main"/>
-        <item
-            android:id="@+id/editor_chan_sat_red"
-            android:title="@string/editor_chan_sat_red"/>
-        <item
-            android:id="@+id/editor_chan_sat_yellow"
-            android:title="@string/editor_chan_sat_yellow"/>
-        <item
-            android:id="@+id/editor_chan_sat_green"
-            android:title="@string/editor_chan_sat_green"/>
-       <item
-            android:id="@+id/editor_chan_sat_cyan"
-            android:title="@string/editor_chan_sat_cyan"/>
-        <item
-            android:id="@+id/editor_chan_sat_blue"
-            android:title="@string/editor_chan_sat_blue"/>
-        <item
-            android:id="@+id/editor_chan_sat_magenta"
-            android:title="@string/editor_chan_sat_magenta"/>
-    </group>
-
-</menu>
\ No newline at end of file
diff --git a/res/menu/filtershow_menu_crop.xml b/res/menu/filtershow_menu_crop.xml
deleted file mode 100644
index f8ba3df..0000000
--- a/res/menu/filtershow_menu_crop.xml
+++ /dev/null
@@ -1,35 +0,0 @@
-<menu xmlns:android="http://schemas.android.com/apk/res/android" >
-
-    <group android:id="@+id/crop_popupmenu" >
-        <item
-            android:id="@+id/crop_menu_1to1"
-            android:title="@string/aspect1to1_effect"/>
-        <item
-            android:id="@+id/crop_menu_4to6"
-            android:visible="false"
-            android:title="@string/aspect4to6_effect"/>
-        <item
-            android:id="@+id/crop_menu_4to3"
-            android:title="@string/aspect4to3_effect"/>
-        <item
-            android:id="@+id/crop_menu_3to4"
-            android:title="@string/aspect3to4_effect"/>
-        <item
-            android:id="@+id/crop_menu_5to7"
-            android:title="@string/aspect5to7_effect"/>
-        <item
-            android:id="@+id/crop_menu_7to5"
-            android:title="@string/aspect7to5_effect"/>
-        <item
-            android:id="@+id/crop_menu_9to16"
-            android:visible="false"
-            android:title="@string/aspect9to16_effect"/>
-        <item
-            android:id="@+id/crop_menu_none"
-            android:title="@string/aspectNone_effect"/>
-        <item
-            android:id="@+id/crop_menu_original"
-            android:title="@string/aspectOriginal_effect"/>
-    </group>
-
-</menu>
diff --git a/res/menu/filtershow_menu_curves.xml b/res/menu/filtershow_menu_curves.xml
deleted file mode 100644
index 326df45..0000000
--- a/res/menu/filtershow_menu_curves.xml
+++ /dev/null
@@ -1,18 +0,0 @@
-<menu xmlns:android="http://schemas.android.com/apk/res/android" >
-
-    <group android:id="@+id/curves_popupmenu" >
-        <item
-            android:id="@+id/curve_menu_rgb"
-            android:title="@string/curves_channel_rgb"/>
-        <item
-            android:id="@+id/curve_menu_red"
-            android:title="@string/curves_channel_red"/>
-        <item
-            android:id="@+id/curve_menu_green"
-            android:title="@string/curves_channel_green"/>
-        <item
-            android:id="@+id/curve_menu_blue"
-            android:title="@string/curves_channel_blue"/>
-    </group>
-
-</menu>
\ No newline at end of file
diff --git a/res/menu/filtershow_menu_draw.xml b/res/menu/filtershow_menu_draw.xml
deleted file mode 100644
index 2960c1f..0000000
--- a/res/menu/filtershow_menu_draw.xml
+++ /dev/null
@@ -1,41 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-     Copyright (C) 2013 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.
--->
-
-<menu xmlns:android="http://schemas.android.com/apk/res/android" >
-
-    <group android:id="@+id/curves_popupmenu" >
-        <item
-            android:id="@+id/draw_menu_style_line"
-            android:title="@string/draw_style_line" />
-         <item
-            android:id="@+id/draw_menu_style_brush_marker"
-            android:title="@string/draw_style_brush_marker"/>
-         <item
-            android:id="@+id/draw_menu_style_brush_spatter"
-            android:title="@string/draw_style_brush_spatter"/>
-         <item
-            android:id="@+id/draw_menu_size"
-            android:title="@string/draw_size" />
-        <item
-            android:id="@+id/draw_menu_color"
-            android:title="@string/draw_color"/>
-        <item
-            android:id="@+id/draw_menu_clear"
-            android:title="@string/draw_clear"/>
-    </group>
-
-</menu>
\ No newline at end of file
diff --git a/res/menu/filtershow_menu_grad.xml b/res/menu/filtershow_menu_grad.xml
deleted file mode 100644
index 1dee7e0..0000000
--- a/res/menu/filtershow_menu_grad.xml
+++ /dev/null
@@ -1,27 +0,0 @@
-<!--
-     Copyright (C) 2013 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.
--->
-
-<menu xmlns:android="http://schemas.android.com/apk/res/android" >
-     <item
-          android:id="@+id/editor_grad_brightness"
-          android:title="@string/editor_grad_brightness"/>
-     <item
-          android:id="@+id/editor_grad_saturation"
-          android:title="@string/editor_grad_saturation"/>
-     <item
-          android:id="@+id/editor_grad_contrast"
-          android:title="@string/editor_grad_contrast"/>
-</menu>
diff --git a/res/menu/gallery.xml b/res/menu/gallery.xml
deleted file mode 100644
index dc36787..0000000
--- a/res/menu/gallery.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<menu xmlns:android="http://schemas.android.com/apk/res/android" >
-    <item
-        android:id="@+id/menu_camera"
-        android:icon="@android:drawable/ic_menu_camera"
-        android:showAsAction="ifRoom"
-        android:title="@string/menu_camera"/>
-    <item
-        android:id="@+id/menu_search"
-        android:icon="@android:drawable/ic_menu_search"
-        android:showAsAction="ifRoom"
-        android:title="@string/menu_search"/>
-    <item
-        android:id="@+id/menu_settings"
-        android:icon="@android:drawable/ic_menu_preferences"
-        android:showAsAction="never"
-        android:title="@string/settings"/>
-    <item
-        android:id="@+id/menu_help"
-        android:icon="@android:drawable/ic_menu_help"
-        android:showAsAction="never"
-        android:title="@string/help"/>
-</menu>
\ No newline at end of file
diff --git a/res/menu/gallery_multiselect.xml b/res/menu/gallery_multiselect.xml
deleted file mode 100644
index d9365c1..0000000
--- a/res/menu/gallery_multiselect.xml
+++ /dev/null
@@ -1,33 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<menu xmlns:android="http://schemas.android.com/apk/res/android" >
-    <item android:id="@+id/menu_edit"
-            android:title="@string/edit"
-            android:visible="false"
-            android:showAsAction="ifRoom" />
-    <item android:id="@+id/menu_delete"
-            android:icon="@android:drawable/ic_menu_delete"
-            android:title="@string/delete"
-            android:visible="false"
-            android:showAsAction="ifRoom" />
-    <item android:id="@+id/menu_share"
-          android:title="@string/share"
-          android:showAsAction="ifRoom"
-          android:visible="false"
-          android:actionProviderClass="android.widget.ShareActionProvider" />
-    <item android:id="@+id/menu_crop"
-            android:title="@string/crop_action"
-            android:visible="false"
-            android:showAsAction="never" />
-    <item android:id="@+id/menu_trim"
-            android:title="@string/trim_action"
-            android:visible="false"
-            android:showAsAction="never" />
-    <item android:id="@+id/menu_mute"
-            android:title="@string/mute_action"
-            android:visible="false"
-            android:showAsAction="never" />
-    <item android:id="@+id/menu_set_as"
-            android:title="@string/set_as"
-            android:visible="false"
-            android:showAsAction="never" />
-</menu>
\ No newline at end of file
diff --git a/res/menu/groupby.xml b/res/menu/groupby.xml
deleted file mode 100644
index b2c2b8d..0000000
--- a/res/menu/groupby.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2010 Google Inc.
-
-     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.
--->
-<menu xmlns:android="http://schemas.android.com/apk/res/android">
-    <item android:id="@+id/action_cluster_album"
-            android:title="@string/group_by_album" />
-    <item android:id="@+id/action_cluster_time"
-            android:title="@string/group_by_time" />
-    <item android:id="@+id/action_cluster_location"
-            android:title="@string/group_by_location" />
-    <item android:id="@+id/action_cluster_tags"
-            android:title="@string/group_by_tags" />
-    <item android:id="@+id/action_cluster_size"
-            android:title="@string/group_by_size" />
-    <item android:id="@+id/action_cluster_faces"
-            android:title="@string/group_by_faces" />
-</menu>
diff --git a/res/menu/ingest_menu_item_list_selection.xml b/res/menu/ingest_menu_item_list_selection.xml
deleted file mode 100644
index 2f020b6..0000000
--- a/res/menu/ingest_menu_item_list_selection.xml
+++ /dev/null
@@ -1,22 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2013 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.
--->
-<menu xmlns:android="http://schemas.android.com/apk/res/android">
-    <item android:id="@+id/ingest_switch_view"
-          android:showAsAction="always" />
-    <item android:id="@+id/import_items"
-          android:showAsAction="always|withText"
-          android:title="@string/Import" />
-</menu>
\ No newline at end of file
diff --git a/res/menu/movie.xml b/res/menu/movie.xml
deleted file mode 100644
index fde235c..0000000
--- a/res/menu/movie.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2010 Google Inc.
-
-     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.
--->
-<menu xmlns:android="http://schemas.android.com/apk/res/android">
-    <item android:id="@+id/action_share"
-            android:icon="@drawable/ic_menu_share_holo_light"
-            android:title="@string/share"
-            android:enabled="true"
-            android:actionProviderClass="android.widget.ShareActionProvider"
-            android:showAsAction="ifRoom" />
-</menu>
diff --git a/res/menu/operation.xml b/res/menu/operation.xml
deleted file mode 100644
index d1791e2..0000000
--- a/res/menu/operation.xml
+++ /dev/null
@@ -1,73 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2010 Google Inc.
-
-     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.
--->
-<menu xmlns:android="http://schemas.android.com/apk/res/android">
-    <item android:id="@+id/action_import"
-            android:title="@string/Import"
-            android:icon="@drawable/ic_menu_ptp_holo_light"
-            android:showAsAction="always|withText"
-            android:visible="false" />
-    <!-- Ideally, showAsAction for share_panorama and share should be reversed.
-         But, if share_panorama is set to never, it doesn't seem to get promoted
-         to the action bar and stays on the overflow menu. -->
-    <item android:id="@+id/action_share_panorama"
-            android:icon="@drawable/ic_menu_share_holo_light"
-            android:title="@string/share_panorama"
-            android:visible="false"
-            android:actionProviderClass="android.widget.ShareActionProvider"
-            android:showAsAction="ifRoom">
-    </item>
-    <item android:id="@+id/action_share"
-            android:icon="@drawable/ic_menu_share_holo_light"
-            android:title="@string/share"
-            android:visible="false"
-            android:actionProviderClass="android.widget.ShareActionProvider"
-            android:showAsAction="never">
-    </item>
-    <item android:id="@+id/action_delete"
-            android:icon="@drawable/ic_menu_trash_holo_light"
-            android:title="@string/delete"
-            android:visible="false"
-            android:showAsAction="ifRoom" />
-    <item android:id="@+id/action_edit"
-            android:title="@string/edit"
-            android:showAsAction="never"
-            android:visible="false" />
-    <item android:id="@+id/action_rotate_ccw"
-            android:showAsAction="never"
-            android:visible="false"
-            android:title="@string/rotate_left" />
-    <item android:id="@+id/action_rotate_cw"
-            android:showAsAction="never"
-            android:visible="false"
-            android:title="@string/rotate_right" />
-    <item android:id="@+id/action_crop"
-            android:title="@string/crop_action"
-            android:showAsAction="never"
-            android:visible="false" />
-    <item android:id="@+id/action_setas"
-            android:title="@string/set_image"
-            android:showAsAction="never"
-            android:visible="false" />
-    <item android:id="@+id/action_details"
-            android:icon="@drawable/ic_menu_info_details"
-            android:title="@string/details"
-            android:visible="false"
-            android:showAsAction="never" />
-    <item android:id="@+id/action_show_on_map"
-            android:title="@string/show_on_map"
-            android:showAsAction="never"
-            android:visible="false" />
-</menu>
diff --git a/res/menu/photo.xml b/res/menu/photo.xml
deleted file mode 100644
index 48742d1..0000000
--- a/res/menu/photo.xml
+++ /dev/null
@@ -1,78 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2010 Google Inc.
-
-     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.
--->
-<menu xmlns:android="http://schemas.android.com/apk/res/android">
-    <item android:id="@+id/action_import"
-            android:title="@string/Import"
-            android:icon="@drawable/ic_menu_ptp_holo_light"
-            android:showAsAction="always|withText"
-            android:visible="false" />
-    <!-- Ideally, showAsAction for share_panorama and share should be reversed.
-         But, if share_panorama is set to never, it doesn't seem to get promoted
-         to the action bar and stays on the overflow menu. -->
-    <item android:id="@+id/action_share_panorama"
-            android:icon="@drawable/ic_menu_share_holo_light"
-            android:title="@string/share_panorama"
-            android:visible="false"
-            android:actionProviderClass="android.widget.ShareActionProvider"
-            android:showAsAction="ifRoom" />
-    <item android:id="@+id/action_share"
-            android:icon="@drawable/ic_menu_share_holo_light"
-            android:title="@string/share"
-            android:visible="false"
-            android:actionProviderClass="android.widget.ShareActionProvider"
-            android:showAsAction="never" />
-    <item android:id="@+id/action_delete"
-            android:icon="@drawable/ic_menu_trash_holo_light"
-            android:title="@string/delete"
-            android:visible="false"
-            android:showAsAction="never" />
-    <item android:id="@+id/action_slideshow"
-            android:icon="@drawable/ic_menu_slideshow_holo_light"
-            android:title="@string/slideshow"
-            android:showAsAction="never" />
-    <item android:id="@+id/action_edit"
-            android:title="@string/edit"
-            android:showAsAction="never"
-            android:visible="false" />
-    <item android:id="@+id/action_simple_edit"
-          android:title="@string/simple_edit"
-          android:showAsAction="never"
-          android:visible="false" />
-    <item android:id="@+id/action_rotate_ccw"
-            android:showAsAction="never"
-            android:title="@string/rotate_left" />
-    <item android:id="@+id/action_rotate_cw"
-            android:showAsAction="never"
-            android:title="@string/rotate_right" />
-    <item android:id="@+id/action_crop"
-            android:title="@string/crop_action"
-            android:showAsAction="never" />
-    <item android:id="@+id/action_trim"
-            android:title="@string/trim_action"
-            android:showAsAction="never" />
-    <item android:id="@+id/action_mute"
-            android:title="@string/mute_action"
-            android:showAsAction="never" />
-    <item android:id="@+id/action_setas"
-            android:title="@string/set_image"
-            android:showAsAction="never" />
-    <item android:id="@+id/action_details"
-            android:title="@string/details"
-            android:showAsAction="never" />
-    <item android:id="@+id/action_show_on_map"
-            android:title="@string/show_on_map"
-            android:showAsAction="never" />
-</menu>
diff --git a/res/menu/pickup.xml b/res/menu/pickup.xml
deleted file mode 100644
index 44de9b1..0000000
--- a/res/menu/pickup.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2010 Google Inc.
-
-     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.
--->
-<menu xmlns:android="http://schemas.android.com/apk/res/android">
-    <item android:id="@+id/action_cancel"
-            android:title="@string/cancel"
-            android:showAsAction="always|withText" />
-</menu>
diff --git a/res/menu/settings.xml b/res/menu/settings.xml
deleted file mode 100644
index f91f1ba..0000000
--- a/res/menu/settings.xml
+++ /dev/null
@@ -1,21 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2011 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.
--->
-<menu xmlns:android="http://schemas.android.com/apk/res/android">
-    <item android:id="@+id/add_account"
-            android:title="@string/add_account"
-            android:showAsAction="always|withText">
-    </item>
-</menu>
diff --git a/res/mipmap-hdpi/ic_launcher_gallery.png b/res/mipmap-hdpi/ic_launcher_gallery.png
deleted file mode 100644
index 23ea998..0000000
--- a/res/mipmap-hdpi/ic_launcher_gallery.png
+++ /dev/null
Binary files differ
diff --git a/res/mipmap-mdpi/ic_launcher_gallery.png b/res/mipmap-mdpi/ic_launcher_gallery.png
deleted file mode 100644
index e1a9949..0000000
--- a/res/mipmap-mdpi/ic_launcher_gallery.png
+++ /dev/null
Binary files differ
diff --git a/res/mipmap-xhdpi/ic_launcher_gallery.png b/res/mipmap-xhdpi/ic_launcher_gallery.png
deleted file mode 100644
index 79544a2..0000000
--- a/res/mipmap-xhdpi/ic_launcher_gallery.png
+++ /dev/null
Binary files differ
diff --git a/res/values/filtershow_color.xml b/res/values/filtershow_color.xml
deleted file mode 100644
index d7cf79d..0000000
--- a/res/values/filtershow_color.xml
+++ /dev/null
@@ -1,51 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2013 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.
--->
-
-<resources>
-    <color name="yellow">#FFFF00</color>
-    <color name="green">#00FF00</color>
-    <color name="red">#FF0000</color>
-    <color name="blue">#0000FF</color>
-    <color name="text_toolbar">#FFFFFF</color>
-    <color name="background_screen">#101010</color>
-    <color name="background_toolbar">#363949</color>
-    <color name="background_main_toolbar">#232323</color>
-    <color name="toolbar_separation_line">#333333</color>
-    <color name="slider_dot_color">#6464FF</color>
-    <color name="slider_line_color">#33B5E5</color>
-    <color name="state_panel_separation_line">#232323</color>
-    <color name="filtershow_background">#333333</color>
-    <color name="filtershow_graphic">#717171</color>
-    <color name="filtershow_stateview_end_background">#232323</color>
-    <color name="filtershow_stateview_end_text">#a7a7a7</color>
-    <color name="filtershow_stateview_background">#464646</color>
-    <color name="filtershow_stateview_text">#FFFFFF</color>
-    <color name="filtershow_stateview_selected_background">#c8c8c8</color>
-    <color name="filtershow_stateview_selected_text">#000000</color>
-    <color name="filtershow_categoryview_background">#1a1a1a</color>
-    <color name="filtershow_categoryview_text">#a7a7a7</color>
-    <color name="filtershow_category_selection">#ffffffff</color>
-    <color name="gradcontrol_point_center">#ffffffff</color>
-    <color name="gradcontrol_point_edge">#ffffffff</color>
-    <color name="gradcontrol_graypoint_center">#888888</color>
-    <color name="gradcontrol_graypoint_edge">#BBBBBB</color>
-    <color name="gradcontrol_point_shadow_start">#66000000</color>
-    <color name="gradcontrol_point_shadow_end">#00000000</color>
-    <color name="gradcontrol_line_color">#FFFFFF</color>
-    <color name="gradcontrol_line_shadow">#000000</color>
-
-
-</resources>
\ No newline at end of file
diff --git a/res/values/filtershow_ids.xml b/res/values/filtershow_ids.xml
deleted file mode 100644
index b315d12..0000000
--- a/res/values/filtershow_ids.xml
+++ /dev/null
@@ -1,52 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-* Copyright (C) 2013 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.
-*/
--->
-<resources>
-    <!-- Buttons ids for the filters -->
-    <item type="id" name="tinyplanetButton" />
-    <item type="id" name="vignetteButton" />
-    <item type="id" name="vibranceButton" />
-    <item type="id" name="contrastButton" />
-    <item type="id" name="saturationButton" />
-    <item type="id" name="bwfilterButton" />
-    <item type="id" name="wbalanceButton" />
-    <item type="id" name="hueButton" />
-    <item type="id" name="exposureButton" />
-    <item type="id" name="shadowRecoveryButton" />
-    <item type="id" name="highlightRecoveryButton" />
-    <item type="id" name="sharpenButton" />
-    <item type="id" name="curvesButtonRGB" />
-    <item type="id" name="negativeButton" />
-    <item type="id" name="edgeButton" />
-    <item type="id" name="kmeansButton" />
-    <item type="id" name="downsampleButton" />
-    <item type="id" name="drawOnImageButton" />
-    <item type="id" name="imageCurves" />
-    <item type="id" name="imageZoom" />
-    <item type="id" name="editorDraw" />
-    <item type="id" name="editorRedEye" />
-    <item type="id" name="imageOnlyEditor" />
-    <item type="id" name="vignetteEditor" />
-    <item type="id" name="editorCrop" />
-    <item type="id" name="editorFlip" />
-    <item type="id" name="editorRotate" />
-    <item type="id" name="editorStraighten" />
-    <item type="id" name="editorParametric" />
-    <item type="id" name="editorGrad" />
-    <item type="id" name="editorChanSat" />
-</resources>
diff --git a/res/values/filtershow_strings.xml b/res/values/filtershow_strings.xml
deleted file mode 100644
index c4546c8..0000000
--- a/res/values/filtershow_strings.xml
+++ /dev/null
@@ -1,248 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- 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.
--->
-
-<resources>
-    <!--  Title for the image editor activity [CHAR LIMIT=NONE]-->
-    <string name="title_activity_filter_show">Photo Editor</string>
-
-    <!--  String shown when we cannot load the image when starting the activity [CHAR LIMIT=NONE] -->
-    <string name="cannot_load_image">Cannot load the image!</string>
-    <!--  String displayed when showing the original image [CHAR LIMIT=NONE] -->
-    <string name="original_picture_text">@string/original</string>
-    <!--  String displayed when setting the homepage wallpaper in the background [CHAR LIMIT=NONE] -->
-    <string name="setting_wallpaper">Setting wallpaper</string>
-
-    <!--  generic strings -->
-
-
-    <!--  Text for to display on a download failure [CHAR LIMIT=NONE] -->
-    <string name="download_failure">Could not download photo. Network unavailable.</string>
-    <!--  Text for original image [CHAR LIMIT=20] -->
-    <string name="original">Original</string>
-    <!--  Text for original image [CHAR LIMIT=20] -->
-    <string name="saved">Saved</string>
-    <!--  Text for filters that apply a border to a picture [CHAR LIMIT=20] -->
-    <string name="borders" msgid="4461692156695893616">Borders</string>
-
-    <!--  actionbar menu -->
-
-    <!--  Text for the undo menu item [CHAR LIMIT=20] -->
-    <string name="filtershow_undo">Undo</string>
-    <!--  Text for redo menu item [CHAR LIMIT=20] -->
-    <string name="filtershow_redo">Redo</string>
-    <!--  Text for the image menu item showing the filters that have been applied [CHAR LIMIT=30] -->
-    <string name="show_imagestate_panel">Show Applied Effects</string>
-    <!--  Text for the image state panel menu item [CHAR LIMIT=30] -->
-    <string name="hide_imagestate_panel">Hide Applied Effects</string>
-    <!--  Text for the menu item to export a flattened photo[CHAR LIMIT=30] -->
-    <string name="export_flattened">Export Flattened Image</string>
-    <!--  Text for selecting export image quality [CHAR LIMIT=100] -->
-    <string name="select_compression">Select output quality.</string>
-    <!--  Text for quality value tag [CHAR LIMIT=30] -->
-    <string name="quality">Quality</string>
-
-    <!--  Name for the overflow menu item for settings [CHAR LIMIT=20] -->
-    <string name="menu_settings">Settings</string>
-
-    <!--  Exit Dialog -->
-
-    <!--  String displayed when exiting with unsaved changes [CHAR LIMIT=NONE] -->
-    <string name="unsaved">There are unsaved changes to this image.</string>
-    <!--  String displayed when exiting with unsaved changes [CHAR LIMIT=NONE] -->
-    <string name="save_before_exit">Do you want to save before exiting?</string>
-    <!--  String displayed when saving and exiting editor [CHAR LIMIT=NONE] -->
-    <string name="save_and_exit">Save and Exit</string>
-    <!--  String displayed when exiting editor[CHAR LIMIT=NONE] -->
-    <string name="exit">Exit</string>
-
-    <!--  History Panel -->
-
-    <!--  Text for the history panel title [CHAR LIMIT=50] -->
-    <string name="history">History</string>
-    <!--  Text for the history panel reset button [CHAR LIMIT=20]-->
-    <string name="reset">Reset</string>
-    <!--  Text for the original image[CHAR LIMIT=20]-->
-    <string name="history_original">@string/original</string>
-
-    <!--  Image state panel -->
-
-    <!--  Text for the image state panel title [CHAR LIMIT=50] -->
-    <string name="imageState">Applied Effects</string>
-
-    <!--  Additional filters buttons  -->
-
-    <!--  Label for the compare original image filter button [CHAR LIMIT=15] -->
-    <string name="compare_original">Compare</string>
-    <!--  Label for the apply effect button [CHAR LIMIT=15] -->
-    <string name="apply_effect">Apply</string>
-    <!--  Label for the reset effect button [CHAR LIMIT=15] -->
-    <string name="reset_effect">Reset</string>
-    <!--  Label for aspect [CHAR LIMIT=15] -->
-    <string name="aspect">Aspect</string>
-    <!--  Label for the aspect 1:1 effect [CHAR LIMIT=15] -->
-    <string name="aspect1to1_effect">1:1</string>
-    <!--  Label for the aspect 4:3 effect [CHAR LIMIT=15] -->
-    <string name="aspect4to3_effect">4:3</string>
-    <!--  Label for the aspect 3:4 effect [CHAR LIMIT=15] -->
-    <string name="aspect3to4_effect">3:4</string>
-    <!--  Label for the aspect 4:7 effect [CHAR LIMIT=15] -->
-    <string name="aspect4to6_effect">4:6</string>
-    <!--  Label for the aspect 5:7 effect [CHAR LIMIT=15] -->
-    <string name="aspect5to7_effect">5:7</string>
-    <!--  Label for the aspect 7:5 effect [CHAR LIMIT=15] -->
-    <string name="aspect7to5_effect">7:5</string>
-    <!--  Label for the aspect 1:1 effect [CHAR LIMIT=15] -->
-    <string name="aspect9to16_effect">16:9</string>
-    <!--  Label for the aspect None effect [CHAR LIMIT=15] -->
-    <string name="aspectNone_effect">None</string>
-    <!--  Label for the aspect None effect [CHAR LIMIT=15] -->
-    <string name="aspectOriginal_effect">@string/original</string>
-    <!-- Label for when the aspect ratio is fixed to a value [CHAR LIMIT=15] -->
-    <string name="Fixed">Fixed</string>
-    <!--  Label for the tuny planet effect [CHAR LIMIT=10] -->
-    <string name="tinyplanet">Tiny Planet</string>
-
-    <!--  Filters buttons -->
-
-    <!--  Label for the image exposure (brightness) filter button [CHAR LIMIT=10] -->
-    <string name="exposure" msgid="1229093066434614811">Exposure</string>
-    <!--  Label for the image sharpness (clarity, distinctness) filter button [CHAR LIMIT=10] -->
-    <string name="sharpness">Sharpness</string>
-    <!--  Label for the image contrast (color difference) filter button [CHAR LIMIT=10] -->
-    <string name="contrast">Contrast</string>
-    <!--  Label for the image vibrance (strengthens colors) filter button [CHAR LIMIT=10] -->
-    <string name="vibrance">Vibrance</string>
-    <!--  Label for the image saturation (brightens colors) filter button [CHAR LIMIT=10] -->
-    <string name="saturation">Saturation</string>
-    <!--  Label for the image BW filter (makes black & white) button [CHAR LIMIT=10] -->
-    <string name="bwfilter">BW Filter</string>
-    <!--  Label for the image Autocolor filter (makes off-white colors whiter) button [CHAR LIMIT=10] -->
-    <string name="wbalance">Autocolor</string>
-    <!--  Label for the image Hue filter (color, shade, tinge, tone) button [CHAR LIMIT=10] -->
-    <string name="hue">Hue</string>
-    <!--  Label for the image shadow recovery (lightens/darkens shadows) filter button [CHAR LIMIT=10] -->
-    <string name="shadow_recovery">Shadows</string>
-    <!--  Label for the image highlights recovery (lightens/darkens bright regions) filter button [CHAR LIMIT=15] -->
-    <string name="highlight_recovery">Highlights</string>
-    <!--  Label for the image curves filter button [CHAR LIMIT=10] -->
-    <string name="curvesRGB">Curves</string>
-    <!--  Label for the image vignette filter (darkens photo around edges) button [CHAR LIMIT=10] -->
-    <string name="vignette">Vignette</string>
-    <!--  Label for the image effect that removes redeye. [CHAR LIMIT=10] -->
-    <string name="redeye">Red Eye</string>
-    <!--  Label for the that allows drawing on Image [CHAR LIMIT=10] -->
-    <string name="imageDraw">Draw</string>
-    <!--  Label for the image straighten effect [CHAR LIMIT=15] -->
-    <string name="straighten" msgid="5217801513491493491">Straighten</string>
-    <!--  Label for the image crop effect [CHAR LIMIT=15] -->
-    <string name="crop" msgid="5584000454518174632">Crop</string>
-    <!--  Label for the image rotate effect [CHAR LIMIT=15] -->
-    <string name="rotate" msgid="460017689320955494">Rotate</string>
-    <!--  Label for the image flip effect [CHAR LIMIT=15] -->
-    <string name="mirror">Mirror</string>
-    <!-- Name for the photo effect that inverts photo to negative images. [CHAR LIMIT=10] -->
-    <string name="negative">Negative</string>
-    <!--  Label for having no filters applied to the image [CHAR LIMIT=10] -->
-    <string name="none" msgid="3601545724573307541">None</string>
-    <!--  Label for the image edges effect (highlights edges in image) [CHAR LIMIT=10] -->
-    <string name="edge">Edges</string>
-    <!--  Label for an image effect that replicates the "pop art" style of segmenting
-          images into solid colors, as popularized by Andy Warhol [CHAR LIMIT=10] -->
-    <string name="kmeans">Warhol</string>
-    <!--  Label for the image downsampling effect (makes image smaller) [CHAR LIMIT=15] -->
-    <string name="downsample">Downsample</string>
-    <!--  Label for the image graduated filter effect  [CHAR LIMIT=15] -->
-    <string name="grad">Graduated</string>
-    <!--  Label for the Brightness effect  [CHAR LIMIT=20] -->
-    <string name="editor_grad_brightness">Brightness</string>
-    <!--  Label for the Contrast filter effect  [CHAR LIMIT=20] -->
-    <string name="editor_grad_contrast">Contrast</string>
-    <!--  Label for the saturation effect  [CHAR LIMIT=20] -->
-    <string name="editor_grad_saturation">Saturation</string>
-    <!--  Label for the Main or Master control for per channel saturation effect [CHAR LIMIT=20] -->
-    <string name="editor_chan_sat_main">Main</string>
-    <!--  Label for the red control for per channel saturation effect [CHAR LIMIT=20] -->
-    <string name="editor_chan_sat_red">Red</string>
-    <!--  Label for the yellow control for per channel saturation effect [CHAR LIMIT=20] -->
-    <string name="editor_chan_sat_yellow">Yellow</string>
-    <!--  Label for the green control for per channel saturation effect [CHAR LIMIT=20] -->
-    <string name="editor_chan_sat_green">Green</string>
-    <!--  Label for the cyan control for per channel saturation effect [CHAR LIMIT=20] -->
-    <string name="editor_chan_sat_cyan">Cyan</string>
-    <!--  Label for the blue control for per channel saturation effect [CHAR LIMIT=20] -->
-    <string name="editor_chan_sat_blue">Blue</string>
-    <!--  Label for the Magenta control for per channel saturation effect [CHAR LIMIT=20] -->
-    <string name="editor_chan_sat_magenta">Magenta</string>
-    <!--  Label for the image graduated filter effect  [CHAR LIMIT=20] -->
-    <string name="editor_grad_style">Style</string>
-    <!--  Label for the image new grad layer  [CHAR LIMIT=20] -->
-    <string name="editor_grad_new">new</string>
-
-
-    <!--  Labels for the curves tool -->
-
-    <!--  Label for the curves tool, all channels (RGB) [CHAR LIMIT=3] -->
-    <string name="curves_channel_rgb">RGB</string>
-    <!--  Label for the curves tool, Red color channel [CHAR LIMIT=14] -->
-    <string name="curves_channel_red">Red</string>
-    <!--  Label for the curves tool, Green color channel [CHAR LIMIT=14] -->
-    <string name="curves_channel_green">Green</string>
-    <!--  Label for the curves tool, Blue color channel [CHAR LIMIT=14] -->
-    <string name="curves_channel_blue">Blue</string>
-
-    <!--  Label for the The style to draw in [CHAR LIMIT=14] -->
-    <string name="draw_style">Style</string>
-    <!--  Label for the size to draw in in [CHAR LIMIT=14] -->
-    <string name="draw_size">Size</string>
-    <!--  Label for the color to draw in [CHAR LIMIT=14] -->
-    <string name="draw_color">Color</string>
-    <!--  Label for the line style of drawing in [CHAR LIMIT=14] -->
-    <string name="draw_style_line">Lines</string>
-    <!--  Label for the Marker brush style of drawing in [CHAR LIMIT=14] -->
-    <string name="draw_style_brush_spatter">Marker</string>
-    <!--  Label for the Spatter brush style of drawing in [CHAR LIMIT=14] -->
-    <string name="draw_style_brush_marker">Spatter</string>
-    <!--  Label for the removing drawing from screen [CHAR LIMIT=14] -->
-    <string name="draw_clear">Clear</string>
-
-    <!--  Label for the select the color [CHAR LIMIT=35] -->
-    <string name="color_pick_select">Choose custom color</string>
-    <!--  The title for the color pick dialog [CHAR LIMIT=20] -->
-    <string name="color_pick_title">Select Color</string>
-    <!--  The title for draw size [CHAR LIMIT=50] -->
-    <string name="draw_size_title">Select Size</string>
-    <!--  The accept the draw size [CHAR LIMIT=20] -->
-    <string name="draw_size_accept">OK</string>
-
-    <!--  Name used to indicate the original image in the state panel [CHAR LIMIT=20] -->
-    <string name="state_panel_original">Original</string>
-
-    <!--  Name used to indicate the final image in the state panel [CHAR LIMIT=20] -->
-    <string name="state_panel_result">Result</string>
-
-    <!-- Label for the notification [CHAR LIMIT=50] -->
-    <string name="filtershow_notification_label">Saving Image</string>
-    <!-- Label for the notification message [CHAR LIMIT=50] -->
-    <string name="filtershow_notification_message">Processing...</string>
-
-    <!-- Label for the save preset menu [CHAR LIMIT=30] -->
-    <string name="filtershow_save_preset">Save current preset</string>
-    <!-- Label for the manage preset menu [CHAR LIMIT=30] -->
-    <string name="filtershow_manage_preset">Manage user presets</string>
-    <!-- Label for newly created user preset [CHAR LIMIT=30] -->
-    <string name="filtershow_new_preset">New Preset</string>
-
-</resources>
diff --git a/res/values/filtershow_styles.xml b/res/values/filtershow_styles.xml
deleted file mode 100644
index 4162ccd..0000000
--- a/res/values/filtershow_styles.xml
+++ /dev/null
@@ -1,68 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-     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.
--->
-<resources>
-
-    <style name="FilterShowHistoryButton">
-        <item name="android:layout_width">wrap_content</item>
-        <item name="android:layout_height">48dip</item>
-        <item name="android:layout_weight">1</item>
-        <item name="android:background">@drawable/filtershow_button_background</item>
-        <item name="android:gravity">center</item>
-        <item name="android:padding">2dip</item>
-        <item name="android:textColor">@android:color/white</item>
-        <item name="android:textSize">18dip</item>
-        <item name="android:textStyle">bold</item>
-    </style>
-
-    <style name="FilterShowTopButton">
-        <item name="android:layout_width">wrap_content</item>
-        <item name="android:layout_height">match_parent</item>
-        <item name="android:background">@drawable/filtershow_button_background</item>
-        <item name="android:gravity">center</item>
-        <item name="android:padding">8dip</item>
-        <item name="android:textColor">@android:color/white</item>
-        <item name="android:textSize">18dip</item>
-        <item name="android:textStyle">bold</item>
-        <item name="android:scaleType">centerInside</item>
-    </style>
-
-    <style name="FilterShowBottomButton">
-        <item name="android:layout_width">96dip</item>
-        <item name="android:layout_height">wrap_content</item>
-        <item name="android:background">@drawable/filtershow_button_background</item>
-        <item name="android:gravity">center</item>
-        <item name="android:paddingBottom">16dip</item>
-        <item name="android:textColor">@android:color/white</item>
-        <item name="android:textSize">18dip</item>
-        <item name="android:textStyle">bold</item>
-        <item name="android:scaleType">centerInside</item>
-    </style>
-
-    <style name="FilterShowSlider">
-        <item name="android:indeterminateOnly">false</item>
-        <item name="android:progressDrawable">@drawable/filtershow_slider</item>
-        <item name="android:indeterminateDrawable">@drawable/filtershow_slider</item>
-        <item name="android:minHeight">13dip</item>
-        <item name="android:maxHeight">13dip</item>
-        <item name="android:thumb">@drawable/filtershow_scrubber</item>
-        <item name="android:thumbOffset">16dip</item>
-        <item name="android:focusable">true</item>
-        <item name="android:paddingStart">16dip</item>
-        <item name="android:paddingEnd">16dip</item>
-    </style>
-
-</resources>
\ No newline at end of file
diff --git a/res/values/filtershow_values.xml b/res/values/filtershow_values.xml
deleted file mode 100644
index 0bb59c0..0000000
--- a/res/values/filtershow_values.xml
+++ /dev/null
@@ -1,43 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2013 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.
--->
-
-<resources>
-    <!-- Specify the screen orientation -->
-    <bool name="only_use_portrait">true</bool>
-
-    <!-- Text size for the state panel -->
-    <dimen name="state_panel_text_size">16dip</dimen>
-
-    <!-- Category Panel Height -->
-    <dimen name="category_panel_height">86dip</dimen>
-
-    <!-- Category Panel Icon Size -->
-    <dimen name="category_panel_icon_size">64dip</dimen>
-
-    <!-- Category Panel Text Size -->
-    <dimen name="category_panel_text_size">13dip</dimen>
-
-    <!-- Category Panel Text Size -->
-    <dimen name="category_panel_margin">4dip</dimen>
-
-    <!-- Grad filter dot size -->
-    <dimen name="gradcontrol_dot_size">20dip</dimen>
-
-    <!-- Grad filter minimum touch distance -->
-    <dimen name="gradcontrol_min_touch_dist">80dip</dimen>
-
-
-</resources>
\ No newline at end of file
diff --git a/res/values/filtershow_values_attrs.xml b/res/values/filtershow_values_attrs.xml
deleted file mode 100644
index 32a3a87..0000000
--- a/res/values/filtershow_values_attrs.xml
+++ /dev/null
@@ -1,32 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- 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.
--->
-
-<resources>
-    <declare-styleable name="ImageButtonTitle">
-        <attr name="android:text"/>
-        <attr name="android:textColor"/>
-    </declare-styleable>
-    <declare-styleable name="CenteredLinearLayout">
-        <attr name="max_width" format="dimension" />
-    </declare-styleable>
-    <declare-styleable name="StatePanelTrack">
-        <attr name="elemSize" format="dimension" />
-        <attr name="elemEndSize" format="dimension" />
-    </declare-styleable>
-    <declare-styleable name="CategoryTrack">
-        <attr name="iconSize" format="dimension" />
-    </declare-styleable>
-</resources>
\ No newline at end of file
diff --git a/res/values/iconbutton_styles.xml b/res/values/iconbutton_styles.xml
deleted file mode 100644
index e33460a..0000000
--- a/res/values/iconbutton_styles.xml
+++ /dev/null
@@ -1,49 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-     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.
--->
-<resources>
-    <style name="IconButton">
-        <item name="android:layout_width">96dp</item>
-        <item name="android:layout_height">match_parent</item>
-        <item name="android:background">@drawable/filtershow_button_background</item>
-        <item name="android:textColor">@android:color/white</item>
-        <item name="android:textSize">14dp</item>
-        <item name="android:scaleType">centerInside</item>
-        <item name="android:gravity">center</item>
-        <item name="android:padding">6dp</item>
-        <item name="android:drawablePadding">6dp</item>
-        <item name="android:ellipsize">marquee</item>
-        <item name="android:marqueeRepeatLimit">marquee_forever</item>
-        <item name="android:singleLine">true</item>
-    </style>
-
-    <style name="FilterIconButton">
-        <item name="android:layout_width">70dp</item>
-        <item name="android:layout_height">match_parent</item>
-        <item name="android:background">@drawable/filtershow_button_background</item>
-        <item name="android:textColor">@android:color/white</item>
-        <item name="android:textSize">13dp</item>
-        <item name="android:scaleType">centerInside</item>
-        <item name="android:gravity">center</item>
-        <item name="android:paddingLeft">3dp</item>
-        <item name="android:paddingRight">3dp</item>
-        <item name="android:paddingTop">6dp</item>
-        <item name="android:paddingBottom">6dp</item>
-        <item name="android:ellipsize">marquee</item>
-        <item name="android:marqueeRepeatLimit">marquee_forever</item>
-        <item name="android:singleLine">true</item>
-    </style>
-</resources>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index f2d69c8..cd0df05 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -15,7 +15,8 @@
 -->
 
 <resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="app_name">Gallery</string>
+    <string name="app_name">Camera++</string>
+    <string name="camera_2">Camera++</string>
     <!-- Title for picture frame gadget to show in list of all available gadgets -->
     <string name="gadget_title">Picture frame</string>
 
diff --git a/res/values/styles.xml b/res/values/styles.xml
index 67c53f8..655c659 100644
--- a/res/values/styles.xml
+++ b/res/values/styles.xml
@@ -15,7 +15,7 @@
 -->
 
 <resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <style name="Theme.GalleryBase" parent="android:Theme.Holo">
+<!--     <style name="Theme.GalleryBase" parent="android:Theme.Holo">
         <item name="listPreferredItemHeightSmall">48dp</item>
         <item name="switchStyle">@android:style/Widget.CompoundButton</item>
     </style>
@@ -50,7 +50,7 @@
     <style name="ActionBarTwoLineSecondary" parent="@android:style/TextAppearance.Holo.Widget.ActionBar.Subtitle"></style>
     <style name="ActionBarTwoLineItem">
         <item name="android:background">@drawable/action_bar_two_line_background</item>
-    </style>
+    </style> -->
 
     <!-- Camera resources below -->
 
diff --git a/res/xml/camera_preferences.xml b/res/xml/camera_preferences.xml
index 8c13a34..b978404 100644
--- a/res/xml/camera_preferences.xml
+++ b/res/xml/camera_preferences.xml
@@ -15,7 +15,7 @@
 -->
 
 <PreferenceGroup
-        xmlns:camera="http://schemas.android.com/apk/res/com.android.gallery3d"
+        xmlns:camera="http://schemas.android.com/apk/res/com.android.camera2"
         camera:title="@string/pref_camera_settings_category">
     <IconListPreference
             camera:key="pref_camera_flashmode_key"
diff --git a/res/xml/device_filter.xml b/res/xml/device_filter.xml
deleted file mode 100644
index 36cd13d..0000000
--- a/res/xml/device_filter.xml
+++ /dev/null
@@ -1,19 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2011 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.
--->
-<resources>
-    <!-- filter for PTP devices -->
-    <usb-device class="6" subclass="1" protocol="1" />
-</resources>
diff --git a/res/xml/video_preferences.xml b/res/xml/video_preferences.xml
index 79154e6..ce36219 100644
--- a/res/xml/video_preferences.xml
+++ b/res/xml/video_preferences.xml
@@ -15,7 +15,7 @@
 -->
 
 <PreferenceGroup
-        xmlns:camera="http://schemas.android.com/apk/res/com.android.gallery3d"
+        xmlns:camera="http://schemas.android.com/apk/res/com.android.camera2"
         camera:title="@string/pref_camcorder_settings_category">
     <ListPreference
             camera:key="pref_video_quality_key"
diff --git a/res/xml/wallpaper_picker_preview.xml b/res/xml/wallpaper_picker_preview.xml
deleted file mode 100644
index 759ff6f..0000000
--- a/res/xml/wallpaper_picker_preview.xml
+++ /dev/null
@@ -1,19 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2009 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.
--->
-
-<wallpaper-preview xmlns:android="http://schemas.android.com/apk/res/android"
-    android:staticWallpaperPreview="@drawable/wallpaper_picker_preview">
-</wallpaper-preview>
diff --git a/res/xml/widget_info.xml b/res/xml/widget_info.xml
deleted file mode 100644
index 4aa460f..0000000
--- a/res/xml/widget_info.xml
+++ /dev/null
@@ -1,8 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
-        android:minWidth="@dimen/appwidget_width"
-        android:minHeight="@dimen/appwidget_height"
-        android:updatePeriodMillis="86400000"
-        android:previewImage="@drawable/preview"
-        android:initialLayout="@layout/appwidget_main"
-        android:configure="com.android.gallery3d.gadget.WidgetConfigure"/>
diff --git a/src/com/android/camera/AndroidCameraManagerImpl.java b/src/com/android/camera/AndroidCameraManagerImpl.java
index 897aa92..6676306 100644
--- a/src/com/android/camera/AndroidCameraManagerImpl.java
+++ b/src/com/android/camera/AndroidCameraManagerImpl.java
@@ -18,6 +18,8 @@
 
 import static com.android.camera.Util.Assert;
 
+import java.io.IOException;
+
 import android.annotation.TargetApi;
 import android.graphics.SurfaceTexture;
 import android.hardware.Camera;
@@ -37,9 +39,7 @@
 import android.util.Log;
 import android.view.SurfaceHolder;
 
-import com.android.gallery3d.common.ApiHelper;
-
-import java.io.IOException;
+import com.android.camera.support.common.ApiHelper;
 
 /**
  * A class to implement {@link CameraManager} of the Android camera framework.
diff --git a/src/com/android/camera/CameraActivity.java b/src/com/android/camera/CameraActivity.java
index 7f71d5f..e110327 100644
--- a/src/com/android/camera/CameraActivity.java
+++ b/src/com/android/camera/CameraActivity.java
@@ -47,14 +47,14 @@
 import com.android.camera.data.FixedLastDataAdapter;
 import com.android.camera.data.LocalData;
 import com.android.camera.data.LocalDataAdapter;
+import com.android.camera.support.common.ApiHelper;
 import com.android.camera.ui.CameraSwitcher;
 import com.android.camera.ui.CameraSwitcher.CameraSwitchListener;
 import com.android.camera.ui.FilmStripView;
-import com.android.gallery3d.R;
-import com.android.gallery3d.common.ApiHelper;
-import com.android.gallery3d.util.LightCycleHelper;
-import com.android.gallery3d.util.RefocusHelper;
-import com.android.gallery3d.util.LightCycleHelper.PanoramaViewHelper;
+import com.android.camera.util.PhotoSphereHelper;
+import com.android.camera.util.PhotoSphereHelper.PanoramaViewHelper;
+import com.android.camera.util.RefocusHelper;
+import com.android.camera2.R;
 
 public class CameraActivity extends Activity
     implements CameraSwitchListener {
@@ -279,7 +279,6 @@
         mCameraPreviewData = new CameraPreviewData(rootLayout,
                 FilmStripView.ImageData.SIZE_FULL,
                 FilmStripView.ImageData.SIZE_FULL);
-        // Put a CameraPreviewData at the first position.
         mWrappedDataAdapter = new FixedFirstDataAdapter(
                 new CameraDataAdapter(new ColorDrawable(
                         getResources().getColor(R.color.photo_placeholder))),
@@ -297,25 +296,6 @@
         mOrientationListener = new MyOrientationEventListener(this);
         mMainHandler = new Handler(getMainLooper());
         bindMediaSaveService();
-
-        if (!mSecureCamera) {
-            mDataAdapter = mWrappedDataAdapter;
-            mDataAdapter.requestLoad(getContentResolver());
-        } else {
-            // Put a lock placeholder as the last image by setting its date to 0.
-            ImageView v = (ImageView) getLayoutInflater().inflate(
-                    R.layout.secure_album_placeholder, null);
-            mDataAdapter = new FixedLastDataAdapter(
-                    mWrappedDataAdapter,
-                    new LocalData.LocalViewData(
-                            v,
-                            v.getDrawable().getIntrinsicWidth(),
-                            v.getDrawable().getIntrinsicHeight(),
-                            0, 0));
-            // Flush out all the original data.
-            mDataAdapter.flush();
-        }
-        mFilmStripView.setDataAdapter(mDataAdapter);
     }
 
     private void setRotationAnimation() {
@@ -363,6 +343,25 @@
     public void onStart() {
         super.onStart();
 
+        // The loading is done in background and will update the filmstrip later.
+        if (!mSecureCamera) {
+            mDataAdapter = mWrappedDataAdapter;
+            mDataAdapter.requestLoad(getContentResolver());
+            mFilmStripView.setDataAdapter(mDataAdapter);
+        } else {
+            // Put a lock placeholder as the last image by setting its date to 0.
+            ImageView v = (ImageView) getLayoutInflater().inflate(
+                    R.layout.secure_album_placeholder, null);
+            mDataAdapter = new FixedLastDataAdapter(
+                    mWrappedDataAdapter,
+                    new LocalData.LocalViewData(
+                            v,
+                            v.getDrawable().getIntrinsicWidth(),
+                            v.getDrawable().getIntrinsicHeight(),
+                            0, 0));
+            // Flush out all the original data.
+            mDataAdapter.flush();
+        }
         mPanoramaViewHelper.onStart();
     }
 
@@ -497,7 +496,7 @@
                 mCurrentModule = new PhotoModule();
                 break;
             case CameraSwitcher.LIGHTCYCLE_MODULE_INDEX:
-                mCurrentModule = LightCycleHelper.createPanoramaModule();
+                mCurrentModule = PhotoSphereHelper.createPanoramaModule();
                 break;
             case CameraSwitcher.REFOCUS_MODULE_INDEX:
                 mCurrentModule = RefocusHelper.createRefocusModule();
diff --git a/src/com/android/camera/CameraManager.java b/src/com/android/camera/CameraManager.java
index 90a838c..fd9b2ce 100644
--- a/src/com/android/camera/CameraManager.java
+++ b/src/com/android/camera/CameraManager.java
@@ -16,6 +16,8 @@
 
 package com.android.camera;
 
+import java.io.IOException;
+
 import android.annotation.TargetApi;
 import android.graphics.SurfaceTexture;
 import android.hardware.Camera;
@@ -25,9 +27,7 @@
 import android.os.Handler;
 import android.view.SurfaceHolder;
 
-import com.android.gallery3d.common.ApiHelper;
-
-import java.io.IOException;
+import com.android.camera.support.common.ApiHelper;
 
 /**
  * An interface which provides possible camera device operations.
diff --git a/src/com/android/camera/CameraPreference.java b/src/com/android/camera/CameraPreference.java
index 5ddd86d..407c140 100644
--- a/src/com/android/camera/CameraPreference.java
+++ b/src/com/android/camera/CameraPreference.java
@@ -21,7 +21,7 @@
 import android.content.res.TypedArray;
 import android.util.AttributeSet;
 
-import com.android.gallery3d.R;
+import com.android.camera2.R;
 
 /**
  * The base class of all Preferences used in Camera. The preferences can be
diff --git a/src/com/android/camera/CameraScreenNail.java b/src/com/android/camera/CameraScreenNail.java
index 993a7d3..9fe2c06 100644
--- a/src/com/android/camera/CameraScreenNail.java
+++ b/src/com/android/camera/CameraScreenNail.java
@@ -16,16 +16,16 @@
 
 package com.android.camera;
 
+import android.annotation.SuppressLint;
 import android.annotation.TargetApi;
 import android.content.Context;
 import android.graphics.SurfaceTexture;
 import android.opengl.Matrix;
 import android.util.Log;
-
-import com.android.gallery3d.common.ApiHelper;
-import com.android.gallery3d.glrenderer.GLCanvas;
-import com.android.gallery3d.glrenderer.RawTexture;
-import com.android.gallery3d.ui.SurfaceTextureScreenNail;
+import com.android.camera.support.common.ApiHelper;
+import com.android.camera.support.glrenderer.GLCanvas;
+import com.android.camera.support.glrenderer.RawTexture;
+import com.android.camera.support.ui.SurfaceTextureScreenNail;
 
 /*
  * This is a ScreenNail which can display camera's preview.
@@ -313,11 +313,13 @@
         Matrix.translateM(matrix, 0, -.5f, -.5f, 0);
     }
 
-    public void directDraw(GLCanvas canvas, int x, int y, int width, int height) {
+    @SuppressLint("WrongCall")
+	public void directDraw(GLCanvas canvas, int x, int y, int width, int height) {
         DrawClient draw;
         synchronized (mLock) {
             draw = mDraw;
         }
+        // TODO: Should this call draw or onDraw?
         draw.onDraw(canvas, x, y, width, height);
     }
 
diff --git a/src/com/android/camera/CameraSettings.java b/src/com/android/camera/CameraSettings.java
index 3558014..9e01d5c 100644
--- a/src/com/android/camera/CameraSettings.java
+++ b/src/com/android/camera/CameraSettings.java
@@ -16,7 +16,6 @@
 
 package com.android.camera;
 
-import android.annotation.TargetApi;
 import android.app.Activity;
 import android.content.Context;
 import android.content.SharedPreferences;
@@ -30,8 +29,8 @@
 import android.util.FloatMath;
 import android.util.Log;
 
-import com.android.gallery3d.R;
-import com.android.gallery3d.common.ApiHelper;
+import com.android.camera2.R;
+import com.android.camera.support.common.ApiHelper;
 
 import java.util.ArrayList;
 import java.util.List;
diff --git a/src/com/android/camera/CaptureAnimManager.java b/src/com/android/camera/CaptureAnimManager.java
index 6e80925..3510d75 100644
--- a/src/com/android/camera/CaptureAnimManager.java
+++ b/src/com/android/camera/CaptureAnimManager.java
@@ -23,10 +23,10 @@
 import android.view.animation.DecelerateInterpolator;
 import android.view.animation.Interpolator;
 
-import com.android.gallery3d.R;
-import com.android.gallery3d.glrenderer.GLCanvas;
-import com.android.gallery3d.glrenderer.NinePatchTexture;
-import com.android.gallery3d.glrenderer.RawTexture;
+import com.android.camera.support.glrenderer.GLCanvas;
+import com.android.camera.support.glrenderer.NinePatchTexture;
+import com.android.camera.support.glrenderer.RawTexture;
+import com.android.camera2.R;
 
 /**
  * Class to handle the capture animation.
diff --git a/src/com/android/camera/ComboPreferences.java b/src/com/android/camera/ComboPreferences.java
index e17e47a..142f698 100644
--- a/src/com/android/camera/ComboPreferences.java
+++ b/src/com/android/camera/ComboPreferences.java
@@ -22,13 +22,13 @@
 import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
 import android.preference.PreferenceManager;
 
-import com.android.gallery3d.util.UsageStatistics;
-
 import java.util.Map;
 import java.util.Set;
 import java.util.WeakHashMap;
 import java.util.concurrent.CopyOnWriteArrayList;
 
+import com.android.camera.util.UsageStatistics;
+
 public class ComboPreferences implements
         SharedPreferences,
         OnSharedPreferenceChangeListener {
diff --git a/src/com/android/camera/CountDownTimerPreference.java b/src/com/android/camera/CountDownTimerPreference.java
index 9c66dda..9a7e44b 100644
--- a/src/com/android/camera/CountDownTimerPreference.java
+++ b/src/com/android/camera/CountDownTimerPreference.java
@@ -19,7 +19,7 @@
 import android.content.Context;
 import android.util.AttributeSet;
 
-import com.android.gallery3d.R;
+import com.android.camera2.R;
 
 public class CountDownTimerPreference extends ListPreference {
     private static final int[] DURATIONS = {
diff --git a/src/com/android/camera/EffectsRecorder.java b/src/com/android/camera/EffectsRecorder.java
index 4bf8d41..9012263 100644
--- a/src/com/android/camera/EffectsRecorder.java
+++ b/src/com/android/camera/EffectsRecorder.java
@@ -16,6 +16,13 @@
 
 package com.android.camera;
 
+import java.io.FileDescriptor;
+import java.io.Serializable;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
+
 import android.annotation.TargetApi;
 import android.content.Context;
 import android.graphics.SurfaceTexture;
@@ -26,15 +33,8 @@
 import android.os.Looper;
 import android.util.Log;
 
-import com.android.gallery3d.R;
-import com.android.gallery3d.common.ApiHelper;
-
-import java.io.FileDescriptor;
-import java.io.Serializable;
-import java.lang.reflect.Constructor;
-import java.lang.reflect.InvocationHandler;
-import java.lang.reflect.Method;
-import java.lang.reflect.Proxy;
+import com.android.camera.support.common.ApiHelper;
+import com.android.camera2.R;
 
 
 /**
diff --git a/src/com/android/camera/FocusOverlayManager.java b/src/com/android/camera/FocusOverlayManager.java
index 8bcb52f..7a9e1dd 100644
--- a/src/com/android/camera/FocusOverlayManager.java
+++ b/src/com/android/camera/FocusOverlayManager.java
@@ -16,6 +16,9 @@
 
 package com.android.camera;
 
+import java.util.ArrayList;
+import java.util.List;
+
 import android.annotation.TargetApi;
 import android.graphics.Matrix;
 import android.graphics.Rect;
@@ -27,10 +30,7 @@
 import android.os.Message;
 import android.util.Log;
 
-import com.android.gallery3d.common.ApiHelper;
-
-import java.util.ArrayList;
-import java.util.List;
+import com.android.camera.support.common.ApiHelper;
 
 /* A class that handles everything about focus in still picture mode.
  * This also handles the metering area because it is the same as focus area.
diff --git a/src/com/android/camera/IconListPreference.java b/src/com/android/camera/IconListPreference.java
index e5f75d3..97e729d 100644
--- a/src/com/android/camera/IconListPreference.java
+++ b/src/com/android/camera/IconListPreference.java
@@ -16,14 +16,14 @@
 
 package com.android.camera;
 
+import java.util.List;
+
 import android.content.Context;
 import android.content.res.Resources;
 import android.content.res.TypedArray;
 import android.util.AttributeSet;
 
-import com.android.gallery3d.R;
-
-import java.util.List;
+import com.android.camera2.R;
 
 /** A {@code ListPreference} where each entry has a corresponding icon. */
 public class IconListPreference extends ListPreference {
diff --git a/src/com/android/camera/ListPreference.java b/src/com/android/camera/ListPreference.java
index 38866de..f593b35 100644
--- a/src/com/android/camera/ListPreference.java
+++ b/src/com/android/camera/ListPreference.java
@@ -16,6 +16,9 @@
 
 package com.android.camera;
 
+import java.util.ArrayList;
+import java.util.List;
+
 import android.content.Context;
 import android.content.SharedPreferences;
 import android.content.res.TypedArray;
@@ -23,10 +26,7 @@
 import android.util.Log;
 import android.util.TypedValue;
 
-import com.android.gallery3d.R;
-
-import java.util.ArrayList;
-import java.util.List;
+import com.android.camera2.R;
 
 /**
  * A type of <code>CameraPreference</code> whose number of possible values
diff --git a/src/com/android/camera/OnScreenHint.java b/src/com/android/camera/OnScreenHint.java
index 4d7fa70..f47d9d8 100644
--- a/src/com/android/camera/OnScreenHint.java
+++ b/src/com/android/camera/OnScreenHint.java
@@ -25,7 +25,7 @@
 import android.view.WindowManager;
 import android.widget.TextView;
 
-import com.android.gallery3d.R;
+import com.android.camera2.R;
 
 /**
  * A on-screen hint is a view containing a little message for the user and will
diff --git a/src/com/android/camera/OnScreenIndicators.java b/src/com/android/camera/OnScreenIndicators.java
index 77c8faf..1ddea1c 100644
--- a/src/com/android/camera/OnScreenIndicators.java
+++ b/src/com/android/camera/OnScreenIndicators.java
@@ -23,7 +23,7 @@
 import android.view.View;
 import android.widget.ImageView;
 
-import com.android.gallery3d.R;
+import com.android.camera2.R;
 
 /**
  * The on-screen indicators of the pie menu button. They show the camera
diff --git a/src/com/android/camera/PhotoMenu.java b/src/com/android/camera/PhotoMenu.java
index 6c1e2d0..6f47e13 100644
--- a/src/com/android/camera/PhotoMenu.java
+++ b/src/com/android/camera/PhotoMenu.java
@@ -16,6 +16,8 @@
 
 package com.android.camera;
 
+import java.util.Locale;
+
 import android.content.res.Resources;
 import android.hardware.Camera.Parameters;
 
@@ -25,9 +27,7 @@
 import com.android.camera.ui.PieItem;
 import com.android.camera.ui.PieItem.OnClickListener;
 import com.android.camera.ui.PieRenderer;
-import com.android.gallery3d.R;
-
-import java.util.Locale;
+import com.android.camera2.R;
 
 public class PhotoMenu extends PieController
         implements CountdownTimerPopup.Listener,
diff --git a/src/com/android/camera/PhotoModule.java b/src/com/android/camera/PhotoModule.java
index c65a49e..89833b3 100644
--- a/src/com/android/camera/PhotoModule.java
+++ b/src/com/android/camera/PhotoModule.java
@@ -16,6 +16,15 @@
 
 package com.android.camera;
 
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.ArrayList;
+import java.util.Formatter;
+import java.util.List;
+
 import android.annotation.TargetApi;
 import android.app.Activity;
 import android.content.ContentProviderClient;
@@ -56,26 +65,16 @@
 import com.android.camera.CameraManager.CameraPictureCallback;
 import com.android.camera.CameraManager.CameraProxy;
 import com.android.camera.CameraManager.CameraShutterCallback;
+import com.android.camera.support.common.ApiHelper;
+import com.android.camera.support.filtershow.crop.CropExtras;
 import com.android.camera.ui.CountDownView.OnCountDownFinishedListener;
 import com.android.camera.ui.PopupManager;
 import com.android.camera.ui.RotateTextToast;
-import com.android.gallery3d.R;
-import com.android.gallery3d.common.ApiHelper;
+import com.android.camera.util.UsageStatistics;
+import com.android.camera2.R;
 import com.android.gallery3d.exif.ExifInterface;
 import com.android.gallery3d.exif.ExifTag;
 import com.android.gallery3d.exif.Rational;
-import com.android.gallery3d.filtershow.crop.CropActivity;
-import com.android.gallery3d.filtershow.crop.CropExtras;
-import com.android.gallery3d.util.UsageStatistics;
-
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.OutputStream;
-import java.util.ArrayList;
-import java.util.Formatter;
-import java.util.List;
 
 public class PhotoModule
     implements CameraModule,
@@ -1131,7 +1130,9 @@
                 newExtras.putBoolean(CropExtras.KEY_SHOW_WHEN_LOCKED, true);
             }
 
-            Intent cropIntent = new Intent(CropActivity.CROP_ACTION);
+            // TODO ...
+            final String CROP_ACTION = "com.android.camera.action.CROP";
+            Intent cropIntent = new Intent(CROP_ACTION);
 
             cropIntent.setData(tempUri);
             cropIntent.putExtras(newExtras);
diff --git a/src/com/android/camera/PhotoUI.java b/src/com/android/camera/PhotoUI.java
index d58ed7f..e10570a 100644
--- a/src/com/android/camera/PhotoUI.java
+++ b/src/com/android/camera/PhotoUI.java
@@ -17,6 +17,8 @@
 
 package com.android.camera;
 
+import java.util.List;
+
 import android.animation.Animator;
 import android.animation.ObjectAnimator;
 import android.animation.ValueAnimator;
@@ -26,7 +28,6 @@
 import android.graphics.SurfaceTexture;
 import android.hardware.Camera;
 import android.hardware.Camera.Face;
-import android.hardware.Camera.FaceDetectionListener;
 import android.hardware.Camera.Size;
 import android.os.Handler;
 import android.os.Message;
@@ -57,11 +58,9 @@
 import com.android.camera.ui.PieRenderer.PieListener;
 import com.android.camera.ui.RenderOverlay;
 import com.android.camera.ui.ZoomRenderer;
-import com.android.gallery3d.R;
+import com.android.camera2.R;
 import com.android.gallery3d.common.ApiHelper;
 
-import java.util.List;
-
 public class PhotoUI implements PieListener,
     PreviewGestures.SingleTapListener,
     FocusUI, TextureView.SurfaceTextureListener,
diff --git a/src/com/android/camera/PreviewFrameLayout.java b/src/com/android/camera/PreviewFrameLayout.java
index 03ef91c..cc2d280 100644
--- a/src/com/android/camera/PreviewFrameLayout.java
+++ b/src/com/android/camera/PreviewFrameLayout.java
@@ -16,17 +16,15 @@
 
 package com.android.camera;
 
+import android.annotation.SuppressLint;
 import android.content.Context;
-import android.content.res.Configuration;
 import android.util.AttributeSet;
 import android.view.View;
-import android.view.ViewStub;
 import android.widget.RelativeLayout;
-
+import com.android.camera.support.common.ApiHelper;
 import com.android.camera.ui.LayoutChangeHelper;
 import com.android.camera.ui.LayoutChangeNotifier;
-import com.android.gallery3d.R;
-import com.android.gallery3d.common.ApiHelper;
+import com.android.camera2.R;
 
 /**
  * A layout which handles the preview aspect ratio.
@@ -128,9 +126,11 @@
         mLayoutChangeHelper.setOnLayoutChangeListener(listener);
     }
 
-    @Override
+    @SuppressLint("WrongCall")
+	@Override
     protected void onLayout(boolean changed, int l, int t, int r, int b) {
         super.onLayout(changed, l, t, r, b);
+        // TODO: Suspicious call!
         mLayoutChangeHelper.onLayout(changed, l, t, r, b);
     }
 }
diff --git a/src/com/android/camera/RotateDialogController.java b/src/com/android/camera/RotateDialogController.java
index 5d5e5e7..45163f1 100644
--- a/src/com/android/camera/RotateDialogController.java
+++ b/src/com/android/camera/RotateDialogController.java
@@ -28,7 +28,7 @@
 
 import com.android.camera.ui.Rotatable;
 import com.android.camera.ui.RotateLayout;
-import com.android.gallery3d.R;
+import com.android.camera2.R;
 
 public class RotateDialogController implements Rotatable {
 
diff --git a/src/com/android/camera/SoundClips.java b/src/com/android/camera/SoundClips.java
index 8155c03..b5cfedd 100644
--- a/src/com/android/camera/SoundClips.java
+++ b/src/com/android/camera/SoundClips.java
@@ -23,7 +23,7 @@
 import android.media.SoundPool;
 import android.util.Log;
 
-import com.android.gallery3d.R;
+import com.android.camera2.R;
 import com.android.gallery3d.common.ApiHelper;
 
 /*
diff --git a/src/com/android/camera/StaticBitmapScreenNail.java b/src/com/android/camera/StaticBitmapScreenNail.java
index 10788c0..91ac35c 100644
--- a/src/com/android/camera/StaticBitmapScreenNail.java
+++ b/src/com/android/camera/StaticBitmapScreenNail.java
@@ -18,7 +18,7 @@
 
 import android.graphics.Bitmap;
 
-import com.android.gallery3d.ui.BitmapScreenNail;
+import com.android.camera.support.ui.BitmapScreenNail;
 
 public class StaticBitmapScreenNail extends BitmapScreenNail {
     public StaticBitmapScreenNail(Bitmap bitmap) {
diff --git a/src/com/android/camera/Storage.java b/src/com/android/camera/Storage.java
index ba995ed..4e5a7dd 100644
--- a/src/com/android/camera/Storage.java
+++ b/src/com/android/camera/Storage.java
@@ -16,6 +16,9 @@
 
 package com.android.camera;
 
+import java.io.File;
+import java.io.FileOutputStream;
+
 import android.annotation.TargetApi;
 import android.content.ContentResolver;
 import android.content.ContentValues;
@@ -29,12 +32,9 @@
 import android.provider.MediaStore.MediaColumns;
 import android.util.Log;
 
-import com.android.gallery3d.common.ApiHelper;
+import com.android.camera.support.common.ApiHelper;
 import com.android.gallery3d.exif.ExifInterface;
 
-import java.io.File;
-import java.io.FileOutputStream;
-
 public class Storage {
     private static final String TAG = "CameraStorage";
 
diff --git a/src/com/android/camera/SwitchAnimManager.java b/src/com/android/camera/SwitchAnimManager.java
index 6ec8822..20a4bfd 100644
--- a/src/com/android/camera/SwitchAnimManager.java
+++ b/src/com/android/camera/SwitchAnimManager.java
@@ -19,8 +19,8 @@
 import android.os.SystemClock;
 import android.util.Log;
 
-import com.android.gallery3d.glrenderer.GLCanvas;
-import com.android.gallery3d.glrenderer.RawTexture;
+import com.android.camera.support.glrenderer.GLCanvas;
+import com.android.camera.support.glrenderer.RawTexture;
 
 /**
  * Class to handle the animation when switching between back and front cameras.
diff --git a/src/com/android/camera/Util.java b/src/com/android/camera/Util.java
index ccc2d90..43ad22e 100644
--- a/src/com/android/camera/Util.java
+++ b/src/com/android/camera/Util.java
@@ -16,6 +16,15 @@
 
 package com.android.camera;
 
+import java.io.Closeable;
+import java.io.IOException;
+import java.lang.reflect.Method;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.List;
+import java.util.StringTokenizer;
+
+import com.android.camera2.R;
 import android.annotation.TargetApi;
 import android.app.Activity;
 import android.app.AlertDialog;
@@ -38,7 +47,6 @@
 import android.location.Location;
 import android.net.Uri;
 import android.os.Build;
-import android.os.Handler;
 import android.os.ParcelFileDescriptor;
 import android.telephony.TelephonyManager;
 import android.util.DisplayMetrics;
@@ -54,17 +62,7 @@
 import android.view.animation.Animation;
 import android.widget.Toast;
 
-import com.android.gallery3d.R;
-import com.android.gallery3d.app.MovieActivity;
-import com.android.gallery3d.common.ApiHelper;
-
-import java.io.Closeable;
-import java.io.IOException;
-import java.lang.reflect.Method;
-import java.text.SimpleDateFormat;
-import java.util.Date;
-import java.util.List;
-import java.util.StringTokenizer;
+import com.android.camera.support.common.ApiHelper;
 
 /**
  * Collection of utility functions used in this package.
@@ -90,6 +88,9 @@
     public static final String SCENE_MODE_HDR = "hdr";
     public static final String TRUE = "true";
     public static final String FALSE = "false";
+    
+    /** Has to by in sync with the receiving MovieActivity. */
+    public static final String KEY_TREAT_UP_AS_BACK = "treat-up-as-back";
 
     public static boolean isSupported(String value, List<String> supported) {
         return supported == null ? false : supported.indexOf(value) >= 0;
@@ -794,7 +795,7 @@
             Intent intent = new Intent(Intent.ACTION_VIEW)
                     .setDataAndType(uri, "video/*")
                     .putExtra(Intent.EXTRA_TITLE, title)
-                    .putExtra(MovieActivity.KEY_TREAT_UP_AS_BACK, true);
+                    .putExtra(KEY_TREAT_UP_AS_BACK, true);
             context.startActivity(intent);
         } catch (ActivityNotFoundException e) {
             Toast.makeText(context, context.getString(R.string.video_err),
diff --git a/src/com/android/camera/VideoMenu.java b/src/com/android/camera/VideoMenu.java
index da0bde1..f0c7db2 100644
--- a/src/com/android/camera/VideoMenu.java
+++ b/src/com/android/camera/VideoMenu.java
@@ -16,7 +16,6 @@
 
 package com.android.camera;
 
-import android.app.Activity;
 import android.content.Context;
 import android.view.LayoutInflater;
 
@@ -27,7 +26,7 @@
 import com.android.camera.ui.PieItem.OnClickListener;
 import com.android.camera.ui.PieRenderer;
 import com.android.camera.ui.TimeIntervalPopup;
-import com.android.gallery3d.R;
+import com.android.camera2.R;
 
 public class VideoMenu extends PieController
         implements MoreSettingPopup.Listener,
diff --git a/src/com/android/camera/VideoModule.java b/src/com/android/camera/VideoModule.java
index 956890e..aa085af 100644
--- a/src/com/android/camera/VideoModule.java
+++ b/src/com/android/camera/VideoModule.java
@@ -16,6 +16,13 @@
 
 package com.android.camera;
 
+import java.io.File;
+import java.io.IOException;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.Iterator;
+import java.util.List;
+
 import android.annotation.TargetApi;
 import android.app.Activity;
 import android.content.ActivityNotFoundException;
@@ -56,21 +63,14 @@
 
 import com.android.camera.CameraManager.CameraPictureCallback;
 import com.android.camera.CameraManager.CameraProxy;
+import com.android.camera.support.app.OrientationManager;
+import com.android.camera.support.util.AccessibilityUtils;
 import com.android.camera.ui.PopupManager;
 import com.android.camera.ui.RotateTextToast;
-import com.android.gallery3d.R;
-import com.android.gallery3d.app.OrientationManager;
+import com.android.camera.util.UsageStatistics;
+import com.android.camera2.R;
 import com.android.gallery3d.common.ApiHelper;
 import com.android.gallery3d.exif.ExifInterface;
-import com.android.gallery3d.util.AccessibilityUtils;
-import com.android.gallery3d.util.UsageStatistics;
-
-import java.io.File;
-import java.io.IOException;
-import java.text.SimpleDateFormat;
-import java.util.Date;
-import java.util.Iterator;
-import java.util.List;
 
 public class VideoModule implements CameraModule,
     VideoController,
diff --git a/src/com/android/camera/VideoUI.java b/src/com/android/camera/VideoUI.java
index 551b725..06c9795 100644
--- a/src/com/android/camera/VideoUI.java
+++ b/src/com/android/camera/VideoUI.java
@@ -16,6 +16,8 @@
 
 package com.android.camera;
 
+import java.util.List;
+
 import android.graphics.Bitmap;
 import android.graphics.Matrix;
 import android.graphics.SurfaceTexture;
@@ -48,11 +50,9 @@
 import com.android.camera.ui.RenderOverlay;
 import com.android.camera.ui.RotateLayout;
 import com.android.camera.ui.ZoomRenderer;
-import com.android.gallery3d.R;
+import com.android.camera2.R;
 import com.android.gallery3d.common.ApiHelper;
 
-import java.util.List;
-
 public class VideoUI implements PieRenderer.PieListener,
         PreviewGestures.SingleTapListener,
         CameraRootView.MyDisplayListener,
diff --git a/src/com/android/camera/app/CameraApp.java b/src/com/android/camera/app/CameraApp.java
new file mode 100644
index 0000000..f020a84
--- /dev/null
+++ b/src/com/android/camera/app/CameraApp.java
@@ -0,0 +1,11 @@
+package com.android.camera.app;
+
+import android.app.Application;
+
+public class CameraApp extends Application {
+	@Override
+	public void onCreate() {
+		super.onCreate();
+		com.android.camera.Util.initialize(this);
+	}
+}
diff --git a/src/com/android/camera/data/CameraDataAdapter.java b/src/com/android/camera/data/CameraDataAdapter.java
index 3605f71..e384b15 100644
--- a/src/com/android/camera/data/CameraDataAdapter.java
+++ b/src/com/android/camera/data/CameraDataAdapter.java
@@ -16,6 +16,11 @@
 
 package com.android.camera.data;
 
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+
 import android.content.ContentResolver;
 import android.content.Context;
 import android.database.Cursor;
@@ -28,12 +33,6 @@
 
 import com.android.camera.Storage;
 import com.android.camera.ui.FilmStripView.ImageData;
-import com.android.gallery3d.util.LightCycleHelper.PanoramaViewHelper;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.List;
 
 /**
  * A {@link LocalDataAdapter} that provides data in the camera folder.
diff --git a/src/com/android/camera/data/LocalData.java b/src/com/android/camera/data/LocalData.java
index efccfe3..eb2212c 100644
--- a/src/com/android/camera/data/LocalData.java
+++ b/src/com/android/camera/data/LocalData.java
@@ -16,6 +16,10 @@
 
 package com.android.camera.data;
 
+import java.io.File;
+import java.util.Comparator;
+import java.util.Date;
+
 import android.content.ContentResolver;
 import android.content.Context;
 import android.database.Cursor;
@@ -42,13 +46,9 @@
 import com.android.camera.Util;
 import com.android.camera.data.PanoramaMetadataLoader.PanoramaMetadataCallback;
 import com.android.camera.ui.FilmStripView;
-import com.android.gallery3d.R;
-import com.android.gallery3d.util.LightCycleHelper.PanoramaMetadata;
-import com.android.gallery3d.util.LightCycleHelper.PanoramaViewHelper;
-
-import java.io.File;
-import java.util.Comparator;
-import java.util.Date;
+import com.android.camera.util.PhotoSphereHelper.PanoramaMetadata;
+import com.android.camera.util.PhotoSphereHelper.PanoramaViewHelper;
+import com.android.camera2.R;
 
 /**
  * An abstract interface that represents the local media data. Also implements
@@ -101,16 +101,10 @@
     // Implementations below.
 
     /**
-<<<<<<< HEAD
      * 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 subclassing BitmapLoadTask and overriding
      * doInBackground() to return a bitmap.
-=======
-     * 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
-     * sub-classing BitmapLoadTask and overriding doInBackground() to return a bitmap.
->>>>>>> Add LocalDataAdapter and wrappers.
      */
     abstract static class LocalMediaData implements LocalData {
         protected long id;
diff --git a/src/com/android/camera/data/PanoramaMetadataLoader.java b/src/com/android/camera/data/PanoramaMetadataLoader.java
index 21b5f8a..fda6848 100644
--- a/src/com/android/camera/data/PanoramaMetadataLoader.java
+++ b/src/com/android/camera/data/PanoramaMetadataLoader.java
@@ -16,13 +16,13 @@
 
 package com.android.camera.data;
 
+import java.util.ArrayList;
+
 import android.content.Context;
 import android.net.Uri;
 
-import com.android.gallery3d.util.LightCycleHelper;
-import com.android.gallery3d.util.LightCycleHelper.PanoramaMetadata;
-
-import java.util.ArrayList;
+import com.android.camera.util.PhotoSphereHelper;
+import com.android.camera.util.PhotoSphereHelper.PanoramaMetadata;
 
 /**
  * This class breaks out the off-thread panorama support.
@@ -72,7 +72,7 @@
                 (new Thread() {
                     @Override
                     public void run() {
-                        onLoadingDone(LightCycleHelper.getPanoramaMetadata(context,
+                        onLoadingDone(PhotoSphereHelper.getPanoramaMetadata(context,
                                 mMediaUri));
                     }
                 }).start();
@@ -96,7 +96,7 @@
         mPanoramaMetadata = metadata;
         if (mPanoramaMetadata == null) {
             // Error getting panorama data from file. Treat as not panorama.
-            mPanoramaMetadata = LightCycleHelper.NOT_PANORAMA;
+            mPanoramaMetadata = PhotoSphereHelper.NOT_PANORAMA;
         }
         for (PanoramaMetadataCallback cb : mCallbacksWaiting) {
             cb.onPanoramaMetadataLoaded(mPanoramaMetadata);
diff --git a/src/com/android/camera/support/app/OrientationManager.java b/src/com/android/camera/support/app/OrientationManager.java
new file mode 100644
index 0000000..850d465
--- /dev/null
+++ b/src/com/android/camera/support/app/OrientationManager.java
@@ -0,0 +1,152 @@
+package com.android.camera.support.app;
+
+
+import android.app.Activity;
+import android.content.ContentResolver;
+import android.content.Context;
+import android.content.pm.ActivityInfo;
+import android.content.res.Configuration;
+import android.provider.Settings;
+import android.util.Log;
+import android.view.OrientationEventListener;
+import android.view.Surface;
+
+import com.android.camera.support.ui.OrientationSource;
+import com.android.gallery3d.common.ApiHelper;
+
+public class OrientationManager implements OrientationSource {
+    private static final String TAG = "OrientationManager";
+
+    // Orientation hysteresis amount used in rounding, in degrees
+    private static final int ORIENTATION_HYSTERESIS = 5;
+
+    private Activity mActivity;
+    private MyOrientationEventListener mOrientationListener;
+    // If the framework orientation is locked.
+    private boolean mOrientationLocked = false;
+
+    // This is true if "Settings -> Display -> Rotation Lock" is checked. We
+    // don't allow the orientation to be unlocked if the value is true.
+    private boolean mRotationLockedSetting = false;
+
+    public OrientationManager(Activity activity) {
+        mActivity = activity;
+        mOrientationListener = new MyOrientationEventListener(activity);
+    }
+
+    public void resume() {
+        ContentResolver resolver = mActivity.getContentResolver();
+        mRotationLockedSetting = Settings.System.getInt(
+                resolver, Settings.System.ACCELEROMETER_ROTATION, 0) != 1;
+        mOrientationListener.enable();
+    }
+
+    public void pause() {
+        mOrientationListener.disable();
+    }
+
+    ////////////////////////////////////////////////////////////////////////////
+    //  Orientation handling
+    //
+    //  We can choose to lock the framework orientation or not. If we lock the
+    //  framework orientation, we calculate a a compensation value according to
+    //  current device orientation and send it to listeners. If we don't lock
+    //  the framework orientation, we always set the compensation value to 0.
+    ////////////////////////////////////////////////////////////////////////////
+
+    // Lock the framework orientation to the current device orientation
+    public void lockOrientation() {
+        if (mOrientationLocked) return;
+        mOrientationLocked = true;
+        if (ApiHelper.HAS_ORIENTATION_LOCK) {
+            mActivity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LOCKED);
+        } else {
+            mActivity.setRequestedOrientation(calculateCurrentScreenOrientation());
+        }
+    }
+
+    // Unlock the framework orientation, so it can change when the device
+    // rotates.
+    public void unlockOrientation() {
+        if (!mOrientationLocked) return;
+        mOrientationLocked = false;
+        Log.d(TAG, "unlock orientation");
+        mActivity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR);
+    }
+
+    private int calculateCurrentScreenOrientation() {
+        int displayRotation = getDisplayRotation();
+        // Display rotation >= 180 means we need to use the REVERSE landscape/portrait
+        boolean standard = displayRotation < 180;
+        if (mActivity.getResources().getConfiguration().orientation
+                == Configuration.ORIENTATION_LANDSCAPE) {
+            return standard
+                    ? ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE
+                    : ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE;
+        } else {
+            if (displayRotation == 90 || displayRotation == 270) {
+                // If displayRotation = 90 or 270 then we are on a landscape
+                // device. On landscape devices, portrait is a 90 degree
+                // clockwise rotation from landscape, so we need
+                // to flip which portrait we pick as display rotation is counter clockwise
+                standard = !standard;
+            }
+            return standard
+                    ? ActivityInfo.SCREEN_ORIENTATION_PORTRAIT
+                    : ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT;
+        }
+    }
+
+    // This listens to the device orientation, so we can update the compensation.
+    private class MyOrientationEventListener extends OrientationEventListener {
+        public MyOrientationEventListener(Context context) {
+            super(context);
+        }
+
+        @Override
+        public void onOrientationChanged(int orientation) {
+            // We keep the last known orientation. So if the user first orient
+            // the camera then point the camera to floor or sky, we still have
+            // the correct orientation.
+            if (orientation == ORIENTATION_UNKNOWN) return;
+            orientation = roundOrientation(orientation, 0);
+        }
+    }
+
+    @Override
+    public int getDisplayRotation() {
+        return getDisplayRotation(mActivity);
+    }
+
+    @Override
+    public int getCompensation() {
+        return 0;
+    }
+
+    private static int roundOrientation(int orientation, int orientationHistory) {
+        boolean changeOrientation = false;
+        if (orientationHistory == OrientationEventListener.ORIENTATION_UNKNOWN) {
+            changeOrientation = true;
+        } else {
+            int dist = Math.abs(orientation - orientationHistory);
+            dist = Math.min(dist, 360 - dist);
+            changeOrientation = (dist >= 45 + ORIENTATION_HYSTERESIS);
+        }
+        if (changeOrientation) {
+            return ((orientation + 45) / 90 * 90) % 360;
+        }
+        return orientationHistory;
+    }
+
+    private static int getDisplayRotation(Activity activity) {
+        int rotation = activity.getWindowManager().getDefaultDisplay()
+                .getRotation();
+        switch (rotation) {
+            case Surface.ROTATION_0: return 0;
+            case Surface.ROTATION_90: return 90;
+            case Surface.ROTATION_180: return 180;
+            case Surface.ROTATION_270: return 270;
+        }
+        return 0;
+    }
+}
\ No newline at end of file
diff --git a/src/com/android/camera/support/app/StitchingChangeListener.java b/src/com/android/camera/support/app/StitchingChangeListener.java
new file mode 100644
index 0000000..f67fb39
--- /dev/null
+++ b/src/com/android/camera/support/app/StitchingChangeListener.java
@@ -0,0 +1,11 @@
+package com.android.camera.support.app;
+
+import android.net.Uri;
+
+public interface StitchingChangeListener {
+    public void onStitchingQueued(Uri uri);
+
+    public void onStitchingResult(Uri uri);
+
+    public void onStitchingProgress(Uri uri, int progress);
+}
diff --git a/src/com/android/camera/support/common/ApiHelper.java b/src/com/android/camera/support/common/ApiHelper.java
new file mode 100644
index 0000000..e6c1f5f
--- /dev/null
+++ b/src/com/android/camera/support/common/ApiHelper.java
@@ -0,0 +1,219 @@
+package com.android.camera.support.common;
+
+
+import android.app.admin.DevicePolicyManager;
+import android.content.ComponentName;
+import android.hardware.Camera;
+import android.os.Build;
+import android.provider.MediaStore.MediaColumns;
+import android.view.View;
+import android.view.WindowManager;
+
+import java.lang.reflect.Field;
+
+public class ApiHelper {
+    public static interface VERSION_CODES {
+        // These value are copied from Build.VERSION_CODES
+        public static final int GINGERBREAD_MR1 = 10;
+        public static final int HONEYCOMB = 11;
+        public static final int HONEYCOMB_MR1 = 12;
+        public static final int HONEYCOMB_MR2 = 13;
+        public static final int ICE_CREAM_SANDWICH = 14;
+        public static final int ICE_CREAM_SANDWICH_MR1 = 15;
+        public static final int JELLY_BEAN = 16;
+        public static final int JELLY_BEAN_MR1 = 17;
+        public static final int JELLY_BEAN_MR2 = 18;
+    }
+
+    public static final boolean AT_LEAST_16 = Build.VERSION.SDK_INT >= 16;
+
+    public static final boolean USE_888_PIXEL_FORMAT =
+            Build.VERSION.SDK_INT >= VERSION_CODES.JELLY_BEAN;
+
+    public static final boolean ENABLE_PHOTO_EDITOR =
+            Build.VERSION.SDK_INT >= VERSION_CODES.ICE_CREAM_SANDWICH;
+
+    public static final boolean HAS_VIEW_SYSTEM_UI_FLAG_LAYOUT_STABLE =
+            hasField(View.class, "SYSTEM_UI_FLAG_LAYOUT_STABLE");
+
+    public static final boolean HAS_VIEW_SYSTEM_UI_FLAG_HIDE_NAVIGATION =
+            hasField(View.class, "SYSTEM_UI_FLAG_HIDE_NAVIGATION");
+
+    public static final boolean HAS_MEDIA_COLUMNS_WIDTH_AND_HEIGHT =
+            hasField(MediaColumns.class, "WIDTH");
+
+    public static final boolean HAS_REUSING_BITMAP_IN_BITMAP_REGION_DECODER =
+            Build.VERSION.SDK_INT >= VERSION_CODES.JELLY_BEAN;
+
+    public static final boolean HAS_REUSING_BITMAP_IN_BITMAP_FACTORY =
+            Build.VERSION.SDK_INT >= VERSION_CODES.HONEYCOMB;
+
+    public static final boolean HAS_SET_BEAM_PUSH_URIS =
+            Build.VERSION.SDK_INT >= VERSION_CODES.JELLY_BEAN;
+
+    public static final boolean HAS_SET_DEFALT_BUFFER_SIZE = hasMethod(
+            "android.graphics.SurfaceTexture", "setDefaultBufferSize",
+            int.class, int.class);
+
+    public static final boolean HAS_RELEASE_SURFACE_TEXTURE = hasMethod(
+            "android.graphics.SurfaceTexture", "release");
+
+    public static final boolean HAS_SURFACE_TEXTURE =
+            Build.VERSION.SDK_INT >= VERSION_CODES.HONEYCOMB;
+
+    public static final boolean HAS_MTP =
+            Build.VERSION.SDK_INT >= VERSION_CODES.HONEYCOMB_MR1;
+
+    public static final boolean HAS_AUTO_FOCUS_MOVE_CALLBACK =
+            Build.VERSION.SDK_INT >= VERSION_CODES.JELLY_BEAN;
+
+    public static final boolean HAS_REMOTE_VIEWS_SERVICE =
+            Build.VERSION.SDK_INT >= VERSION_CODES.HONEYCOMB;
+
+    public static final boolean HAS_INTENT_EXTRA_LOCAL_ONLY =
+            Build.VERSION.SDK_INT >= VERSION_CODES.HONEYCOMB;
+
+    public static final boolean HAS_SET_SYSTEM_UI_VISIBILITY =
+            hasMethod(View.class, "setSystemUiVisibility", int.class);
+
+    public static final boolean HAS_FACE_DETECTION;
+    static {
+        boolean hasFaceDetection = false;
+        try {
+            Class<?> listenerClass = Class.forName(
+                    "android.hardware.Camera$FaceDetectionListener");
+            hasFaceDetection =
+                    hasMethod(Camera.class, "setFaceDetectionListener", listenerClass) &&
+                    hasMethod(Camera.class, "startFaceDetection") &&
+                    hasMethod(Camera.class, "stopFaceDetection") &&
+                    hasMethod(Camera.Parameters.class, "getMaxNumDetectedFaces");
+        } catch (Throwable t) {
+        }
+        HAS_FACE_DETECTION = hasFaceDetection;
+    }
+
+    public static final boolean HAS_GET_CAMERA_DISABLED =
+            hasMethod(DevicePolicyManager.class, "getCameraDisabled", ComponentName.class);
+
+    public static final boolean HAS_MEDIA_ACTION_SOUND =
+            Build.VERSION.SDK_INT >= VERSION_CODES.JELLY_BEAN;
+
+    public static final boolean HAS_TIME_LAPSE_RECORDING =
+            Build.VERSION.SDK_INT >= VERSION_CODES.HONEYCOMB;
+
+    public static final boolean HAS_ZOOM_WHEN_RECORDING =
+            Build.VERSION.SDK_INT >= VERSION_CODES.ICE_CREAM_SANDWICH;
+
+    public static final boolean HAS_CAMERA_FOCUS_AREA =
+            Build.VERSION.SDK_INT >= VERSION_CODES.ICE_CREAM_SANDWICH;
+
+    public static final boolean HAS_CAMERA_METERING_AREA =
+            Build.VERSION.SDK_INT >= VERSION_CODES.ICE_CREAM_SANDWICH;
+
+    public static final boolean HAS_MOTION_EVENT_TRANSFORM =
+            Build.VERSION.SDK_INT >= VERSION_CODES.HONEYCOMB;
+
+    public static final boolean HAS_EFFECTS_RECORDING = false;
+
+    // "Background" filter does not have "context" input port in jelly bean.
+    public static final boolean HAS_EFFECTS_RECORDING_CONTEXT_INPUT =
+            Build.VERSION.SDK_INT >= VERSION_CODES.JELLY_BEAN_MR1;
+
+    public static final boolean HAS_GET_SUPPORTED_VIDEO_SIZE =
+            Build.VERSION.SDK_INT >= VERSION_CODES.HONEYCOMB;
+
+    public static final boolean HAS_SET_ICON_ATTRIBUTE =
+            Build.VERSION.SDK_INT >= VERSION_CODES.HONEYCOMB;
+
+    public static final boolean HAS_MEDIA_PROVIDER_FILES_TABLE =
+            Build.VERSION.SDK_INT >= VERSION_CODES.HONEYCOMB;
+
+    public static final boolean HAS_SURFACE_TEXTURE_RECORDING =
+            Build.VERSION.SDK_INT >= VERSION_CODES.JELLY_BEAN;
+
+    public static final boolean HAS_ACTION_BAR =
+            Build.VERSION.SDK_INT >= VERSION_CODES.HONEYCOMB;
+
+    // Ex: View.setTranslationX.
+    public static final boolean HAS_VIEW_TRANSFORM_PROPERTIES =
+            Build.VERSION.SDK_INT >= VERSION_CODES.HONEYCOMB;
+
+    public static final boolean HAS_CAMERA_HDR =
+            Build.VERSION.SDK_INT >= VERSION_CODES.JELLY_BEAN_MR1;
+
+    public static final boolean HAS_OPTIONS_IN_MUTABLE =
+            Build.VERSION.SDK_INT >= VERSION_CODES.HONEYCOMB;
+
+    public static final boolean CAN_START_PREVIEW_IN_JPEG_CALLBACK =
+            Build.VERSION.SDK_INT >= VERSION_CODES.ICE_CREAM_SANDWICH;
+
+    public static final boolean HAS_VIEW_PROPERTY_ANIMATOR =
+            Build.VERSION.SDK_INT >= VERSION_CODES.HONEYCOMB_MR1;
+
+    public static final boolean HAS_POST_ON_ANIMATION =
+            Build.VERSION.SDK_INT >= VERSION_CODES.JELLY_BEAN;
+
+    public static final boolean HAS_ANNOUNCE_FOR_ACCESSIBILITY =
+            Build.VERSION.SDK_INT >= VERSION_CODES.JELLY_BEAN;
+
+    public static final boolean HAS_OBJECT_ANIMATION =
+            Build.VERSION.SDK_INT >= VERSION_CODES.HONEYCOMB;
+
+    public static final boolean HAS_GLES20_REQUIRED =
+            Build.VERSION.SDK_INT >= VERSION_CODES.HONEYCOMB;
+
+    public static final boolean HAS_ROTATION_ANIMATION =
+            hasField(WindowManager.LayoutParams.class, "rotationAnimation");
+
+    public static final boolean HAS_ORIENTATION_LOCK =
+            Build.VERSION.SDK_INT >= VERSION_CODES.JELLY_BEAN_MR2;
+
+    public static final boolean HAS_CANCELLATION_SIGNAL =
+            Build.VERSION.SDK_INT >= VERSION_CODES.JELLY_BEAN;
+
+    public static final boolean HAS_MEDIA_MUXER =
+                    Build.VERSION.SDK_INT >= VERSION_CODES.JELLY_BEAN_MR2;
+
+    public static final boolean HAS_DISPLAY_LISTENER =
+            Build.VERSION.SDK_INT >= VERSION_CODES.JELLY_BEAN_MR1;
+
+    public static int getIntFieldIfExists(Class<?> klass, String fieldName,
+            Class<?> obj, int defaultVal) {
+        try {
+            Field f = klass.getDeclaredField(fieldName);
+            return f.getInt(obj);
+        } catch (Exception e) {
+            return defaultVal;
+        }
+    }
+
+    private static boolean hasField(Class<?> klass, String fieldName) {
+        try {
+            klass.getDeclaredField(fieldName);
+            return true;
+        } catch (NoSuchFieldException e) {
+            return false;
+        }
+    }
+
+    private static boolean hasMethod(String className, String methodName,
+            Class<?>... parameterTypes) {
+        try {
+            Class<?> klass = Class.forName(className);
+            klass.getDeclaredMethod(methodName, parameterTypes);
+            return true;
+        } catch (Throwable th) {
+            return false;
+        }
+    }
+
+    private static boolean hasMethod(
+            Class<?> klass, String methodName, Class<?> ... paramTypes) {
+        try {
+            klass.getDeclaredMethod(methodName, paramTypes);
+            return true;
+        } catch (NoSuchMethodException e) {
+            return false;
+        }
+    }
+}
diff --git a/src/com/android/camera/support/common/Utils.java b/src/com/android/camera/support/common/Utils.java
new file mode 100644
index 0000000..f36d6ad
--- /dev/null
+++ b/src/com/android/camera/support/common/Utils.java
@@ -0,0 +1,325 @@
+package com.android.camera.support.common;
+
+
+import android.content.Context;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager.NameNotFoundException;
+import android.database.Cursor;
+import android.os.Build;
+import android.os.ParcelFileDescriptor;
+import android.text.TextUtils;
+import android.util.Log;
+
+import java.io.Closeable;
+import java.io.IOException;
+import java.io.InterruptedIOException;
+
+public class Utils {
+    private static final String TAG = "Utils";
+    private static final String DEBUG_TAG = "GalleryDebug";
+
+    private static final long POLY64REV = 0x95AC9329AC4BC9B5L;
+    private static final long INITIALCRC = 0xFFFFFFFFFFFFFFFFL;
+
+    private static long[] sCrcTable = new long[256];
+
+    private static final boolean IS_DEBUG_BUILD =
+            Build.TYPE.equals("eng") || Build.TYPE.equals("userdebug");
+
+    private static final String MASK_STRING = "********************************";
+
+    // Throws AssertionError if the input is false.
+    public static void assertTrue(boolean cond) {
+        if (!cond) {
+            throw new AssertionError();
+        }
+    }
+
+    // Throws AssertionError with the message. We had a method having the form
+    //   assertTrue(boolean cond, String message, Object ... args);
+    // However a call to that method will cause memory allocation even if the
+    // condition is false (due to autoboxing generated by "Object ... args"),
+    // so we don't use that anymore.
+    public static void fail(String message, Object ... args) {
+        throw new AssertionError(
+                args.length == 0 ? message : String.format(message, args));
+    }
+
+    // Throws NullPointerException if the input is null.
+    public static <T> T checkNotNull(T object) {
+        if (object == null) throw new NullPointerException();
+        return object;
+    }
+
+    // Returns true if two input Object are both null or equal
+    // to each other.
+    public static boolean equals(Object a, Object b) {
+        return (a == b) || (a == null ? false : a.equals(b));
+    }
+
+    // Returns the next power of two.
+    // Returns the input if it is already power of 2.
+    // Throws IllegalArgumentException if the input is <= 0 or
+    // the answer overflows.
+    public static int nextPowerOf2(int n) {
+        if (n <= 0 || n > (1 << 30)) throw new IllegalArgumentException("n is invalid: " + n);
+        n -= 1;
+        n |= n >> 16;
+        n |= n >> 8;
+        n |= n >> 4;
+        n |= n >> 2;
+        n |= n >> 1;
+        return n + 1;
+    }
+
+    // Returns the previous power of two.
+    // Returns the input if it is already power of 2.
+    // Throws IllegalArgumentException if the input is <= 0
+    public static int prevPowerOf2(int n) {
+        if (n <= 0) throw new IllegalArgumentException();
+        return Integer.highestOneBit(n);
+    }
+
+    // Returns the input value x clamped to the range [min, max].
+    public static int clamp(int x, int min, int max) {
+        if (x > max) return max;
+        if (x < min) return min;
+        return x;
+    }
+
+    // Returns the input value x clamped to the range [min, max].
+    public static float clamp(float x, float min, float max) {
+        if (x > max) return max;
+        if (x < min) return min;
+        return x;
+    }
+
+    // Returns the input value x clamped to the range [min, max].
+    public static long clamp(long x, long min, long max) {
+        if (x > max) return max;
+        if (x < min) return min;
+        return x;
+    }
+
+    public static boolean isOpaque(int color) {
+        return color >>> 24 == 0xFF;
+    }
+
+    public static void swap(int[] array, int i, int j) {
+        int temp = array[i];
+        array[i] = array[j];
+        array[j] = temp;
+    }
+
+    /**
+     * A function thats returns a 64-bit crc for string
+     *
+     * @param in input string
+     * @return a 64-bit crc value
+     */
+    public static final long crc64Long(String in) {
+        if (in == null || in.length() == 0) {
+            return 0;
+        }
+        return crc64Long(getBytes(in));
+    }
+
+    static {
+        // http://bioinf.cs.ucl.ac.uk/downloads/crc64/crc64.c
+        long part;
+        for (int i = 0; i < 256; i++) {
+            part = i;
+            for (int j = 0; j < 8; j++) {
+                long x = ((int) part & 1) != 0 ? POLY64REV : 0;
+                part = (part >> 1) ^ x;
+            }
+            sCrcTable[i] = part;
+        }
+    }
+
+    public static final long crc64Long(byte[] buffer) {
+        long crc = INITIALCRC;
+        for (int k = 0, n = buffer.length; k < n; ++k) {
+            crc = sCrcTable[(((int) crc) ^ buffer[k]) & 0xff] ^ (crc >> 8);
+        }
+        return crc;
+    }
+
+    public static byte[] getBytes(String in) {
+        byte[] result = new byte[in.length() * 2];
+        int output = 0;
+        for (char ch : in.toCharArray()) {
+            result[output++] = (byte) (ch & 0xFF);
+            result[output++] = (byte) (ch >> 8);
+        }
+        return result;
+    }
+
+    public static void closeSilently(Closeable c) {
+        if (c == null) return;
+        try {
+            c.close();
+        } catch (IOException t) {
+            Log.w(TAG, "close fail ", t);
+        }
+    }
+
+    public static int compare(long a, long b) {
+        return a < b ? -1 : a == b ? 0 : 1;
+    }
+
+    public static int ceilLog2(float value) {
+        int i;
+        for (i = 0; i < 31; i++) {
+            if ((1 << i) >= value) break;
+        }
+        return i;
+    }
+
+    public static int floorLog2(float value) {
+        int i;
+        for (i = 0; i < 31; i++) {
+            if ((1 << i) > value) break;
+        }
+        return i - 1;
+    }
+
+    public static void closeSilently(ParcelFileDescriptor fd) {
+        try {
+            if (fd != null) fd.close();
+        } catch (Throwable t) {
+            Log.w(TAG, "fail to close", t);
+        }
+    }
+
+    public static void closeSilently(Cursor cursor) {
+        try {
+            if (cursor != null) cursor.close();
+        } catch (Throwable t) {
+            Log.w(TAG, "fail to close", t);
+        }
+    }
+
+    public static float interpolateAngle(
+            float source, float target, float progress) {
+        // interpolate the angle from source to target
+        // We make the difference in the range of [-179, 180], this is the
+        // shortest path to change source to target.
+        float diff = target - source;
+        if (diff < 0) diff += 360f;
+        if (diff > 180) diff -= 360f;
+
+        float result = source + diff * progress;
+        return result < 0 ? result + 360f : result;
+    }
+
+    public static float interpolateScale(
+            float source, float target, float progress) {
+        return source + progress * (target - source);
+    }
+
+    public static String ensureNotNull(String value) {
+        return value == null ? "" : value;
+    }
+
+    public static float parseFloatSafely(String content, float defaultValue) {
+        if (content == null) return defaultValue;
+        try {
+            return Float.parseFloat(content);
+        } catch (NumberFormatException e) {
+            return defaultValue;
+        }
+    }
+
+    public static int parseIntSafely(String content, int defaultValue) {
+        if (content == null) return defaultValue;
+        try {
+            return Integer.parseInt(content);
+        } catch (NumberFormatException e) {
+            return defaultValue;
+        }
+    }
+
+    public static boolean isNullOrEmpty(String exifMake) {
+        return TextUtils.isEmpty(exifMake);
+    }
+
+    public static void waitWithoutInterrupt(Object object) {
+        try {
+            object.wait();
+        } catch (InterruptedException e) {
+            Log.w(TAG, "unexpected interrupt: " + object);
+        }
+    }
+
+    public static boolean handleInterrruptedException(Throwable e) {
+        // A helper to deal with the interrupt exception
+        // If an interrupt detected, we will setup the bit again.
+        if (e instanceof InterruptedIOException
+                || e instanceof InterruptedException) {
+            Thread.currentThread().interrupt();
+            return true;
+        }
+        return false;
+    }
+
+    /**
+     * @return String with special XML characters escaped.
+     */
+    public static String escapeXml(String s) {
+        StringBuilder sb = new StringBuilder();
+        for (int i = 0, len = s.length(); i < len; ++i) {
+            char c = s.charAt(i);
+            switch (c) {
+                case '<':  sb.append("&lt;"); break;
+                case '>':  sb.append("&gt;"); break;
+                case '\"': sb.append("&quot;"); break;
+                case '\'': sb.append("&#039;"); break;
+                case '&':  sb.append("&amp;"); break;
+                default: sb.append(c);
+            }
+        }
+        return sb.toString();
+    }
+
+    public static String getUserAgent(Context context) {
+        PackageInfo packageInfo;
+        try {
+            packageInfo = context.getPackageManager().getPackageInfo(context.getPackageName(), 0);
+        } catch (NameNotFoundException e) {
+            throw new IllegalStateException("getPackageInfo failed");
+        }
+        return String.format("%s/%s; %s/%s/%s/%s; %s/%s/%s",
+                packageInfo.packageName,
+                packageInfo.versionName,
+                Build.BRAND,
+                Build.DEVICE,
+                Build.MODEL,
+                Build.ID,
+                Build.VERSION.SDK_INT,
+                Build.VERSION.RELEASE,
+                Build.VERSION.INCREMENTAL);
+    }
+
+    public static String[] copyOf(String[] source, int newSize) {
+        String[] result = new String[newSize];
+        newSize = Math.min(source.length, newSize);
+        System.arraycopy(source, 0, result, 0, newSize);
+        return result;
+    }
+
+    // Mask information for debugging only. It returns <code>info.toString()</code> directly
+    // for debugging build (i.e., 'eng' and 'userdebug') and returns a mask ("****")
+    // in release build to protect the information (e.g. for privacy issue).
+    public static String maskDebugInfo(Object info) {
+        if (info == null) return null;
+        String s = info.toString();
+        int length = Math.min(s.length(), MASK_STRING.length());
+        return IS_DEBUG_BUILD ? s : MASK_STRING.substring(0, length);
+    }
+
+    // This method should be ONLY used for debugging.
+    public static void debug(String message, Object ... args) {
+        Log.v(DEBUG_TAG, String.format(message, args));
+    }
+}
\ No newline at end of file
diff --git a/src/com/android/camera/support/filtershow/crop/CropExtras.java b/src/com/android/camera/support/filtershow/crop/CropExtras.java
new file mode 100644
index 0000000..6250a35
--- /dev/null
+++ b/src/com/android/camera/support/filtershow/crop/CropExtras.java
@@ -0,0 +1,106 @@
+package com.android.camera.support.filtershow.crop;
+
+
+import android.net.Uri;
+
+public class CropExtras {
+
+    public static final String KEY_CROPPED_RECT = "cropped-rect";
+    public static final String KEY_OUTPUT_X = "outputX";
+    public static final String KEY_OUTPUT_Y = "outputY";
+    public static final String KEY_SCALE = "scale";
+    public static final String KEY_SCALE_UP_IF_NEEDED = "scaleUpIfNeeded";
+    public static final String KEY_ASPECT_X = "aspectX";
+    public static final String KEY_ASPECT_Y = "aspectY";
+    public static final String KEY_SET_AS_WALLPAPER = "set-as-wallpaper";
+    public static final String KEY_RETURN_DATA = "return-data";
+    public static final String KEY_DATA = "data";
+    public static final String KEY_SPOTLIGHT_X = "spotlightX";
+    public static final String KEY_SPOTLIGHT_Y = "spotlightY";
+    public static final String KEY_SHOW_WHEN_LOCKED = "showWhenLocked";
+    public static final String KEY_OUTPUT_FORMAT = "outputFormat";
+
+    private int mOutputX = 0;
+    private int mOutputY = 0;
+    private boolean mScaleUp = true;
+    private int mAspectX = 0;
+    private int mAspectY = 0;
+    private boolean mSetAsWallpaper = false;
+    private boolean mReturnData = false;
+    private Uri mExtraOutput = null;
+    private String mOutputFormat = null;
+    private boolean mShowWhenLocked = false;
+    private float mSpotlightX = 0;
+    private float mSpotlightY = 0;
+
+    public CropExtras(int outputX, int outputY, boolean scaleUp, int aspectX, int aspectY,
+            boolean setAsWallpaper, boolean returnData, Uri extraOutput, String outputFormat,
+            boolean showWhenLocked, float spotlightX, float spotlightY) {
+        mOutputX = outputX;
+        mOutputY = outputY;
+        mScaleUp = scaleUp;
+        mAspectX = aspectX;
+        mAspectY = aspectY;
+        mSetAsWallpaper = setAsWallpaper;
+        mReturnData = returnData;
+        mExtraOutput = extraOutput;
+        mOutputFormat = outputFormat;
+        mShowWhenLocked = showWhenLocked;
+        mSpotlightX = spotlightX;
+        mSpotlightY = spotlightY;
+    }
+
+    public CropExtras(CropExtras c) {
+        this(c.mOutputX, c.mOutputY, c.mScaleUp, c.mAspectX, c.mAspectY, c.mSetAsWallpaper,
+                c.mReturnData, c.mExtraOutput, c.mOutputFormat, c.mShowWhenLocked,
+                c.mSpotlightX, c.mSpotlightY);
+    }
+
+    public int getOutputX() {
+        return mOutputX;
+    }
+
+    public int getOutputY() {
+        return mOutputY;
+    }
+
+    public boolean getScaleUp() {
+        return mScaleUp;
+    }
+
+    public int getAspectX() {
+        return mAspectX;
+    }
+
+    public int getAspectY() {
+        return mAspectY;
+    }
+
+    public boolean getSetAsWallpaper() {
+        return mSetAsWallpaper;
+    }
+
+    public boolean getReturnData() {
+        return mReturnData;
+    }
+
+    public Uri getExtraOutput() {
+        return mExtraOutput;
+    }
+
+    public String getOutputFormat() {
+        return mOutputFormat;
+    }
+
+    public boolean getShowWhenLocked() {
+        return mShowWhenLocked;
+    }
+
+    public float getSpotlightX() {
+        return mSpotlightX;
+    }
+
+    public float getSpotlightY() {
+        return mSpotlightY;
+    }
+}
\ No newline at end of file
diff --git a/src/com/android/camera/support/glrenderer/BasicTexture.java b/src/com/android/camera/support/glrenderer/BasicTexture.java
new file mode 100644
index 0000000..39cc519
--- /dev/null
+++ b/src/com/android/camera/support/glrenderer/BasicTexture.java
@@ -0,0 +1,197 @@
+package com.android.camera.support.glrenderer;
+
+
+import java.util.WeakHashMap;
+
+import com.android.camera.support.common.Utils;
+
+import android.util.Log;
+
+// BasicTexture is a Texture corresponds to a real GL texture.
+// The state of a BasicTexture indicates whether its data is loaded to GL memory.
+// If a BasicTexture is loaded into GL memory, it has a GL texture id.
+public abstract class BasicTexture implements Texture {
+
+    @SuppressWarnings("unused")
+    private static final String TAG = "BasicTexture";
+    protected static final int UNSPECIFIED = -1;
+
+    protected static final int STATE_UNLOADED = 0;
+    protected static final int STATE_LOADED = 1;
+    protected static final int STATE_ERROR = -1;
+
+    // Log a warning if a texture is larger along a dimension
+    private static final int MAX_TEXTURE_SIZE = 4096;
+
+    protected int mId = -1;
+    protected int mState;
+
+    protected int mWidth = UNSPECIFIED;
+    protected int mHeight = UNSPECIFIED;
+
+    protected int mTextureWidth;
+    protected int mTextureHeight;
+
+    private boolean mHasBorder;
+
+    protected GLCanvas mCanvasRef = null;
+    private static WeakHashMap<BasicTexture, Object> sAllTextures
+            = new WeakHashMap<BasicTexture, Object>();
+    private static ThreadLocal sInFinalizer = new ThreadLocal();
+
+    protected BasicTexture(GLCanvas canvas, int id, int state) {
+        setAssociatedCanvas(canvas);
+        mId = id;
+        mState = state;
+        synchronized (sAllTextures) {
+            sAllTextures.put(this, null);
+        }
+    }
+
+    protected BasicTexture() {
+        this(null, 0, STATE_UNLOADED);
+    }
+
+    protected void setAssociatedCanvas(GLCanvas canvas) {
+        mCanvasRef = canvas;
+    }
+
+    /**
+     * Sets the content size of this texture. In OpenGL, the actual texture
+     * size must be of power of 2, the size of the content may be smaller.
+     */
+    public void setSize(int width, int height) {
+        mWidth = width;
+        mHeight = height;
+        mTextureWidth = width > 0 ? Utils.nextPowerOf2(width) : 0;
+        mTextureHeight = height > 0 ? Utils.nextPowerOf2(height) : 0;
+        if (mTextureWidth > MAX_TEXTURE_SIZE || mTextureHeight > MAX_TEXTURE_SIZE) {
+            Log.w(TAG, String.format("texture is too large: %d x %d",
+                    mTextureWidth, mTextureHeight), new Exception());
+        }
+    }
+
+    public boolean isFlippedVertically() {
+      return false;
+    }
+
+    public int getId() {
+        return mId;
+    }
+
+    @Override
+    public int getWidth() {
+        return mWidth;
+    }
+
+    @Override
+    public int getHeight() {
+        return mHeight;
+    }
+
+    // Returns the width rounded to the next power of 2.
+    public int getTextureWidth() {
+        return mTextureWidth;
+    }
+
+    // Returns the height rounded to the next power of 2.
+    public int getTextureHeight() {
+        return mTextureHeight;
+    }
+
+    // Returns true if the texture has one pixel transparent border around the
+    // actual content. This is used to avoid jigged edges.
+    //
+    // The jigged edges appear because we use GL_CLAMP_TO_EDGE for texture wrap
+    // mode (GL_CLAMP is not available in OpenGL ES), so a pixel partially
+    // covered by the texture will use the color of the edge texel. If we add
+    // the transparent border, the color of the edge texel will be mixed with
+    // appropriate amount of transparent.
+    //
+    // Currently our background is black, so we can draw the thumbnails without
+    // enabling blending.
+    public boolean hasBorder() {
+        return mHasBorder;
+    }
+
+    protected void setBorder(boolean hasBorder) {
+        mHasBorder = hasBorder;
+    }
+
+    @Override
+    public void draw(GLCanvas canvas, int x, int y) {
+        canvas.drawTexture(this, x, y, getWidth(), getHeight());
+    }
+
+    @Override
+    public void draw(GLCanvas canvas, int x, int y, int w, int h) {
+        canvas.drawTexture(this, x, y, w, h);
+    }
+
+    // onBind is called before GLCanvas binds this texture.
+    // It should make sure the data is uploaded to GL memory.
+    abstract protected boolean onBind(GLCanvas canvas);
+
+    // Returns the GL texture target for this texture (e.g. GL_TEXTURE_2D).
+    abstract protected int getTarget();
+
+    public boolean isLoaded() {
+        return mState == STATE_LOADED;
+    }
+
+    // recycle() is called when the texture will never be used again,
+    // so it can free all resources.
+    public void recycle() {
+        freeResource();
+    }
+
+    // yield() is called when the texture will not be used temporarily,
+    // so it can free some resources.
+    // The default implementation unloads the texture from GL memory, so
+    // the subclass should make sure it can reload the texture to GL memory
+    // later, or it will have to override this method.
+    public void yield() {
+        freeResource();
+    }
+
+    private void freeResource() {
+        GLCanvas canvas = mCanvasRef;
+        if (canvas != null && mId != -1) {
+            canvas.unloadTexture(this);
+            mId = -1; // Don't free it again.
+        }
+        mState = STATE_UNLOADED;
+        setAssociatedCanvas(null);
+    }
+
+    @Override
+    protected void finalize() {
+        sInFinalizer.set(BasicTexture.class);
+        recycle();
+        sInFinalizer.set(null);
+    }
+
+    // This is for deciding if we can call Bitmap's recycle().
+    // We cannot call Bitmap's recycle() in finalizer because at that point
+    // the finalizer of Bitmap may already be called so recycle() will crash.
+    public static boolean inFinalizer() {
+        return sInFinalizer.get() != null;
+    }
+
+    public static void yieldAllTextures() {
+        synchronized (sAllTextures) {
+            for (BasicTexture t : sAllTextures.keySet()) {
+                t.yield();
+            }
+        }
+    }
+
+    public static void invalidateAllTextures() {
+        synchronized (sAllTextures) {
+            for (BasicTexture t : sAllTextures.keySet()) {
+                t.mState = STATE_UNLOADED;
+                t.setAssociatedCanvas(null);
+            }
+        }
+    }
+}
diff --git a/src/com/android/camera/support/glrenderer/BitmapTexture.java b/src/com/android/camera/support/glrenderer/BitmapTexture.java
new file mode 100644
index 0000000..b62a444
--- /dev/null
+++ b/src/com/android/camera/support/glrenderer/BitmapTexture.java
@@ -0,0 +1,38 @@
+package com.android.camera.support.glrenderer;
+
+import android.graphics.Bitmap;
+
+import junit.framework.Assert;
+
+// BitmapTexture is a texture whose content is specified by a fixed Bitmap.
+//
+// The texture does not own the Bitmap. The user should make sure the Bitmap
+// is valid during the texture's lifetime. When the texture is recycled, it
+// does not free the Bitmap.
+public class BitmapTexture extends UploadedTexture {
+    protected Bitmap mContentBitmap;
+
+    public BitmapTexture(Bitmap bitmap) {
+        this(bitmap, false);
+    }
+
+    public BitmapTexture(Bitmap bitmap, boolean hasBorder) {
+        super(hasBorder);
+        Assert.assertTrue(bitmap != null && !bitmap.isRecycled());
+        mContentBitmap = bitmap;
+    }
+
+    @Override
+    protected void onFreeBitmap(Bitmap bitmap) {
+        // Do nothing.
+    }
+
+    @Override
+    protected Bitmap onGetBitmap() {
+        return mContentBitmap;
+    }
+
+    public Bitmap getBitmap() {
+        return mContentBitmap;
+    }
+}
diff --git a/src/com/android/camera/support/glrenderer/ExtTexture.java b/src/com/android/camera/support/glrenderer/ExtTexture.java
new file mode 100644
index 0000000..121e17d
--- /dev/null
+++ b/src/com/android/camera/support/glrenderer/ExtTexture.java
@@ -0,0 +1,45 @@
+package com.android.camera.support.glrenderer;
+
+
+//ExtTexture is a texture whose content comes from a external texture.
+//Before drawing, setSize() should be called.
+public class ExtTexture extends BasicTexture {
+
+ private int mTarget;
+
+ public ExtTexture(GLCanvas canvas, int target) {
+     GLId glId = canvas.getGLId();
+     mId = glId.generateTexture();
+     mTarget = target;
+ }
+
+ private void uploadToCanvas(GLCanvas canvas) {
+     canvas.setTextureParameters(this);
+     setAssociatedCanvas(canvas);
+     mState = STATE_LOADED;
+ }
+
+ @Override
+ protected boolean onBind(GLCanvas canvas) {
+     if (!isLoaded()) {
+         uploadToCanvas(canvas);
+     }
+
+     return true;
+ }
+
+ @Override
+ public int getTarget() {
+     return mTarget;
+ }
+
+ @Override
+ public boolean isOpaque() {
+     return true;
+ }
+
+ @Override
+ public void yield() {
+     // we cannot free the texture because we have no backup.
+ }
+}
diff --git a/src/com/android/camera/support/glrenderer/GLCanvas.java b/src/com/android/camera/support/glrenderer/GLCanvas.java
new file mode 100644
index 0000000..1e4ec2f
--- /dev/null
+++ b/src/com/android/camera/support/glrenderer/GLCanvas.java
@@ -0,0 +1,201 @@
+package com.android.camera.support.glrenderer;
+
+import android.graphics.Bitmap;
+import android.graphics.Rect;
+import android.graphics.RectF;
+
+import javax.microedition.khronos.opengles.GL11;
+
+//
+// GLCanvas gives a convenient interface to draw using OpenGL.
+//
+// When a rectangle is specified in this interface, it means the region
+// [x, x+width) * [y, y+height)
+//
+public interface GLCanvas {
+
+    public GLId getGLId();
+
+    // Tells GLCanvas the size of the underlying GL surface. This should be
+    // called before first drawing and when the size of GL surface is changed.
+    // This is called by GLRoot and should not be called by the clients
+    // who only want to draw on the GLCanvas. Both width and height must be
+    // nonnegative.
+    public abstract void setSize(int width, int height);
+
+    // Clear the drawing buffers. This should only be used by GLRoot.
+    public abstract void clearBuffer();
+
+    public abstract void clearBuffer(float[] argb);
+
+    // Sets and gets the current alpha, alpha must be in [0, 1].
+    public abstract void setAlpha(float alpha);
+
+    public abstract float getAlpha();
+
+    // (current alpha) = (current alpha) * alpha
+    public abstract void multiplyAlpha(float alpha);
+
+    // Change the current transform matrix.
+    public abstract void translate(float x, float y, float z);
+
+    public abstract void translate(float x, float y);
+
+    public abstract void scale(float sx, float sy, float sz);
+
+    public abstract void rotate(float angle, float x, float y, float z);
+
+    public abstract void multiplyMatrix(float[] mMatrix, int offset);
+
+    // Pushes the configuration state (matrix, and alpha) onto
+    // a private stack.
+    public abstract void save();
+
+    // Same as save(), but only save those specified in saveFlags.
+    public abstract void save(int saveFlags);
+
+    public static final int SAVE_FLAG_ALL = 0xFFFFFFFF;
+    public static final int SAVE_FLAG_ALPHA = 0x01;
+    public static final int SAVE_FLAG_MATRIX = 0x02;
+
+    // Pops from the top of the stack as current configuration state (matrix,
+    // alpha, and clip). This call balances a previous call to save(), and is
+    // used to remove all modifications to the configuration state since the
+    // last save call.
+    public abstract void restore();
+
+    // Draws a line using the specified paint from (x1, y1) to (x2, y2).
+    // (Both end points are included).
+    public abstract void drawLine(float x1, float y1, float x2, float y2, GLPaint paint);
+
+    // Draws a rectangle using the specified paint from (x1, y1) to (x2, y2).
+    // (Both end points are included).
+    public abstract void drawRect(float x1, float y1, float x2, float y2, GLPaint paint);
+
+    // Fills the specified rectangle with the specified color.
+    public abstract void fillRect(float x, float y, float width, float height, int color);
+
+    // Draws a texture to the specified rectangle.
+    public abstract void drawTexture(
+            BasicTexture texture, int x, int y, int width, int height);
+
+    public abstract void drawMesh(BasicTexture tex, int x, int y, int xyBuffer,
+            int uvBuffer, int indexBuffer, int indexCount);
+
+    // Draws the source rectangle part of the texture to the target rectangle.
+    public abstract void drawTexture(BasicTexture texture, RectF source, RectF target);
+
+    // Draw a texture with a specified texture transform.
+    public abstract void drawTexture(BasicTexture texture, float[] mTextureTransform,
+                int x, int y, int w, int h);
+
+    // Draw two textures to the specified rectangle. The actual texture used is
+    // from * (1 - ratio) + to * ratio
+    // The two textures must have the same size.
+    public abstract void drawMixed(BasicTexture from, int toColor,
+            float ratio, int x, int y, int w, int h);
+
+    // Draw a region of a texture and a specified color to the specified
+    // rectangle. The actual color used is from * (1 - ratio) + to * ratio.
+    // The region of the texture is defined by parameter "src". The target
+    // rectangle is specified by parameter "target".
+    public abstract void drawMixed(BasicTexture from, int toColor,
+            float ratio, RectF src, RectF target);
+
+    // Unloads the specified texture from the canvas. The resource allocated
+    // to draw the texture will be released. The specified texture will return
+    // to the unloaded state. This function should be called only from
+    // BasicTexture or its descendant
+    public abstract boolean unloadTexture(BasicTexture texture);
+
+    // Delete the specified buffer object, similar to unloadTexture.
+    public abstract void deleteBuffer(int bufferId);
+
+    // Delete the textures and buffers in GL side. This function should only be
+    // called in the GL thread.
+    public abstract void deleteRecycledResources();
+
+    // Dump statistics information and clear the counters. For debug only.
+    public abstract void dumpStatisticsAndClear();
+
+    public abstract void beginRenderTarget(RawTexture texture);
+
+    public abstract void endRenderTarget();
+
+    /**
+     * Sets texture parameters to use GL_CLAMP_TO_EDGE for both
+     * GL_TEXTURE_WRAP_S and GL_TEXTURE_WRAP_T. Sets texture parameters to be
+     * GL_LINEAR for GL_TEXTURE_MIN_FILTER and GL_TEXTURE_MAG_FILTER.
+     * bindTexture() must be called prior to this.
+     *
+     * @param texture The texture to set parameters on.
+     */
+    public abstract void setTextureParameters(BasicTexture texture);
+
+    /**
+     * Initializes the texture to a size by calling texImage2D on it.
+     *
+     * @param texture The texture to initialize the size.
+     * @param format The texture format (e.g. GL_RGBA)
+     * @param type The texture type (e.g. GL_UNSIGNED_BYTE)
+     */
+    public abstract void initializeTextureSize(BasicTexture texture, int format, int type);
+
+    /**
+     * Initializes the texture to a size by calling texImage2D on it.
+     *
+     * @param texture The texture to initialize the size.
+     * @param bitmap The bitmap to initialize the bitmap with.
+     */
+    public abstract void initializeTexture(BasicTexture texture, Bitmap bitmap);
+
+    /**
+     * Calls glTexSubImage2D to upload a bitmap to the texture.
+     *
+     * @param texture The target texture to write to.
+     * @param xOffset Specifies a texel offset in the x direction within the
+     *            texture array.
+     * @param yOffset Specifies a texel offset in the y direction within the
+     *            texture array.
+     * @param format The texture format (e.g. GL_RGBA)
+     * @param type The texture type (e.g. GL_UNSIGNED_BYTE)
+     */
+    public abstract void texSubImage2D(BasicTexture texture, int xOffset, int yOffset,
+            Bitmap bitmap,
+            int format, int type);
+
+    /**
+     * Generates buffers and uploads the buffer data.
+     *
+     * @param buffer The buffer to upload
+     * @return The buffer ID that was generated.
+     */
+    public abstract int uploadBuffer(java.nio.FloatBuffer buffer);
+
+    /**
+     * Generates buffers and uploads the element array buffer data.
+     *
+     * @param buffer The buffer to upload
+     * @return The buffer ID that was generated.
+     */
+    public abstract int uploadBuffer(java.nio.ByteBuffer buffer);
+
+    /**
+     * After LightCycle makes GL calls, this method is called to restore the GL
+     * configuration to the one expected by GLCanvas.
+     */
+    public abstract void recoverFromLightCycle();
+
+    /**
+     * Gets the bounds given by x, y, width, and height as well as the internal
+     * matrix state. There is no special handling for non-90-degree rotations.
+     * It only considers the lower-left and upper-right corners as the bounds.
+     *
+     * @param bounds The output bounds to write to.
+     * @param x The left side of the input rectangle.
+     * @param y The bottom of the input rectangle.
+     * @param width The width of the input rectangle.
+     * @param height The height of the input rectangle.
+     */
+    public abstract void getBounds(Rect bounds, int x, int y, int width, int height);
+}
\ No newline at end of file
diff --git a/src/com/android/camera/support/glrenderer/GLId.java b/src/com/android/camera/support/glrenderer/GLId.java
new file mode 100644
index 0000000..695343b
--- /dev/null
+++ b/src/com/android/camera/support/glrenderer/GLId.java
@@ -0,0 +1,17 @@
+package com.android.camera.support.glrenderer;
+
+import javax.microedition.khronos.opengles.GL11;
+import javax.microedition.khronos.opengles.GL11ExtensionPack;
+
+// This mimics corresponding GL functions.
+public interface GLId {
+    public int generateTexture();
+
+    public void glGenBuffers(int n, int[] buffers, int offset);
+
+    public void glDeleteTextures(GL11 gl, int n, int[] textures, int offset);
+
+    public void glDeleteBuffers(GL11 gl, int n, int[] buffers, int offset);
+
+    public void glDeleteFramebuffers(GL11ExtensionPack gl11ep, int n, int[] buffers, int offset);
+}
diff --git a/src/com/android/camera/support/glrenderer/GLPaint.java b/src/com/android/camera/support/glrenderer/GLPaint.java
new file mode 100644
index 0000000..7c6af73
--- /dev/null
+++ b/src/com/android/camera/support/glrenderer/GLPaint.java
@@ -0,0 +1,26 @@
+package com.android.camera.support.glrenderer;
+
+
+import junit.framework.Assert;
+
+public class GLPaint {
+    private float mLineWidth = 1f;
+    private int mColor = 0;
+
+    public void setColor(int color) {
+        mColor = color;
+    }
+
+    public int getColor() {
+        return mColor;
+    }
+
+    public void setLineWidth(float width) {
+        Assert.assertTrue(width >= 0);
+        mLineWidth = width;
+    }
+
+    public float getLineWidth() {
+        return mLineWidth;
+    }
+}
diff --git a/src/com/android/camera/support/glrenderer/NinePatchChunk.java b/src/com/android/camera/support/glrenderer/NinePatchChunk.java
new file mode 100644
index 0000000..f7deb18
--- /dev/null
+++ b/src/com/android/camera/support/glrenderer/NinePatchChunk.java
@@ -0,0 +1,66 @@
+package com.android.camera.support.glrenderer;
+
+import android.graphics.Rect;
+
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+
+// See "frameworks/base/include/utils/ResourceTypes.h" for the format of
+// NinePatch chunk.
+class NinePatchChunk {
+
+    public static final int NO_COLOR = 0x00000001;
+    public static final int TRANSPARENT_COLOR = 0x00000000;
+
+    public Rect mPaddings = new Rect();
+
+    public int mDivX[];
+    public int mDivY[];
+    public int mColor[];
+
+    private static void readIntArray(int[] data, ByteBuffer buffer) {
+        for (int i = 0, n = data.length; i < n; ++i) {
+            data[i] = buffer.getInt();
+        }
+    }
+
+    private static void checkDivCount(int length) {
+        if (length == 0 || (length & 0x01) != 0) {
+            throw new RuntimeException("invalid nine-patch: " + length);
+        }
+    }
+
+    public static NinePatchChunk deserialize(byte[] data) {
+        ByteBuffer byteBuffer =
+                ByteBuffer.wrap(data).order(ByteOrder.nativeOrder());
+
+        byte wasSerialized = byteBuffer.get();
+        if (wasSerialized == 0) return null;
+
+        NinePatchChunk chunk = new NinePatchChunk();
+        chunk.mDivX = new int[byteBuffer.get()];
+        chunk.mDivY = new int[byteBuffer.get()];
+        chunk.mColor = new int[byteBuffer.get()];
+
+        checkDivCount(chunk.mDivX.length);
+        checkDivCount(chunk.mDivY.length);
+
+        // skip 8 bytes
+        byteBuffer.getInt();
+        byteBuffer.getInt();
+
+        chunk.mPaddings.left = byteBuffer.getInt();
+        chunk.mPaddings.right = byteBuffer.getInt();
+        chunk.mPaddings.top = byteBuffer.getInt();
+        chunk.mPaddings.bottom = byteBuffer.getInt();
+
+        // skip 4 bytes
+        byteBuffer.getInt();
+
+        readIntArray(chunk.mDivX, byteBuffer);
+        readIntArray(chunk.mDivY, byteBuffer);
+        readIntArray(chunk.mColor, byteBuffer);
+
+        return chunk;
+    }
+}
\ No newline at end of file
diff --git a/src/com/android/camera/support/glrenderer/NinePatchTexture.java b/src/com/android/camera/support/glrenderer/NinePatchTexture.java
new file mode 100644
index 0000000..c69afd6
--- /dev/null
+++ b/src/com/android/camera/support/glrenderer/NinePatchTexture.java
@@ -0,0 +1,408 @@
+package com.android.camera.support.glrenderer;
+
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.nio.FloatBuffer;
+
+import android.content.Context;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.graphics.Rect;
+
+import com.android.camera.support.common.Utils;
+
+// NinePatchTexture is a texture backed by a NinePatch resource.
+//
+// getPaddings() returns paddings specified in the NinePatch.
+// getNinePatchChunk() returns the layout data specified in the NinePatch.
+//
+public class NinePatchTexture extends ResourceTexture {
+    @SuppressWarnings("unused")
+    private static final String TAG = "NinePatchTexture";
+    private NinePatchChunk mChunk;
+    private SmallCache<NinePatchInstance> mInstanceCache
+            = new SmallCache<NinePatchInstance>();
+
+    public NinePatchTexture(Context context, int resId) {
+        super(context, resId);
+    }
+
+    @Override
+    protected Bitmap onGetBitmap() {
+        if (mBitmap != null) return mBitmap;
+
+        BitmapFactory.Options options = new BitmapFactory.Options();
+        options.inPreferredConfig = Bitmap.Config.ARGB_8888;
+        Bitmap bitmap = BitmapFactory.decodeResource(
+                mContext.getResources(), mResId, options);
+        mBitmap = bitmap;
+        setSize(bitmap.getWidth(), bitmap.getHeight());
+        byte[] chunkData = bitmap.getNinePatchChunk();
+        mChunk = chunkData == null
+                ? null
+                : NinePatchChunk.deserialize(bitmap.getNinePatchChunk());
+        if (mChunk == null) {
+            throw new RuntimeException("invalid nine-patch image: " + mResId);
+        }
+        return bitmap;
+    }
+
+    public Rect getPaddings() {
+        // get the paddings from nine patch
+        if (mChunk == null) onGetBitmap();
+        return mChunk.mPaddings;
+    }
+
+    public NinePatchChunk getNinePatchChunk() {
+        if (mChunk == null) onGetBitmap();
+        return mChunk;
+    }
+
+    // This is a simple cache for a small number of things. Linear search
+    // is used because the cache is small. It also tries to remove less used
+    // item when the cache is full by moving the often-used items to the front.
+    private static class SmallCache<V> {
+        private static final int CACHE_SIZE = 16;
+        private static final int CACHE_SIZE_START_MOVE = CACHE_SIZE / 2;
+        private int[] mKey = new int[CACHE_SIZE];
+        private V[] mValue = (V[]) new Object[CACHE_SIZE];
+        private int mCount;  // number of items in this cache
+
+        // Puts a value into the cache. If the cache is full, also returns
+        // a less used item, otherwise returns null.
+        public V put(int key, V value) {
+            if (mCount == CACHE_SIZE) {
+                V old = mValue[CACHE_SIZE - 1];  // remove the last item
+                mKey[CACHE_SIZE - 1] = key;
+                mValue[CACHE_SIZE - 1] = value;
+                return old;
+            } else {
+                mKey[mCount] = key;
+                mValue[mCount] = value;
+                mCount++;
+                return null;
+            }
+        }
+
+        public V get(int key) {
+            for (int i = 0; i < mCount; i++) {
+                if (mKey[i] == key) {
+                    // Move the accessed item one position to the front, so it
+                    // will less likely to be removed when cache is full. Only
+                    // do this if the cache is starting to get full.
+                    if (mCount > CACHE_SIZE_START_MOVE && i > 0) {
+                        int tmpKey = mKey[i];
+                        mKey[i] = mKey[i - 1];
+                        mKey[i - 1] = tmpKey;
+
+                        V tmpValue = mValue[i];
+                        mValue[i] = mValue[i - 1];
+                        mValue[i - 1] = tmpValue;
+                    }
+                    return mValue[i];
+                }
+            }
+            return null;
+        }
+
+        public void clear() {
+            for (int i = 0; i < mCount; i++) {
+                mValue[i] = null;  // make sure it's can be garbage-collected.
+            }
+            mCount = 0;
+        }
+
+        public int size() {
+            return mCount;
+        }
+
+        public V valueAt(int i) {
+            return mValue[i];
+        }
+    }
+
+    private NinePatchInstance findInstance(GLCanvas canvas, int w, int h) {
+        int key = w;
+        key = (key << 16) | h;
+        NinePatchInstance instance = mInstanceCache.get(key);
+
+        if (instance == null) {
+            instance = new NinePatchInstance(this, w, h);
+            NinePatchInstance removed = mInstanceCache.put(key, instance);
+            if (removed != null) {
+                removed.recycle(canvas);
+            }
+        }
+
+        return instance;
+    }
+
+    @Override
+    public void draw(GLCanvas canvas, int x, int y, int w, int h) {
+        if (!isLoaded()) {
+            mInstanceCache.clear();
+        }
+
+        if (w != 0 && h != 0) {
+            findInstance(canvas, w, h).draw(canvas, this, x, y);
+        }
+    }
+
+    @Override
+    public void recycle() {
+        super.recycle();
+        GLCanvas canvas = mCanvasRef;
+        if (canvas == null) return;
+        int n = mInstanceCache.size();
+        for (int i = 0; i < n; i++) {
+            NinePatchInstance instance = mInstanceCache.valueAt(i);
+            instance.recycle(canvas);
+        }
+        mInstanceCache.clear();
+    }
+}
+
+// This keeps data for a specialization of NinePatchTexture with the size
+// (width, height). We pre-compute the coordinates for efficiency.
+class NinePatchInstance {
+
+    @SuppressWarnings("unused")
+    private static final String TAG = "NinePatchInstance";
+
+    // We need 16 vertices for a normal nine-patch image (the 4x4 vertices)
+    private static final int VERTEX_BUFFER_SIZE = 16 * 2;
+
+    // We need 22 indices for a normal nine-patch image, plus 2 for each
+    // transparent region. Current there are at most 1 transparent region.
+    private static final int INDEX_BUFFER_SIZE = 22 + 2;
+
+    private FloatBuffer mXyBuffer;
+    private FloatBuffer mUvBuffer;
+    private ByteBuffer mIndexBuffer;
+
+    // Names for buffer names: xy, uv, index.
+    private int mXyBufferName = -1;
+    private int mUvBufferName;
+    private int mIndexBufferName;
+
+    private int mIdxCount;
+
+    public NinePatchInstance(NinePatchTexture tex, int width, int height) {
+        NinePatchChunk chunk = tex.getNinePatchChunk();
+
+        if (width <= 0 || height <= 0) {
+            throw new RuntimeException("invalid dimension");
+        }
+
+        // The code should be easily extended to handle the general cases by
+        // allocating more space for buffers. But let's just handle the only
+        // use case.
+        if (chunk.mDivX.length != 2 || chunk.mDivY.length != 2) {
+            throw new RuntimeException("unsupported nine patch");
+        }
+
+        float divX[] = new float[4];
+        float divY[] = new float[4];
+        float divU[] = new float[4];
+        float divV[] = new float[4];
+
+        int nx = stretch(divX, divU, chunk.mDivX, tex.getWidth(), width);
+        int ny = stretch(divY, divV, chunk.mDivY, tex.getHeight(), height);
+
+        prepareVertexData(divX, divY, divU, divV, nx, ny, chunk.mColor);
+    }
+
+    /**
+     * Stretches the texture according to the nine-patch rules. It will
+     * linearly distribute the strechy parts defined in the nine-patch chunk to
+     * the target area.
+     *
+     * <pre>
+     *                      source
+     *          /--------------^---------------\
+     *         u0    u1       u2  u3     u4   u5
+     * div ---> |fffff|ssssssss|fff|ssssss|ffff| ---> u
+     *          |    div0    div1 div2   div3  |
+     *          |     |       /   /      /    /
+     *          |     |      /   /     /    /
+     *          |     |     /   /    /    /
+     *          |fffff|ssss|fff|sss|ffff| ---> x
+     *         x0    x1   x2  x3  x4   x5
+     *          \----------v------------/
+     *                  target
+     *
+     * f: fixed segment
+     * s: stretchy segment
+     * </pre>
+     *
+     * @param div the stretch parts defined in nine-patch chunk
+     * @param source the length of the texture
+     * @param target the length on the drawing plan
+     * @param u output, the positions of these dividers in the texture
+     *        coordinate
+     * @param x output, the corresponding position of these dividers on the
+     *        drawing plan
+     * @return the number of these dividers.
+     */
+    private static int stretch(
+            float x[], float u[], int div[], int source, int target) {
+        int textureSize = Utils.nextPowerOf2(source);
+        float textureBound = (float) source / textureSize;
+
+        float stretch = 0;
+        for (int i = 0, n = div.length; i < n; i += 2) {
+            stretch += div[i + 1] - div[i];
+        }
+
+        float remaining = target - source + stretch;
+
+        float lastX = 0;
+        float lastU = 0;
+
+        x[0] = 0;
+        u[0] = 0;
+        for (int i = 0, n = div.length; i < n; i += 2) {
+            // Make the stretchy segment a little smaller to prevent sampling
+            // on neighboring fixed segments.
+            // fixed segment
+            x[i + 1] = lastX + (div[i] - lastU) + 0.5f;
+            u[i + 1] = Math.min((div[i] + 0.5f) / textureSize, textureBound);
+
+            // stretchy segment
+            float partU = div[i + 1] - div[i];
+            float partX = remaining * partU / stretch;
+            remaining -= partX;
+            stretch -= partU;
+
+            lastX = x[i + 1] + partX;
+            lastU = div[i + 1];
+            x[i + 2] = lastX - 0.5f;
+            u[i + 2] = Math.min((lastU - 0.5f)/ textureSize, textureBound);
+        }
+        // the last fixed segment
+        x[div.length + 1] = target;
+        u[div.length + 1] = textureBound;
+
+        // remove segments with length 0.
+        int last = 0;
+        for (int i = 1, n = div.length + 2; i < n; ++i) {
+            if ((x[i] - x[last]) < 1f) continue;
+            x[++last] = x[i];
+            u[last] = u[i];
+        }
+        return last + 1;
+    }
+
+    private void prepareVertexData(float x[], float y[], float u[], float v[],
+            int nx, int ny, int[] color) {
+        /*
+         * Given a 3x3 nine-patch image, the vertex order is defined as the
+         * following graph:
+         *
+         * (0) (1) (2) (3)
+         *  |  /|  /|  /|
+         *  | / | / | / |
+         * (4) (5) (6) (7)
+         *  | \ | \ | \ |
+         *  |  \|  \|  \|
+         * (8) (9) (A) (B)
+         *  |  /|  /|  /|
+         *  | / | / | / |
+         * (C) (D) (E) (F)
+         *
+         * And we draw the triangle strip in the following index order:
+         *
+         * index: 04152637B6A5948C9DAEBF
+         */
+        int pntCount = 0;
+        float xy[] = new float[VERTEX_BUFFER_SIZE];
+        float uv[] = new float[VERTEX_BUFFER_SIZE];
+        for (int j = 0; j < ny; ++j) {
+            for (int i = 0; i < nx; ++i) {
+                int xIndex = (pntCount++) << 1;
+                int yIndex = xIndex + 1;
+                xy[xIndex] = x[i];
+                xy[yIndex] = y[j];
+                uv[xIndex] = u[i];
+                uv[yIndex] = v[j];
+            }
+        }
+
+        int idxCount = 1;
+        boolean isForward = false;
+        byte index[] = new byte[INDEX_BUFFER_SIZE];
+        for (int row = 0; row < ny - 1; row++) {
+            --idxCount;
+            isForward = !isForward;
+
+            int start, end, inc;
+            if (isForward) {
+                start = 0;
+                end = nx;
+                inc = 1;
+            } else {
+                start = nx - 1;
+                end = -1;
+                inc = -1;
+            }
+
+            for (int col = start; col != end; col += inc) {
+                int k = row * nx + col;
+                if (col != start) {
+                    int colorIdx = row * (nx - 1) + col;
+                    if (isForward) colorIdx--;
+                    if (color[colorIdx] == NinePatchChunk.TRANSPARENT_COLOR) {
+                        index[idxCount] = index[idxCount - 1];
+                        ++idxCount;
+                        index[idxCount++] = (byte) k;
+                    }
+                }
+
+                index[idxCount++] = (byte) k;
+                index[idxCount++] = (byte) (k + nx);
+            }
+        }
+
+        mIdxCount = idxCount;
+
+        int size = (pntCount * 2) * (Float.SIZE / Byte.SIZE);
+        mXyBuffer = allocateDirectNativeOrderBuffer(size).asFloatBuffer();
+        mUvBuffer = allocateDirectNativeOrderBuffer(size).asFloatBuffer();
+        mIndexBuffer = allocateDirectNativeOrderBuffer(mIdxCount);
+
+        mXyBuffer.put(xy, 0, pntCount * 2).position(0);
+        mUvBuffer.put(uv, 0, pntCount * 2).position(0);
+        mIndexBuffer.put(index, 0, idxCount).position(0);
+    }
+
+    private static ByteBuffer allocateDirectNativeOrderBuffer(int size) {
+        return ByteBuffer.allocateDirect(size).order(ByteOrder.nativeOrder());
+    }
+
+    private void prepareBuffers(GLCanvas canvas) {
+        mXyBufferName = canvas.uploadBuffer(mXyBuffer);
+        mUvBufferName = canvas.uploadBuffer(mUvBuffer);
+        mIndexBufferName = canvas.uploadBuffer(mIndexBuffer);
+
+        // These buffers are never used again.
+        mXyBuffer = null;
+        mUvBuffer = null;
+        mIndexBuffer = null;
+    }
+
+    public void draw(GLCanvas canvas, NinePatchTexture tex, int x, int y) {
+        if (mXyBufferName == -1) {
+            prepareBuffers(canvas);
+        }
+        canvas.drawMesh(tex, x, y, mXyBufferName, mUvBufferName, mIndexBufferName, mIdxCount);
+    }
+
+    public void recycle(GLCanvas canvas) {
+        if (mXyBuffer == null) {
+            canvas.deleteBuffer(mXyBufferName);
+            canvas.deleteBuffer(mUvBufferName);
+            canvas.deleteBuffer(mIndexBufferName);
+            mXyBufferName = -1;
+        }
+    }
+}
\ No newline at end of file
diff --git a/src/com/android/camera/support/glrenderer/RawTexture.java b/src/com/android/camera/support/glrenderer/RawTexture.java
new file mode 100644
index 0000000..b86282d
--- /dev/null
+++ b/src/com/android/camera/support/glrenderer/RawTexture.java
@@ -0,0 +1,58 @@
+package com.android.camera.support.glrenderer;
+
+
+import android.util.Log;
+
+import javax.microedition.khronos.opengles.GL11;
+
+public class RawTexture extends BasicTexture {
+    private static final String TAG = "RawTexture";
+
+    private final boolean mOpaque;
+    private boolean mIsFlipped;
+
+    public RawTexture(int width, int height, boolean opaque) {
+        mOpaque = opaque;
+        setSize(width, height);
+    }
+
+    @Override
+    public boolean isOpaque() {
+        return mOpaque;
+    }
+
+    @Override
+    public boolean isFlippedVertically() {
+        return mIsFlipped;
+    }
+
+    public void setIsFlippedVertically(boolean isFlipped) {
+        mIsFlipped = isFlipped;
+    }
+
+    protected void prepare(GLCanvas canvas) {
+        GLId glId = canvas.getGLId();
+        mId = glId.generateTexture();
+        canvas.initializeTextureSize(this, GL11.GL_RGBA, GL11.GL_UNSIGNED_BYTE);
+        canvas.setTextureParameters(this);
+        mState = STATE_LOADED;
+        setAssociatedCanvas(canvas);
+    }
+
+    @Override
+    protected boolean onBind(GLCanvas canvas) {
+        if (isLoaded()) return true;
+        Log.w(TAG, "lost the content due to context change");
+        return false;
+    }
+
+    @Override
+     public void yield() {
+         // we cannot free the texture because we have no backup.
+     }
+
+    @Override
+    protected int getTarget() {
+        return GL11.GL_TEXTURE_2D;
+    }
+}
diff --git a/src/com/android/camera/support/glrenderer/ResourceTexture.java b/src/com/android/camera/support/glrenderer/ResourceTexture.java
new file mode 100644
index 0000000..121c184
--- /dev/null
+++ b/src/com/android/camera/support/glrenderer/ResourceTexture.java
@@ -0,0 +1,37 @@
+package com.android.camera.support.glrenderer;
+
+import android.content.Context;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+
+import junit.framework.Assert;
+
+// ResourceTexture is a texture whose Bitmap is decoded from a resource.
+// By default ResourceTexture is not opaque.
+public class ResourceTexture extends UploadedTexture {
+
+    protected final Context mContext;
+    protected final int mResId;
+
+    public ResourceTexture(Context context, int resId) {
+        Assert.assertNotNull(context);
+        mContext = context;
+        mResId = resId;
+        setOpaque(false);
+    }
+
+    @Override
+    protected Bitmap onGetBitmap() {
+        BitmapFactory.Options options = new BitmapFactory.Options();
+        options.inPreferredConfig = Bitmap.Config.ARGB_8888;
+        return BitmapFactory.decodeResource(
+                mContext.getResources(), mResId, options);
+    }
+
+    @Override
+    protected void onFreeBitmap(Bitmap bitmap) {
+        if (!inFinalizer()) {
+            bitmap.recycle();
+        }
+    }
+}
diff --git a/src/com/android/camera/support/glrenderer/Texture.java b/src/com/android/camera/support/glrenderer/Texture.java
new file mode 100644
index 0000000..4d1a49d
--- /dev/null
+++ b/src/com/android/camera/support/glrenderer/Texture.java
@@ -0,0 +1,27 @@
+package com.android.camera.support.glrenderer;
+
+//Texture is a rectangular image which can be drawn on GLCanvas.
+//The isOpaque() function gives a hint about whether the texture is opaque,
+//so the drawing can be done faster.
+//
+//This is the current texture hierarchy:
+//
+//Texture
+//-- ColorTexture
+//-- FadeInTexture
+//-- BasicTexture
+// -- UploadedTexture
+//    -- BitmapTexture
+//    -- Tile
+//    -- ResourceTexture
+//       -- NinePatchTexture
+//    -- CanvasTexture
+//       -- StringTexture
+//
+public interface Texture {
+ public int getWidth();
+ public int getHeight();
+ public void draw(GLCanvas canvas, int x, int y);
+ public void draw(GLCanvas canvas, int x, int y, int w, int h);
+ public boolean isOpaque();
+}
diff --git a/src/com/android/camera/support/glrenderer/UploadedTexture.java b/src/com/android/camera/support/glrenderer/UploadedTexture.java
new file mode 100644
index 0000000..106aa4e
--- /dev/null
+++ b/src/com/android/camera/support/glrenderer/UploadedTexture.java
@@ -0,0 +1,283 @@
+package com.android.camera.support.glrenderer;
+
+
+import android.graphics.Bitmap;
+import android.graphics.Bitmap.Config;
+import android.opengl.GLUtils;
+
+import junit.framework.Assert;
+
+import java.util.HashMap;
+
+import javax.microedition.khronos.opengles.GL11;
+
+// UploadedTextures use a Bitmap for the content of the texture.
+//
+// Subclasses should implement onGetBitmap() to provide the Bitmap and
+// implement onFreeBitmap(mBitmap) which will be called when the Bitmap
+// is not needed anymore.
+//
+// isContentValid() is meaningful only when the isLoaded() returns true.
+// It means whether the content needs to be updated.
+//
+// The user of this class should call recycle() when the texture is not
+// needed anymore.
+//
+// By default an UploadedTexture is opaque (so it can be drawn faster without
+// blending). The user or subclass can override it using setOpaque().
+public abstract class UploadedTexture extends BasicTexture {
+
+    // To prevent keeping allocation the borders, we store those used borders here.
+    // Since the length will be power of two, it won't use too much memory.
+    private static HashMap<BorderKey, Bitmap> sBorderLines =
+            new HashMap<BorderKey, Bitmap>();
+    private static BorderKey sBorderKey = new BorderKey();
+
+    @SuppressWarnings("unused")
+    private static final String TAG = "Texture";
+    private boolean mContentValid = true;
+
+    // indicate this textures is being uploaded in background
+    private boolean mIsUploading = false;
+    private boolean mOpaque = true;
+    private boolean mThrottled = false;
+    private static int sUploadedCount;
+    private static final int UPLOAD_LIMIT = 100;
+
+    protected Bitmap mBitmap;
+    private int mBorder;
+
+    protected UploadedTexture() {
+        this(false);
+    }
+
+    protected UploadedTexture(boolean hasBorder) {
+        super(null, 0, STATE_UNLOADED);
+        if (hasBorder) {
+            setBorder(true);
+            mBorder = 1;
+        }
+    }
+
+    protected void setIsUploading(boolean uploading) {
+        mIsUploading = uploading;
+    }
+
+    public boolean isUploading() {
+        return mIsUploading;
+    }
+
+    private static class BorderKey implements Cloneable {
+        public boolean vertical;
+        public Config config;
+        public int length;
+
+        @Override
+        public int hashCode() {
+            int x = config.hashCode() ^ length;
+            return vertical ? x : -x;
+        }
+
+        @Override
+        public boolean equals(Object object) {
+            if (!(object instanceof BorderKey)) return false;
+            BorderKey o = (BorderKey) object;
+            return vertical == o.vertical
+                    && config == o.config && length == o.length;
+        }
+
+        @Override
+        public BorderKey clone() {
+            try {
+                return (BorderKey) super.clone();
+            } catch (CloneNotSupportedException e) {
+                throw new AssertionError(e);
+            }
+        }
+    }
+
+    protected void setThrottled(boolean throttled) {
+        mThrottled = throttled;
+    }
+
+    private static Bitmap getBorderLine(
+            boolean vertical, Config config, int length) {
+        BorderKey key = sBorderKey;
+        key.vertical = vertical;
+        key.config = config;
+        key.length = length;
+        Bitmap bitmap = sBorderLines.get(key);
+        if (bitmap == null) {
+            bitmap = vertical
+                    ? Bitmap.createBitmap(1, length, config)
+                    : Bitmap.createBitmap(length, 1, config);
+            sBorderLines.put(key.clone(), bitmap);
+        }
+        return bitmap;
+    }
+
+    private Bitmap getBitmap() {
+        if (mBitmap == null) {
+            mBitmap = onGetBitmap();
+            int w = mBitmap.getWidth() + mBorder * 2;
+            int h = mBitmap.getHeight() + mBorder * 2;
+            if (mWidth == UNSPECIFIED) {
+                setSize(w, h);
+            }
+        }
+        return mBitmap;
+    }
+
+    private void freeBitmap() {
+        Assert.assertTrue(mBitmap != null);
+        onFreeBitmap(mBitmap);
+        mBitmap = null;
+    }
+
+    @Override
+    public int getWidth() {
+        if (mWidth == UNSPECIFIED) getBitmap();
+        return mWidth;
+    }
+
+    @Override
+    public int getHeight() {
+        if (mWidth == UNSPECIFIED) getBitmap();
+        return mHeight;
+    }
+
+    protected abstract Bitmap onGetBitmap();
+
+    protected abstract void onFreeBitmap(Bitmap bitmap);
+
+    protected void invalidateContent() {
+        if (mBitmap != null) freeBitmap();
+        mContentValid = false;
+        mWidth = UNSPECIFIED;
+        mHeight = UNSPECIFIED;
+    }
+
+    /**
+     * Whether the content on GPU is valid.
+     */
+    public boolean isContentValid() {
+        return isLoaded() && mContentValid;
+    }
+
+    /**
+     * Updates the content on GPU's memory.
+     * @param canvas
+     */
+    public void updateContent(GLCanvas canvas) {
+        if (!isLoaded()) {
+            if (mThrottled && ++sUploadedCount > UPLOAD_LIMIT) {
+                return;
+            }
+            uploadToCanvas(canvas);
+        } else if (!mContentValid) {
+            Bitmap bitmap = getBitmap();
+            int format = GLUtils.getInternalFormat(bitmap);
+            int type = GLUtils.getType(bitmap);
+            canvas.texSubImage2D(this, mBorder, mBorder, bitmap, format, type);
+            freeBitmap();
+            mContentValid = true;
+        }
+    }
+
+    public static void resetUploadLimit() {
+        sUploadedCount = 0;
+    }
+
+    public static boolean uploadLimitReached() {
+        return sUploadedCount > UPLOAD_LIMIT;
+    }
+
+    private void uploadToCanvas(GLCanvas canvas) {
+
+        Bitmap bitmap = getBitmap();
+        if (bitmap != null) {
+            try {
+                int bWidth = bitmap.getWidth();
+                int bHeight = bitmap.getHeight();
+                int width = bWidth + mBorder * 2;
+                int height = bHeight + mBorder * 2;
+                int texWidth = getTextureWidth();
+                int texHeight = getTextureHeight();
+
+                Assert.assertTrue(bWidth <= texWidth && bHeight <= texHeight);
+
+                // Upload the bitmap to a new texture.
+                mId = canvas.getGLId().generateTexture();
+                canvas.setTextureParameters(this);
+
+                if (bWidth == texWidth && bHeight == texHeight) {
+                    canvas.initializeTexture(this, bitmap);
+                } else {
+                    int format = GLUtils.getInternalFormat(bitmap);
+                    int type = GLUtils.getType(bitmap);
+                    Config config = bitmap.getConfig();
+
+                    canvas.initializeTextureSize(this, format, type);
+                    canvas.texSubImage2D(this, mBorder, mBorder, bitmap, format, type);
+
+                    if (mBorder > 0) {
+                        // Left border
+                        Bitmap line = getBorderLine(true, config, texHeight);
+                        canvas.texSubImage2D(this, 0, 0, line, format, type);
+
+                        // Top border
+                        line = getBorderLine(false, config, texWidth);
+                        canvas.texSubImage2D(this, 0, 0, line, format, type);
+                    }
+
+                    // Right border
+                    if (mBorder + bWidth < texWidth) {
+                        Bitmap line = getBorderLine(true, config, texHeight);
+                        canvas.texSubImage2D(this, mBorder + bWidth, 0, line, format, type);
+                    }
+
+                    // Bottom border
+                    if (mBorder + bHeight < texHeight) {
+                        Bitmap line = getBorderLine(false, config, texWidth);
+                        canvas.texSubImage2D(this, 0, mBorder + bHeight, line, format, type);
+                    }
+                }
+            } finally {
+                freeBitmap();
+            }
+            // Update texture state.
+            setAssociatedCanvas(canvas);
+            mState = STATE_LOADED;
+            mContentValid = true;
+        } else {
+            mState = STATE_ERROR;
+            throw new RuntimeException("Texture load fail, no bitmap");
+        }
+    }
+
+    @Override
+    protected boolean onBind(GLCanvas canvas) {
+        updateContent(canvas);
+        return isContentValid();
+    }
+
+    @Override
+    protected int getTarget() {
+        return GL11.GL_TEXTURE_2D;
+    }
+
+    public void setOpaque(boolean isOpaque) {
+        mOpaque = isOpaque;
+    }
+
+    @Override
+    public boolean isOpaque() {
+        return mOpaque;
+    }
+
+    @Override
+    public void recycle() {
+        super.recycle();
+        if (mBitmap != null) freeBitmap();
+    }
+}
\ No newline at end of file
diff --git a/src/com/android/camera/support/ui/BitmapScreenNail.java b/src/com/android/camera/support/ui/BitmapScreenNail.java
new file mode 100644
index 0000000..a0252b9
--- /dev/null
+++ b/src/com/android/camera/support/ui/BitmapScreenNail.java
@@ -0,0 +1,45 @@
+package com.android.camera.support.ui;
+
+import android.graphics.Bitmap;
+import android.graphics.RectF;
+
+import com.android.camera.support.glrenderer.BitmapTexture;
+import com.android.camera.support.glrenderer.GLCanvas;
+
+public class BitmapScreenNail implements ScreenNail {
+    private final BitmapTexture mBitmapTexture;
+
+    public BitmapScreenNail(Bitmap bitmap) {
+        mBitmapTexture = new BitmapTexture(bitmap);
+    }
+
+    @Override
+    public int getWidth() {
+        return mBitmapTexture.getWidth();
+    }
+
+    @Override
+    public int getHeight() {
+        return mBitmapTexture.getHeight();
+    }
+
+    @Override
+    public void draw(GLCanvas canvas, int x, int y, int width, int height) {
+        mBitmapTexture.draw(canvas, x, y, width, height);
+    }
+
+    @Override
+    public void noDraw() {
+        // do nothing
+    }
+
+    @Override
+    public void recycle() {
+        mBitmapTexture.recycle();
+    }
+
+    @Override
+    public void draw(GLCanvas canvas, RectF source, RectF dest) {
+        canvas.drawTexture(mBitmapTexture, source, dest);
+    }
+}
diff --git a/src/com/android/camera/support/ui/OrientationSource.java b/src/com/android/camera/support/ui/OrientationSource.java
new file mode 100644
index 0000000..a2841ee
--- /dev/null
+++ b/src/com/android/camera/support/ui/OrientationSource.java
@@ -0,0 +1,6 @@
+package com.android.camera.support.ui;
+
+public interface OrientationSource {
+    public int getDisplayRotation();
+    public int getCompensation();
+}
diff --git a/src/com/android/camera/support/ui/ScreenNail.java b/src/com/android/camera/support/ui/ScreenNail.java
new file mode 100644
index 0000000..67b2f58
--- /dev/null
+++ b/src/com/android/camera/support/ui/ScreenNail.java
@@ -0,0 +1,21 @@
+package com.android.camera.support.ui;
+
+
+import android.graphics.RectF;
+
+import com.android.camera.support.glrenderer.GLCanvas;
+
+public interface ScreenNail {
+    public int getWidth();
+    public int getHeight();
+    public void draw(GLCanvas canvas, int x, int y, int width, int height);
+
+    // We do not need to draw this ScreenNail in this frame.
+    public void noDraw();
+
+    // This ScreenNail will not be used anymore. Release related resources.
+    public void recycle();
+
+    // This is only used by TileImageView to back up the tiles not yet loaded.
+    public void draw(GLCanvas canvas, RectF source, RectF dest);
+}
diff --git a/src/com/android/camera/support/ui/SurfaceTextureScreenNail.java b/src/com/android/camera/support/ui/SurfaceTextureScreenNail.java
new file mode 100644
index 0000000..d78b1ba
--- /dev/null
+++ b/src/com/android/camera/support/ui/SurfaceTextureScreenNail.java
@@ -0,0 +1,128 @@
+package com.android.camera.support.ui;
+
+
+import android.annotation.TargetApi;
+import android.graphics.RectF;
+import android.graphics.SurfaceTexture;
+
+import com.android.camera.support.common.ApiHelper;
+import com.android.camera.support.glrenderer.ExtTexture;
+import com.android.camera.support.glrenderer.GLCanvas;
+
+
+@TargetApi(ApiHelper.VERSION_CODES.HONEYCOMB)
+public abstract class SurfaceTextureScreenNail implements ScreenNail,
+        SurfaceTexture.OnFrameAvailableListener {
+    @SuppressWarnings("unused")
+    private static final String TAG = "SurfaceTextureScreenNail";
+    // This constant is not available in API level before 15, but it was just an
+    // oversight.
+    private static final int GL_TEXTURE_EXTERNAL_OES = 0x8D65;
+
+    protected ExtTexture mExtTexture;
+    private SurfaceTexture mSurfaceTexture;
+    private int mWidth, mHeight;
+    private float[] mTransform = new float[16];
+    private boolean mHasTexture = false;
+
+    public SurfaceTextureScreenNail() {
+    }
+
+    public void acquireSurfaceTexture(GLCanvas canvas) {
+        mExtTexture = new ExtTexture(canvas, GL_TEXTURE_EXTERNAL_OES);
+        mExtTexture.setSize(mWidth, mHeight);
+        mSurfaceTexture = new SurfaceTexture(mExtTexture.getId());
+        setDefaultBufferSize(mSurfaceTexture, mWidth, mHeight);
+        mSurfaceTexture.setOnFrameAvailableListener(this);
+        synchronized (this) {
+            mHasTexture = true;
+        }
+    }
+
+    @TargetApi(ApiHelper.VERSION_CODES.ICE_CREAM_SANDWICH_MR1)
+    private static void setDefaultBufferSize(SurfaceTexture st, int width, int height) {
+        if (ApiHelper.HAS_SET_DEFALT_BUFFER_SIZE) {
+            st.setDefaultBufferSize(width, height);
+        }
+    }
+
+    @TargetApi(ApiHelper.VERSION_CODES.ICE_CREAM_SANDWICH)
+    private static void releaseSurfaceTexture(SurfaceTexture st) {
+        st.setOnFrameAvailableListener(null);
+        if (ApiHelper.HAS_RELEASE_SURFACE_TEXTURE) {
+            st.release();
+        }
+    }
+
+    public SurfaceTexture getSurfaceTexture() {
+        return mSurfaceTexture;
+    }
+
+    public void releaseSurfaceTexture() {
+        synchronized (this) {
+            mHasTexture = false;
+        }
+        mExtTexture.recycle();
+        mExtTexture = null;
+        releaseSurfaceTexture(mSurfaceTexture);
+        mSurfaceTexture = null;
+    }
+
+    public void setSize(int width, int height) {
+        mWidth = width;
+        mHeight = height;
+    }
+
+    public void resizeTexture() {
+        if (mExtTexture != null) {
+            mExtTexture.setSize(mWidth, mHeight);
+            setDefaultBufferSize(mSurfaceTexture, mWidth, mHeight);
+        }
+    }
+
+    @Override
+    public int getWidth() {
+        return mWidth;
+    }
+
+    @Override
+    public int getHeight() {
+        return mHeight;
+    }
+
+    @Override
+    public void draw(GLCanvas canvas, int x, int y, int width, int height) {
+        synchronized (this) {
+            if (!mHasTexture) return;
+            mSurfaceTexture.updateTexImage();
+            mSurfaceTexture.getTransformMatrix(mTransform);
+
+            // Flip vertically.
+            canvas.save(GLCanvas.SAVE_FLAG_MATRIX);
+            int cx = x + width / 2;
+            int cy = y + height / 2;
+            canvas.translate(cx, cy);
+            canvas.scale(1, -1, 1);
+            canvas.translate(-cx, -cy);
+            updateTransformMatrix(mTransform);
+            canvas.drawTexture(mExtTexture, mTransform, x, y, width, height);
+            canvas.restore();
+        }
+    }
+
+    @Override
+    public void draw(GLCanvas canvas, RectF source, RectF dest) {
+        throw new UnsupportedOperationException();
+    }
+
+    protected void updateTransformMatrix(float[] matrix) {}
+
+    @Override
+    abstract public void noDraw();
+
+    @Override
+    abstract public void recycle();
+
+    @Override
+    abstract public void onFrameAvailable(SurfaceTexture surfaceTexture);
+}
\ No newline at end of file
diff --git a/src/com/android/camera/support/util/AccessibilityUtils.java b/src/com/android/camera/support/util/AccessibilityUtils.java
new file mode 100644
index 0000000..e758e2f
--- /dev/null
+++ b/src/com/android/camera/support/util/AccessibilityUtils.java
@@ -0,0 +1,38 @@
+package com.android.camera.support.util;
+
+import android.content.Context;
+import android.support.v4.view.accessibility.AccessibilityRecordCompat;
+import android.view.View;
+import android.view.accessibility.AccessibilityEvent;
+import android.view.accessibility.AccessibilityManager;
+
+import com.android.camera.support.common.ApiHelper;
+
+/**
+ * AccessibilityUtils provides functions needed in accessibility mode. All the functions
+ * in this class are made compatible with gingerbread and later API's
+*/
+public class AccessibilityUtils {
+    public static void makeAnnouncement(View view, CharSequence announcement) {
+        if (view == null)
+            return;
+        if (ApiHelper.HAS_ANNOUNCE_FOR_ACCESSIBILITY) {
+            view.announceForAccessibility(announcement);
+        } else {
+            // For API 15 and earlier, we need to construct an accessibility event
+            Context ctx = view.getContext();
+            AccessibilityManager am = (AccessibilityManager) ctx.getSystemService(
+                    Context.ACCESSIBILITY_SERVICE);
+            if (!am.isEnabled()) return;
+            AccessibilityEvent event = AccessibilityEvent.obtain(
+                    AccessibilityEvent.TYPE_NOTIFICATION_STATE_CHANGED);
+            AccessibilityRecordCompat arc = new AccessibilityRecordCompat(event);
+            arc.setSource(view);
+            event.setClassName(view.getClass().getName());
+            event.setPackageName(view.getContext().getPackageName());
+            event.setEnabled(view.isEnabled());
+            event.getText().add(announcement);
+            am.sendAccessibilityEvent(event);
+        }
+    }
+}
\ No newline at end of file
diff --git a/src/com/android/camera/support/util/MotionEventHelper.java b/src/com/android/camera/support/util/MotionEventHelper.java
new file mode 100644
index 0000000..2a3340e
--- /dev/null
+++ b/src/com/android/camera/support/util/MotionEventHelper.java
@@ -0,0 +1,105 @@
+package com.android.camera.support.util;
+
+import android.annotation.TargetApi;
+import android.graphics.Matrix;
+import android.util.FloatMath;
+import android.view.MotionEvent;
+import android.view.MotionEvent.PointerCoords;
+
+import com.android.gallery3d.common.ApiHelper;
+
+public final class MotionEventHelper {
+    private MotionEventHelper() {}
+
+    public static MotionEvent transformEvent(MotionEvent e, Matrix m) {
+        // We try to use the new transform method if possible because it uses
+        // less memory.
+        if (ApiHelper.HAS_MOTION_EVENT_TRANSFORM) {
+            return transformEventNew(e, m);
+        } else {
+            return transformEventOld(e, m);
+        }
+    }
+
+    @TargetApi(ApiHelper.VERSION_CODES.HONEYCOMB)
+    private static MotionEvent transformEventNew(MotionEvent e, Matrix m) {
+        MotionEvent newEvent = MotionEvent.obtain(e);
+        newEvent.transform(m);
+        return newEvent;
+    }
+
+    // This is copied from Input.cpp in the android framework.
+    private static MotionEvent transformEventOld(MotionEvent e, Matrix m) {
+        long downTime = e.getDownTime();
+        long eventTime = e.getEventTime();
+        int action = e.getAction();
+        int pointerCount = e.getPointerCount();
+        int[] pointerIds = getPointerIds(e);
+        PointerCoords[] pointerCoords = getPointerCoords(e);
+        int metaState = e.getMetaState();
+        float xPrecision = e.getXPrecision();
+        float yPrecision = e.getYPrecision();
+        int deviceId = e.getDeviceId();
+        int edgeFlags = e.getEdgeFlags();
+        int source = e.getSource();
+        int flags = e.getFlags();
+
+        // Copy the x and y coordinates into an array, map them, and copy back.
+        float[] xy = new float[pointerCoords.length * 2];
+        for (int i = 0; i < pointerCount;i++) {
+            xy[2 * i] = pointerCoords[i].x;
+            xy[2 * i + 1] = pointerCoords[i].y;
+        }
+        m.mapPoints(xy);
+        for (int i = 0; i < pointerCount;i++) {
+            pointerCoords[i].x = xy[2 * i];
+            pointerCoords[i].y = xy[2 * i + 1];
+            pointerCoords[i].orientation = transformAngle(
+                m, pointerCoords[i].orientation);
+        }
+
+        MotionEvent n = MotionEvent.obtain(downTime, eventTime, action,
+                pointerCount, pointerIds, pointerCoords, metaState, xPrecision,
+                yPrecision, deviceId, edgeFlags, source, flags);
+
+        return n;
+    }
+
+    private static int[] getPointerIds(MotionEvent e) {
+        int n = e.getPointerCount();
+        int[] r = new int[n];
+        for (int i = 0; i < n; i++) {
+            r[i] = e.getPointerId(i);
+        }
+        return r;
+    }
+
+    private static PointerCoords[] getPointerCoords(MotionEvent e) {
+        int n = e.getPointerCount();
+        PointerCoords[] r = new PointerCoords[n];
+        for (int i = 0; i < n; i++) {
+            r[i] = new PointerCoords();
+            e.getPointerCoords(i, r[i]);
+        }
+        return r;
+    }
+
+    private static float transformAngle(Matrix m, float angleRadians) {
+        // Construct and transform a vector oriented at the specified clockwise
+        // angle from vertical.  Coordinate system: down is increasing Y, right is
+        // increasing X.
+        float[] v = new float[2];
+        v[0] = FloatMath.sin(angleRadians);
+        v[1] = -FloatMath.cos(angleRadians);
+        m.mapVectors(v);
+
+        // Derive the transformed vector's clockwise angle from vertical.
+        float result = (float) Math.atan2(v[0], -v[1]);
+        if (result < -Math.PI / 2) {
+            result += Math.PI;
+        } else if (result > Math.PI / 2) {
+            result -= Math.PI;
+        }
+        return result;
+    }
+}
diff --git a/src/com/android/camera/ui/AbstractSettingPopup.java b/src/com/android/camera/ui/AbstractSettingPopup.java
index 783b6c7..a3cf298 100644
--- a/src/com/android/camera/ui/AbstractSettingPopup.java
+++ b/src/com/android/camera/ui/AbstractSettingPopup.java
@@ -21,7 +21,7 @@
 import android.view.ViewGroup;
 import android.widget.TextView;
 
-import com.android.gallery3d.R;
+import com.android.camera2.R;
 
 // A popup window that shows one or more camera settings.
 abstract public class AbstractSettingPopup extends RotateLayout {
diff --git a/src/com/android/camera/ui/CameraControls.java b/src/com/android/camera/ui/CameraControls.java
index 7fa6890..ed28139 100644
--- a/src/com/android/camera/ui/CameraControls.java
+++ b/src/com/android/camera/ui/CameraControls.java
@@ -16,17 +16,13 @@
 
 package com.android.camera.ui;
 
-import android.app.Activity;
 import android.content.Context;
-import android.content.res.Configuration;
 import android.graphics.Rect;
 import android.util.AttributeSet;
 import android.view.View;
 import android.widget.FrameLayout;
 
-import com.android.camera.Util;
-import com.android.gallery3d.R;
-import com.android.gallery3d.common.ApiHelper;
+import com.android.camera2.R;
 
 public class CameraControls extends RotatableLayout {
 
diff --git a/src/com/android/camera/ui/CameraRootView.java b/src/com/android/camera/ui/CameraRootView.java
index adda706..5186ea2 100644
--- a/src/com/android/camera/ui/CameraRootView.java
+++ b/src/com/android/camera/ui/CameraRootView.java
@@ -16,6 +16,7 @@
 
 package com.android.camera.ui;
 
+import android.annotation.SuppressLint;
 import android.app.Activity;
 import android.content.Context;
 import android.content.res.Configuration;
@@ -27,8 +28,9 @@
 import android.widget.FrameLayout;
 
 import com.android.camera.Util;
-import com.android.gallery3d.common.ApiHelper;
+import com.android.camera.support.common.ApiHelper;
 
+@SuppressLint("NewApi")
 public class CameraRootView extends FrameLayout {
 
     private int mTopMargin = 0;
diff --git a/src/com/android/camera/ui/CameraSwitcher.java b/src/com/android/camera/ui/CameraSwitcher.java
index 6e43215..f9e78f0 100644
--- a/src/com/android/camera/ui/CameraSwitcher.java
+++ b/src/com/android/camera/ui/CameraSwitcher.java
@@ -35,10 +35,10 @@
 import android.widget.LinearLayout;
 
 import com.android.camera.Util;
-import com.android.gallery3d.R;
+import com.android.camera.util.PhotoSphereHelper;
+import com.android.camera.util.UsageStatistics;
+import com.android.camera2.R;
 import com.android.gallery3d.common.ApiHelper;
-import com.android.gallery3d.util.LightCycleHelper;
-import com.android.gallery3d.util.UsageStatistics;
 
 public class CameraSwitcher extends RotateImageView
         implements OnClickListener, OnTouchListener {
@@ -96,14 +96,14 @@
     }
 
     public void initializeDrawables(Context context) {
-        int totaldrawid = (LightCycleHelper.hasLightCycleCapture(context)
+        int totaldrawid = (PhotoSphereHelper.hasLightCycleCapture(context)
                 ? DRAW_IDS.length : DRAW_IDS.length - 1);
 
         int[] drawids = new int[totaldrawid];
         int[] moduleids = new int[totaldrawid];
         int ix = 0;
         for (int i = 0; i < DRAW_IDS.length; i++) {
-            if (i == LIGHTCYCLE_MODULE_INDEX && !LightCycleHelper.hasLightCycleCapture(context)) {
+            if (i == LIGHTCYCLE_MODULE_INDEX && !PhotoSphereHelper.hasLightCycleCapture(context)) {
                 continue; // not enabled, so don't add to UI
             }
             moduleids[ix] = i;
diff --git a/src/com/android/camera/ui/CountDownView.java b/src/com/android/camera/ui/CountDownView.java
index 907d335..6f4ae8c 100644
--- a/src/com/android/camera/ui/CountDownView.java
+++ b/src/com/android/camera/ui/CountDownView.java
@@ -31,7 +31,7 @@
 import android.widget.FrameLayout;
 import android.widget.TextView;
 
-import com.android.gallery3d.R;
+import com.android.camera2.R;
 
 public class CountDownView extends FrameLayout {
 
diff --git a/src/com/android/camera/ui/CountdownTimerPopup.java b/src/com/android/camera/ui/CountdownTimerPopup.java
index 7c3572b..3f3a1ac 100644
--- a/src/com/android/camera/ui/CountdownTimerPopup.java
+++ b/src/com/android/camera/ui/CountdownTimerPopup.java
@@ -16,6 +16,8 @@
 
 package com.android.camera.ui;
 
+import java.util.Locale;
+
 import android.content.Context;
 import android.util.AttributeSet;
 import android.util.Log;
@@ -26,9 +28,7 @@
 import android.widget.NumberPicker.OnValueChangeListener;
 
 import com.android.camera.ListPreference;
-import com.android.gallery3d.R;
-
-import java.util.Locale;
+import com.android.camera2.R;
 
 /**
  * This is a popup window that allows users to specify a countdown timer
diff --git a/src/com/android/camera/ui/EffectSettingPopup.java b/src/com/android/camera/ui/EffectSettingPopup.java
index 568781a..d51803a 100644
--- a/src/com/android/camera/ui/EffectSettingPopup.java
+++ b/src/com/android/camera/ui/EffectSettingPopup.java
@@ -16,6 +16,9 @@
 
 package com.android.camera.ui;
 
+import java.util.ArrayList;
+import java.util.HashMap;
+
 import android.annotation.TargetApi;
 import android.content.Context;
 import android.util.AttributeSet;
@@ -26,13 +29,9 @@
 import android.widget.SimpleAdapter;
 
 import com.android.camera.IconListPreference;
-
-import com.android.gallery3d.R;
+import com.android.camera2.R;
 import com.android.gallery3d.common.ApiHelper;
 
-import java.util.ArrayList;
-import java.util.HashMap;
-
 // A popup window that shows video effect setting. It has two grid view.
 // One shows the goofy face effects. The other shows the background replacer
 // effects.
diff --git a/src/com/android/camera/ui/FaceView.java b/src/com/android/camera/ui/FaceView.java
index 7d66dc0..1a53966 100644
--- a/src/com/android/camera/ui/FaceView.java
+++ b/src/com/android/camera/ui/FaceView.java
@@ -33,7 +33,7 @@
 
 import com.android.camera.PhotoUI;
 import com.android.camera.Util;
-import com.android.gallery3d.R;
+import com.android.camera2.R;
 import com.android.gallery3d.common.ApiHelper;
 
 @TargetApi(ApiHelper.VERSION_CODES.ICE_CREAM_SANDWICH)
diff --git a/src/com/android/camera/ui/FilmStripView.java b/src/com/android/camera/ui/FilmStripView.java
index 8a1a85a..79f58c7 100644
--- a/src/com/android/camera/ui/FilmStripView.java
+++ b/src/com/android/camera/ui/FilmStripView.java
@@ -33,8 +33,8 @@
 import android.widget.Scroller;
 
 import com.android.camera.ui.FilmStripView.ImageData.PanoramaSupportCallback;
-import com.android.gallery3d.R;
-import com.android.gallery3d.util.LightCycleHelper.PanoramaViewHelper;
+import com.android.camera.util.PhotoSphereHelper.PanoramaViewHelper;
+import com.android.camera2.R;
 
 public class FilmStripView extends ViewGroup {
     @SuppressWarnings("unused")
diff --git a/src/com/android/camera/ui/InLineSettingCheckBox.java b/src/com/android/camera/ui/InLineSettingCheckBox.java
index c1aa5a9..c3cd197 100644
--- a/src/com/android/camera/ui/InLineSettingCheckBox.java
+++ b/src/com/android/camera/ui/InLineSettingCheckBox.java
@@ -23,9 +23,8 @@
 import android.widget.CompoundButton;
 import android.widget.CompoundButton.OnCheckedChangeListener;
 
-
 import com.android.camera.ListPreference;
-import com.android.gallery3d.R;
+import com.android.camera2.R;
 
 /* A check box setting control which turns on/off the setting. */
 public class InLineSettingCheckBox extends InLineSettingItem {
diff --git a/src/com/android/camera/ui/InLineSettingItem.java b/src/com/android/camera/ui/InLineSettingItem.java
index 839a77f..288781f 100644
--- a/src/com/android/camera/ui/InLineSettingItem.java
+++ b/src/com/android/camera/ui/InLineSettingItem.java
@@ -23,7 +23,7 @@
 import android.widget.TextView;
 
 import com.android.camera.ListPreference;
-import com.android.gallery3d.R;
+import com.android.camera2.R;
 
 /**
  * A one-line camera setting could be one of three types: knob, switch or restore
diff --git a/src/com/android/camera/ui/InLineSettingMenu.java b/src/com/android/camera/ui/InLineSettingMenu.java
index 8e45c3e..1d80741 100644
--- a/src/com/android/camera/ui/InLineSettingMenu.java
+++ b/src/com/android/camera/ui/InLineSettingMenu.java
@@ -23,7 +23,7 @@
 import android.widget.TextView;
 
 import com.android.camera.ListPreference;
-import com.android.gallery3d.R;
+import com.android.camera2.R;
 
 /* Setting menu item that will bring up a menu when you click on it. */
 public class InLineSettingMenu extends InLineSettingItem {
diff --git a/src/com/android/camera/ui/ListPrefSettingPopup.java b/src/com/android/camera/ui/ListPrefSettingPopup.java
index cfef73f..ff4d995 100644
--- a/src/com/android/camera/ui/ListPrefSettingPopup.java
+++ b/src/com/android/camera/ui/ListPrefSettingPopup.java
@@ -16,24 +16,24 @@
 
 package com.android.camera.ui;
 
-import android.content.Context;
-import android.util.AttributeSet;
-import android.util.Log;
-import android.view.View;
-import android.widget.ListView;
-import android.widget.AdapterView;
-import android.widget.ImageView;
-import android.widget.SimpleAdapter;
-
-import com.android.camera.IconListPreference;
-import com.android.camera.ListPreference;
-import com.android.gallery3d.R;
-
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 
+import android.content.Context;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.view.View;
+import android.widget.AdapterView;
+import android.widget.ImageView;
+import android.widget.ListView;
+import android.widget.SimpleAdapter;
+
+import com.android.camera.IconListPreference;
+import com.android.camera.ListPreference;
+import com.android.camera2.R;
+
 // A popup window that shows one camera setting. The title is the name of the
 // setting (ex: white-balance). The entries are the supported values (ex:
 // daylight, incandescent, etc). If initialized with an IconListPreference,
diff --git a/src/com/android/camera/ui/MoreSettingPopup.java b/src/com/android/camera/ui/MoreSettingPopup.java
index 5900058..8da26c9 100644
--- a/src/com/android/camera/ui/MoreSettingPopup.java
+++ b/src/com/android/camera/ui/MoreSettingPopup.java
@@ -16,6 +16,8 @@
 
 package com.android.camera.ui;
 
+import java.util.ArrayList;
+
 import android.content.Context;
 import android.util.AttributeSet;
 import android.util.Log;
@@ -28,9 +30,7 @@
 
 import com.android.camera.ListPreference;
 import com.android.camera.PreferenceGroup;
-import com.android.gallery3d.R;
-
-import java.util.ArrayList;
+import com.android.camera2.R;
 
 /* A popup window that contains several camera settings. */
 public class MoreSettingPopup extends AbstractSettingPopup
diff --git a/src/com/android/camera/ui/PieRenderer.java b/src/com/android/camera/ui/PieRenderer.java
index c78107c..666fa13 100644
--- a/src/com/android/camera/ui/PieRenderer.java
+++ b/src/com/android/camera/ui/PieRenderer.java
@@ -16,6 +16,9 @@
 
 package com.android.camera.ui;
 
+import java.util.ArrayList;
+import java.util.List;
+
 import android.animation.Animator;
 import android.animation.Animator.AnimatorListener;
 import android.animation.ValueAnimator;
@@ -37,10 +40,7 @@
 import android.view.animation.Transformation;
 
 import com.android.camera.drawable.TextDrawable;
-import com.android.gallery3d.R;
-
-import java.util.ArrayList;
-import java.util.List;
+import com.android.camera2.R;
 
 public class PieRenderer extends OverlayRenderer
         implements FocusIndicator {
diff --git a/src/com/android/camera/ui/RotateLayout.java b/src/com/android/camera/ui/RotateLayout.java
index 86f5c81..5d6debb 100644
--- a/src/com/android/camera/ui/RotateLayout.java
+++ b/src/com/android/camera/ui/RotateLayout.java
@@ -27,8 +27,8 @@
 import android.view.ViewGroup;
 import android.view.ViewParent;
 
+import com.android.camera.support.util.MotionEventHelper;
 import com.android.gallery3d.common.ApiHelper;
-import com.android.gallery3d.util.MotionEventHelper;
 
 // A RotateLayout is designed to display a single item and provides the
 // capabilities to rotate the item.
diff --git a/src/com/android/camera/ui/RotateTextToast.java b/src/com/android/camera/ui/RotateTextToast.java
index c78a258..1638244 100644
--- a/src/com/android/camera/ui/RotateTextToast.java
+++ b/src/com/android/camera/ui/RotateTextToast.java
@@ -24,7 +24,7 @@
 import android.widget.TextView;
 
 import com.android.camera.Util;
-import com.android.gallery3d.R;
+import com.android.camera2.R;
 
 public class RotateTextToast {
     private static final int TOAST_DURATION = 5000; // milliseconds
diff --git a/src/com/android/camera/ui/Switch.java b/src/com/android/camera/ui/Switch.java
index ac21758..9191242 100644
--- a/src/com/android/camera/ui/Switch.java
+++ b/src/com/android/camera/ui/Switch.java
@@ -20,11 +20,9 @@
 import android.content.Context;
 import android.content.res.ColorStateList;
 import android.content.res.Resources;
-import android.content.res.TypedArray;
 import android.graphics.Canvas;
 import android.graphics.Paint;
 import android.graphics.Rect;
-import android.graphics.Typeface;
 import android.graphics.drawable.Drawable;
 import android.text.Layout;
 import android.text.StaticLayout;
@@ -32,8 +30,6 @@
 import android.text.TextUtils;
 import android.util.AttributeSet;
 import android.util.DisplayMetrics;
-import android.util.Log;
-import android.util.TypedValue;
 import android.view.Gravity;
 import android.view.MotionEvent;
 import android.view.VelocityTracker;
@@ -42,11 +38,9 @@
 import android.view.accessibility.AccessibilityNodeInfo;
 import android.widget.CompoundButton;
 
-import com.android.gallery3d.R;
+import com.android.camera2.R;
 import com.android.gallery3d.common.ApiHelper;
 
-import java.util.Arrays;
-
 /**
  * A Switch is a two-state toggle switch widget that can select between two
  * options. The user may drag the "thumb" back and forth to choose the selected option,
diff --git a/src/com/android/camera/ui/TimeIntervalPopup.java b/src/com/android/camera/ui/TimeIntervalPopup.java
index 18ad9f5..f35f241 100644
--- a/src/com/android/camera/ui/TimeIntervalPopup.java
+++ b/src/com/android/camera/ui/TimeIntervalPopup.java
@@ -28,7 +28,7 @@
 
 import com.android.camera.IconListPreference;
 import com.android.camera.ListPreference;
-import com.android.gallery3d.R;
+import com.android.camera2.R;
 
 /**
  * This is a popup window that allows users to turn on/off time lapse feature,
diff --git a/src/com/android/camera/ui/ZoomRenderer.java b/src/com/android/camera/ui/ZoomRenderer.java
index 86b82b4..e708d3e 100644
--- a/src/com/android/camera/ui/ZoomRenderer.java
+++ b/src/com/android/camera/ui/ZoomRenderer.java
@@ -24,7 +24,7 @@
 import android.graphics.Rect;
 import android.view.ScaleGestureDetector;
 
-import com.android.gallery3d.R;
+import com.android.camera2.R;
 
 public class ZoomRenderer extends OverlayRenderer
         implements ScaleGestureDetector.OnScaleGestureListener {
diff --git a/src/com/android/gallery3d/anim/AlphaAnimation.java b/src/com/android/gallery3d/anim/AlphaAnimation.java
deleted file mode 100644
index f9f4cbd..0000000
--- a/src/com/android/gallery3d/anim/AlphaAnimation.java
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Copyright (C) 2010 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.gallery3d.anim;
-
-import com.android.gallery3d.common.Utils;
-import com.android.gallery3d.glrenderer.GLCanvas;
-
-public class AlphaAnimation extends CanvasAnimation {
-    private final float mStartAlpha;
-    private final float mEndAlpha;
-    private float mCurrentAlpha;
-
-    public AlphaAnimation(float from, float to) {
-        mStartAlpha = from;
-        mEndAlpha = to;
-        mCurrentAlpha = from;
-    }
-
-    @Override
-    public void apply(GLCanvas canvas) {
-        canvas.multiplyAlpha(mCurrentAlpha);
-    }
-
-    @Override
-    public int getCanvasSaveFlags() {
-        return GLCanvas.SAVE_FLAG_ALPHA;
-    }
-
-    @Override
-    protected void onCalculate(float progress) {
-        mCurrentAlpha = Utils.clamp(mStartAlpha
-                + (mEndAlpha - mStartAlpha) * progress, 0f, 1f);
-    }
-}
diff --git a/src/com/android/gallery3d/anim/Animation.java b/src/com/android/gallery3d/anim/Animation.java
deleted file mode 100644
index cc117bb..0000000
--- a/src/com/android/gallery3d/anim/Animation.java
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- * Copyright (C) 2010 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.gallery3d.anim;
-
-import android.view.animation.Interpolator;
-
-import com.android.gallery3d.common.Utils;
-
-// Animation calculates a value according to the current input time.
-//
-// 1. First we need to use setDuration(int) to set the duration of the
-//    animation. The duration is in milliseconds.
-// 2. Then we should call start(). The actual start time is the first value
-//    passed to calculate(long).
-// 3. Each time we want to get an animation value, we call
-//    calculate(long currentTimeMillis) to ask the Animation to calculate it.
-//    The parameter passed to calculate(long) should be nonnegative.
-// 4. Use get() to get that value.
-//
-// In step 3, onCalculate(float progress) is called so subclasses can calculate
-// the value according to progress (progress is a value in [0,1]).
-//
-// Before onCalculate(float) is called, There is an optional interpolator which
-// can change the progress value. The interpolator can be set by
-// setInterpolator(Interpolator). If the interpolator is used, the value passed
-// to onCalculate may be (for example, the overshoot effect).
-//
-// The isActive() method returns true after the animation start() is called and
-// before calculate is passed a value which reaches the duration of the
-// animation.
-//
-// The start() method can be called again to restart the Animation.
-//
-abstract public class Animation {
-    private static final long ANIMATION_START = -1;
-    private static final long NO_ANIMATION = -2;
-
-    private long mStartTime = NO_ANIMATION;
-    private int mDuration;
-    private Interpolator mInterpolator;
-
-    public void setInterpolator(Interpolator interpolator) {
-        mInterpolator = interpolator;
-    }
-
-    public void setDuration(int duration) {
-        mDuration = duration;
-    }
-
-    public void start() {
-        mStartTime = ANIMATION_START;
-    }
-
-    public void setStartTime(long time) {
-        mStartTime = time;
-    }
-
-    public boolean isActive() {
-        return mStartTime != NO_ANIMATION;
-    }
-
-    public void forceStop() {
-        mStartTime = NO_ANIMATION;
-    }
-
-    public boolean calculate(long currentTimeMillis) {
-        if (mStartTime == NO_ANIMATION) return false;
-        if (mStartTime == ANIMATION_START) mStartTime = currentTimeMillis;
-        int elapse = (int) (currentTimeMillis - mStartTime);
-        float x = Utils.clamp((float) elapse / mDuration, 0f, 1f);
-        Interpolator i = mInterpolator;
-        onCalculate(i != null ? i.getInterpolation(x) : x);
-        if (elapse >= mDuration) mStartTime = NO_ANIMATION;
-        return mStartTime != NO_ANIMATION;
-    }
-
-    abstract protected void onCalculate(float progress);
-}
diff --git a/src/com/android/gallery3d/anim/CanvasAnimation.java b/src/com/android/gallery3d/anim/CanvasAnimation.java
deleted file mode 100644
index cdc66c6..0000000
--- a/src/com/android/gallery3d/anim/CanvasAnimation.java
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * Copyright (C) 2010 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.gallery3d.anim;
-
-import com.android.gallery3d.glrenderer.GLCanvas;
-
-public abstract class CanvasAnimation extends Animation {
-
-    public abstract int getCanvasSaveFlags();
-    public abstract void apply(GLCanvas canvas);
-}
diff --git a/src/com/android/gallery3d/anim/FloatAnimation.java b/src/com/android/gallery3d/anim/FloatAnimation.java
deleted file mode 100644
index 1294ec2..0000000
--- a/src/com/android/gallery3d/anim/FloatAnimation.java
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright (C) 2010 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.gallery3d.anim;
-
-public class FloatAnimation extends Animation {
-
-    private final float mFrom;
-    private final float mTo;
-    private float mCurrent;
-
-    public FloatAnimation(float from, float to, int duration) {
-        mFrom = from;
-        mTo = to;
-        mCurrent = from;
-        setDuration(duration);
-    }
-
-    @Override
-    protected void onCalculate(float progress) {
-        mCurrent = mFrom + (mTo - mFrom) * progress;
-    }
-
-    public float get() {
-        return mCurrent;
-    }
-}
diff --git a/src/com/android/gallery3d/anim/StateTransitionAnimation.java b/src/com/android/gallery3d/anim/StateTransitionAnimation.java
deleted file mode 100644
index bf8a544..0000000
--- a/src/com/android/gallery3d/anim/StateTransitionAnimation.java
+++ /dev/null
@@ -1,180 +0,0 @@
-/*
- * 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.gallery3d.anim;
-
-import android.view.animation.AccelerateInterpolator;
-import android.view.animation.DecelerateInterpolator;
-import android.view.animation.Interpolator;
-
-import com.android.gallery3d.glrenderer.GLCanvas;
-import com.android.gallery3d.glrenderer.RawTexture;
-import com.android.gallery3d.ui.GLView;
-import com.android.gallery3d.ui.TiledScreenNail;
-
-public class StateTransitionAnimation extends Animation {
-
-    public static class Spec {
-        public static final Spec OUTGOING;
-        public static final Spec INCOMING;
-        public static final Spec PHOTO_INCOMING;
-
-        private static final Interpolator DEFAULT_INTERPOLATOR =
-                new DecelerateInterpolator();
-
-        public int duration = 330;
-        public float backgroundAlphaFrom = 0;
-        public float backgroundAlphaTo = 0;
-        public float backgroundScaleFrom = 0;
-        public float backgroundScaleTo = 0;
-        public float contentAlphaFrom = 1;
-        public float contentAlphaTo = 1;
-        public float contentScaleFrom = 1;
-        public float contentScaleTo = 1;
-        public float overlayAlphaFrom = 0;
-        public float overlayAlphaTo = 0;
-        public float overlayScaleFrom = 0;
-        public float overlayScaleTo = 0;
-        public Interpolator interpolator = DEFAULT_INTERPOLATOR;
-
-        static {
-            OUTGOING = new Spec();
-            OUTGOING.backgroundAlphaFrom = 0.5f;
-            OUTGOING.backgroundAlphaTo = 0f;
-            OUTGOING.backgroundScaleFrom = 1f;
-            OUTGOING.backgroundScaleTo = 0f;
-            OUTGOING.contentAlphaFrom = 0.5f;
-            OUTGOING.contentAlphaTo = 1f;
-            OUTGOING.contentScaleFrom = 3f;
-            OUTGOING.contentScaleTo = 1f;
-
-            INCOMING = new Spec();
-            INCOMING.overlayAlphaFrom = 1f;
-            INCOMING.overlayAlphaTo = 0f;
-            INCOMING.overlayScaleFrom = 1f;
-            INCOMING.overlayScaleTo = 3f;
-            INCOMING.contentAlphaFrom = 0f;
-            INCOMING.contentAlphaTo = 1f;
-            INCOMING.contentScaleFrom = 0.25f;
-            INCOMING.contentScaleTo = 1f;
-
-            PHOTO_INCOMING = INCOMING;
-        }
-
-        private static Spec specForTransition(Transition t) {
-            switch (t) {
-                case Outgoing:
-                    return Spec.OUTGOING;
-                case Incoming:
-                    return Spec.INCOMING;
-                case PhotoIncoming:
-                    return Spec.PHOTO_INCOMING;
-                case None:
-                default:
-                    return null;
-            }
-        }
-    }
-
-    public static enum Transition { None, Outgoing, Incoming, PhotoIncoming }
-
-    private final Spec mTransitionSpec;
-    private float mCurrentContentScale;
-    private float mCurrentContentAlpha;
-    private float mCurrentBackgroundScale;
-    private float mCurrentBackgroundAlpha;
-    private float mCurrentOverlayScale;
-    private float mCurrentOverlayAlpha;
-    private RawTexture mOldScreenTexture;
-
-    public StateTransitionAnimation(Transition t, RawTexture oldScreen) {
-        this(Spec.specForTransition(t), oldScreen);
-    }
-
-    public StateTransitionAnimation(Spec spec, RawTexture oldScreen) {
-        mTransitionSpec = spec != null ? spec : Spec.OUTGOING;
-        setDuration(mTransitionSpec.duration);
-        setInterpolator(mTransitionSpec.interpolator);
-        mOldScreenTexture = oldScreen;
-        TiledScreenNail.disableDrawPlaceholder();
-    }
-
-    @Override
-    public boolean calculate(long currentTimeMillis) {
-        boolean retval = super.calculate(currentTimeMillis);
-        if (!isActive()) {
-            if (mOldScreenTexture != null) {
-                mOldScreenTexture.recycle();
-                mOldScreenTexture = null;
-            }
-            TiledScreenNail.enableDrawPlaceholder();
-        }
-        return retval;
-    }
-
-    @Override
-    protected void onCalculate(float progress) {
-        mCurrentContentScale = mTransitionSpec.contentScaleFrom
-                + (mTransitionSpec.contentScaleTo - mTransitionSpec.contentScaleFrom) * progress;
-        mCurrentContentAlpha = mTransitionSpec.contentAlphaFrom
-                + (mTransitionSpec.contentAlphaTo - mTransitionSpec.contentAlphaFrom) * progress;
-        mCurrentBackgroundAlpha = mTransitionSpec.backgroundAlphaFrom
-                + (mTransitionSpec.backgroundAlphaTo - mTransitionSpec.backgroundAlphaFrom)
-                * progress;
-        mCurrentBackgroundScale = mTransitionSpec.backgroundScaleFrom
-                + (mTransitionSpec.backgroundScaleTo - mTransitionSpec.backgroundScaleFrom)
-                * progress;
-        mCurrentOverlayScale = mTransitionSpec.overlayScaleFrom
-                + (mTransitionSpec.overlayScaleTo - mTransitionSpec.overlayScaleFrom) * progress;
-        mCurrentOverlayAlpha = mTransitionSpec.overlayAlphaFrom
-                + (mTransitionSpec.overlayAlphaTo - mTransitionSpec.overlayAlphaFrom) * progress;
-    }
-
-    private void applyOldTexture(GLView view, GLCanvas canvas, float alpha, float scale, boolean clear) {
-        if (mOldScreenTexture == null)
-            return;
-        if (clear) canvas.clearBuffer(view.getBackgroundColor());
-        canvas.save();
-        canvas.setAlpha(alpha);
-        int xOffset = view.getWidth() / 2;
-        int yOffset = view.getHeight() / 2;
-        canvas.translate(xOffset, yOffset);
-        canvas.scale(scale, scale, 1);
-        mOldScreenTexture.draw(canvas, -xOffset, -yOffset);
-        canvas.restore();
-    }
-
-    public void applyBackground(GLView view, GLCanvas canvas) {
-        if (mCurrentBackgroundAlpha > 0f) {
-            applyOldTexture(view, canvas, mCurrentBackgroundAlpha, mCurrentBackgroundScale, true);
-        }
-    }
-
-    public void applyContentTransform(GLView view, GLCanvas canvas) {
-        int xOffset = view.getWidth() / 2;
-        int yOffset = view.getHeight() / 2;
-        canvas.translate(xOffset, yOffset);
-        canvas.scale(mCurrentContentScale, mCurrentContentScale, 1);
-        canvas.translate(-xOffset, -yOffset);
-        canvas.setAlpha(mCurrentContentAlpha);
-    }
-
-    public void applyOverlay(GLView view, GLCanvas canvas) {
-        if (mCurrentOverlayAlpha > 0f) {
-            applyOldTexture(view, canvas, mCurrentOverlayAlpha, mCurrentOverlayScale, false);
-        }
-    }
-}
diff --git a/src/com/android/gallery3d/app/AbstractGalleryActivity.java b/src/com/android/gallery3d/app/AbstractGalleryActivity.java
deleted file mode 100644
index ac39aa5..0000000
--- a/src/com/android/gallery3d/app/AbstractGalleryActivity.java
+++ /dev/null
@@ -1,343 +0,0 @@
-/*
- * Copyright (C) 2010 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.gallery3d.app;
-
-import android.annotation.TargetApi;
-import android.app.Activity;
-import android.app.AlertDialog;
-import android.content.BroadcastReceiver;
-import android.content.ComponentName;
-import android.content.Context;
-import android.content.DialogInterface;
-import android.content.DialogInterface.OnCancelListener;
-import android.content.DialogInterface.OnClickListener;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.content.ServiceConnection;
-import android.content.res.Configuration;
-import android.os.Bundle;
-import android.os.IBinder;
-import android.view.Menu;
-import android.view.MenuItem;
-import android.view.Window;
-import android.view.WindowManager;
-
-import com.android.gallery3d.R;
-import com.android.gallery3d.common.ApiHelper;
-import com.android.gallery3d.data.DataManager;
-import com.android.gallery3d.data.MediaItem;
-import com.android.gallery3d.ui.GLRoot;
-import com.android.gallery3d.ui.GLRootView;
-import com.android.gallery3d.util.LightCycleHelper.PanoramaViewHelper;
-import com.android.gallery3d.util.ThreadPool;
-import com.android.photos.data.GalleryBitmapPool;
-
-public class AbstractGalleryActivity extends Activity implements GalleryContext {
-    @SuppressWarnings("unused")
-    private static final String TAG = "AbstractGalleryActivity";
-    private GLRootView mGLRootView;
-    private StateManager mStateManager;
-    private GalleryActionBar mActionBar;
-    private OrientationManager mOrientationManager;
-    private TransitionStore mTransitionStore = new TransitionStore();
-    private boolean mDisableToggleStatusBar;
-    private PanoramaViewHelper mPanoramaViewHelper;
-
-    private AlertDialog mAlertDialog = null;
-    private BroadcastReceiver mMountReceiver = new BroadcastReceiver() {
-        @Override
-        public void onReceive(Context context, Intent intent) {
-            if (getExternalCacheDir() != null) onStorageReady();
-        }
-    };
-    private IntentFilter mMountFilter = new IntentFilter(Intent.ACTION_MEDIA_MOUNTED);
-
-    @Override
-    protected void onCreate(Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-        mOrientationManager = new OrientationManager(this);
-        toggleStatusBarByOrientation();
-        getWindow().setBackgroundDrawable(null);
-        mPanoramaViewHelper = new PanoramaViewHelper(this);
-        mPanoramaViewHelper.onCreate();
-        doBindBatchService();
-    }
-
-    @Override
-    protected void onSaveInstanceState(Bundle outState) {
-        mGLRootView.lockRenderThread();
-        try {
-            super.onSaveInstanceState(outState);
-            getStateManager().saveState(outState);
-        } finally {
-            mGLRootView.unlockRenderThread();
-        }
-    }
-
-    @Override
-    public void onConfigurationChanged(Configuration config) {
-        super.onConfigurationChanged(config);
-        mStateManager.onConfigurationChange(config);
-        getGalleryActionBar().onConfigurationChanged();
-        invalidateOptionsMenu();
-        toggleStatusBarByOrientation();
-    }
-
-    @Override
-    public boolean onCreateOptionsMenu(Menu menu) {
-        super.onCreateOptionsMenu(menu);
-        return getStateManager().createOptionsMenu(menu);
-    }
-
-    @Override
-    public Context getAndroidContext() {
-        return this;
-    }
-
-    @Override
-    public DataManager getDataManager() {
-        return ((GalleryApp) getApplication()).getDataManager();
-    }
-
-    @Override
-    public ThreadPool getThreadPool() {
-        return ((GalleryApp) getApplication()).getThreadPool();
-    }
-
-    public synchronized StateManager getStateManager() {
-        if (mStateManager == null) {
-            mStateManager = new StateManager(this);
-        }
-        return mStateManager;
-    }
-
-    public GLRoot getGLRoot() {
-        return mGLRootView;
-    }
-
-    public OrientationManager getOrientationManager() {
-        return mOrientationManager;
-    }
-
-    @Override
-    public void setContentView(int resId) {
-        super.setContentView(resId);
-        mGLRootView = (GLRootView) findViewById(R.id.gl_root_view);
-    }
-
-    protected void onStorageReady() {
-        if (mAlertDialog != null) {
-            mAlertDialog.dismiss();
-            mAlertDialog = null;
-            unregisterReceiver(mMountReceiver);
-        }
-    }
-
-    @Override
-    protected void onStart() {
-        super.onStart();
-        if (getExternalCacheDir() == null) {
-            OnCancelListener onCancel = new OnCancelListener() {
-                @Override
-                public void onCancel(DialogInterface dialog) {
-                    finish();
-                }
-            };
-            OnClickListener onClick = new OnClickListener() {
-                @Override
-                public void onClick(DialogInterface dialog, int which) {
-                    dialog.cancel();
-                }
-            };
-            AlertDialog.Builder builder = new AlertDialog.Builder(this)
-                    .setTitle(R.string.no_external_storage_title)
-                    .setMessage(R.string.no_external_storage)
-                    .setNegativeButton(android.R.string.cancel, onClick)
-                    .setOnCancelListener(onCancel);
-            if (ApiHelper.HAS_SET_ICON_ATTRIBUTE) {
-                setAlertDialogIconAttribute(builder);
-            } else {
-                builder.setIcon(android.R.drawable.ic_dialog_alert);
-            }
-            mAlertDialog = builder.show();
-            registerReceiver(mMountReceiver, mMountFilter);
-        }
-        mPanoramaViewHelper.onStart();
-    }
-
-    @TargetApi(ApiHelper.VERSION_CODES.HONEYCOMB)
-    private static void setAlertDialogIconAttribute(
-            AlertDialog.Builder builder) {
-        builder.setIconAttribute(android.R.attr.alertDialogIcon);
-    }
-
-    @Override
-    protected void onStop() {
-        super.onStop();
-        if (mAlertDialog != null) {
-            unregisterReceiver(mMountReceiver);
-            mAlertDialog.dismiss();
-            mAlertDialog = null;
-        }
-        mPanoramaViewHelper.onStop();
-    }
-
-    @Override
-    protected void onResume() {
-        super.onResume();
-        mGLRootView.lockRenderThread();
-        try {
-            getStateManager().resume();
-            getDataManager().resume();
-        } finally {
-            mGLRootView.unlockRenderThread();
-        }
-        mGLRootView.onResume();
-        mOrientationManager.resume();
-    }
-
-    @Override
-    protected void onPause() {
-        super.onPause();
-        mOrientationManager.pause();
-        mGLRootView.onPause();
-        mGLRootView.lockRenderThread();
-        try {
-            getStateManager().pause();
-            getDataManager().pause();
-        } finally {
-            mGLRootView.unlockRenderThread();
-        }
-        GalleryBitmapPool.getInstance().clear();
-        MediaItem.getBytesBufferPool().clear();
-    }
-
-    @Override
-    protected void onDestroy() {
-        super.onDestroy();
-        mGLRootView.lockRenderThread();
-        try {
-            getStateManager().destroy();
-        } finally {
-            mGLRootView.unlockRenderThread();
-        }
-        doUnbindBatchService();
-    }
-
-    @Override
-    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
-        mGLRootView.lockRenderThread();
-        try {
-            getStateManager().notifyActivityResult(
-                    requestCode, resultCode, data);
-        } finally {
-            mGLRootView.unlockRenderThread();
-        }
-    }
-
-    @Override
-    public void onBackPressed() {
-        // send the back event to the top sub-state
-        GLRoot root = getGLRoot();
-        root.lockRenderThread();
-        try {
-            getStateManager().onBackPressed();
-        } finally {
-            root.unlockRenderThread();
-        }
-    }
-
-    public GalleryActionBar getGalleryActionBar() {
-        if (mActionBar == null) {
-            mActionBar = new GalleryActionBar(this);
-        }
-        return mActionBar;
-    }
-
-    @Override
-    public boolean onOptionsItemSelected(MenuItem item) {
-        GLRoot root = getGLRoot();
-        root.lockRenderThread();
-        try {
-            return getStateManager().itemSelected(item);
-        } finally {
-            root.unlockRenderThread();
-        }
-    }
-
-    protected void disableToggleStatusBar() {
-        mDisableToggleStatusBar = true;
-    }
-
-    // Shows status bar in portrait view, hide in landscape view
-    private void toggleStatusBarByOrientation() {
-        if (mDisableToggleStatusBar) return;
-
-        Window win = getWindow();
-        if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) {
-            win.clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
-        } else {
-            win.addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
-        }
-    }
-
-    public TransitionStore getTransitionStore() {
-        return mTransitionStore;
-    }
-
-    public PanoramaViewHelper getPanoramaViewHelper() {
-        return mPanoramaViewHelper;
-    }
-
-    protected boolean isFullscreen() {
-        return (getWindow().getAttributes().flags
-                & WindowManager.LayoutParams.FLAG_FULLSCREEN) != 0;
-    }
-
-    private BatchService mBatchService;
-    private boolean mBatchServiceIsBound = false;
-    private ServiceConnection mBatchServiceConnection = new ServiceConnection() {
-        public void onServiceConnected(ComponentName className, IBinder service) {
-            mBatchService = ((BatchService.LocalBinder)service).getService();
-        }
-
-        public void onServiceDisconnected(ComponentName className) {
-            mBatchService = null;
-        }
-    };
-
-    private void doBindBatchService() {
-        bindService(new Intent(this, BatchService.class), mBatchServiceConnection, Context.BIND_AUTO_CREATE);
-        mBatchServiceIsBound = true;
-    }
-
-    private void doUnbindBatchService() {
-        if (mBatchServiceIsBound) {
-            // Detach our existing connection.
-            unbindService(mBatchServiceConnection);
-            mBatchServiceIsBound = false;
-        }
-    }
-
-    public ThreadPool getBatchServiceThreadPoolIfAvailable() {
-        if (mBatchServiceIsBound && mBatchService != null) {
-            return mBatchService.getThreadPool();
-        } else {
-            throw new RuntimeException("Batch service unavailable");
-        }
-    }
-}
diff --git a/src/com/android/gallery3d/app/ActivityState.java b/src/com/android/gallery3d/app/ActivityState.java
deleted file mode 100644
index 2f1e0c9..0000000
--- a/src/com/android/gallery3d/app/ActivityState.java
+++ /dev/null
@@ -1,276 +0,0 @@
-/*
- * Copyright (C) 2010 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.gallery3d.app;
-
-import android.app.ActionBar;
-import android.app.Activity;
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.content.res.Configuration;
-import android.os.BatteryManager;
-import android.os.Bundle;
-import android.view.HapticFeedbackConstants;
-import android.view.Menu;
-import android.view.MenuInflater;
-import android.view.MenuItem;
-import android.view.Window;
-import android.view.WindowManager;
-
-import com.android.gallery3d.R;
-import com.android.gallery3d.anim.StateTransitionAnimation;
-import com.android.gallery3d.glrenderer.RawTexture;
-import com.android.gallery3d.ui.GLView;
-import com.android.gallery3d.ui.PreparePageFadeoutTexture;
-import com.android.gallery3d.util.GalleryUtils;
-
-abstract public class ActivityState {
-    protected static final int FLAG_HIDE_ACTION_BAR = 1;
-    protected static final int FLAG_HIDE_STATUS_BAR = 2;
-    protected static final int FLAG_SCREEN_ON_WHEN_PLUGGED = 4;
-    protected static final int FLAG_SCREEN_ON_ALWAYS = 8;
-    protected static final int FLAG_ALLOW_LOCK_WHILE_SCREEN_ON = 16;
-    protected static final int FLAG_SHOW_WHEN_LOCKED = 32;
-
-    protected AbstractGalleryActivity mActivity;
-    protected Bundle mData;
-    protected int mFlags;
-
-    protected ResultEntry mReceivedResults;
-    protected ResultEntry mResult;
-
-    protected static class ResultEntry {
-        public int requestCode;
-        public int resultCode = Activity.RESULT_CANCELED;
-        public Intent resultData;
-    }
-
-    private boolean mDestroyed = false;
-    private boolean mPlugged = false;
-    boolean mIsFinishing = false;
-
-    private static final String KEY_TRANSITION_IN = "transition-in";
-
-    private StateTransitionAnimation.Transition mNextTransition =
-            StateTransitionAnimation.Transition.None;
-    private StateTransitionAnimation mIntroAnimation;
-    private GLView mContentPane;
-
-    protected ActivityState() {
-    }
-
-    protected void setContentPane(GLView content) {
-        mContentPane = content;
-        if (mIntroAnimation != null) {
-            mContentPane.setIntroAnimation(mIntroAnimation);
-            mIntroAnimation = null;
-        }
-        mContentPane.setBackgroundColor(getBackgroundColor());
-        mActivity.getGLRoot().setContentPane(mContentPane);
-    }
-
-    void initialize(AbstractGalleryActivity activity, Bundle data) {
-        mActivity = activity;
-        mData = data;
-    }
-
-    public Bundle getData() {
-        return mData;
-    }
-
-    protected void onBackPressed() {
-        mActivity.getStateManager().finishState(this);
-    }
-
-    protected void setStateResult(int resultCode, Intent data) {
-        if (mResult == null) return;
-        mResult.resultCode = resultCode;
-        mResult.resultData = data;
-    }
-
-    protected void onConfigurationChanged(Configuration config) {
-    }
-
-    protected void onSaveState(Bundle outState) {
-    }
-
-    protected void onStateResult(int requestCode, int resultCode, Intent data) {
-    }
-
-    protected float[] mBackgroundColor;
-
-    protected int getBackgroundColorId() {
-        return R.color.default_background;
-    }
-
-    protected float[] getBackgroundColor() {
-        return mBackgroundColor;
-    }
-
-    protected void onCreate(Bundle data, Bundle storedState) {
-        mBackgroundColor = GalleryUtils.intColorToFloatARGBArray(
-                mActivity.getResources().getColor(getBackgroundColorId()));
-    }
-
-    protected void clearStateResult() {
-    }
-
-    BroadcastReceiver mPowerIntentReceiver = new BroadcastReceiver() {
-        @Override
-        public void onReceive(Context context, Intent intent) {
-            final String action = intent.getAction();
-            if (Intent.ACTION_BATTERY_CHANGED.equals(action)) {
-                boolean plugged = (0 != intent.getIntExtra(BatteryManager.EXTRA_PLUGGED, 0));
-
-                if (plugged != mPlugged) {
-                    mPlugged = plugged;
-                    setScreenFlags();
-                }
-            }
-        }
-    };
-
-    private void setScreenFlags() {
-        final Window win = mActivity.getWindow();
-        final WindowManager.LayoutParams params = win.getAttributes();
-        if ((0 != (mFlags & FLAG_SCREEN_ON_ALWAYS)) ||
-                (mPlugged && 0 != (mFlags & FLAG_SCREEN_ON_WHEN_PLUGGED))) {
-            params.flags |= WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON;
-        } else {
-            params.flags &= ~WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON;
-        }
-        if (0 != (mFlags & FLAG_ALLOW_LOCK_WHILE_SCREEN_ON)) {
-            params.flags |= WindowManager.LayoutParams.FLAG_ALLOW_LOCK_WHILE_SCREEN_ON;
-        } else {
-            params.flags &= ~WindowManager.LayoutParams.FLAG_ALLOW_LOCK_WHILE_SCREEN_ON;
-        }
-        if (0 != (mFlags & FLAG_SHOW_WHEN_LOCKED)) {
-            params.flags |= WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED;
-        } else {
-            params.flags &= ~WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED;
-        }
-        win.setAttributes(params);
-    }
-
-    protected void transitionOnNextPause(Class<? extends ActivityState> outgoing,
-            Class<? extends ActivityState> incoming, StateTransitionAnimation.Transition hint) {
-        if (outgoing == SinglePhotoPage.class && incoming == AlbumPage.class) {
-            mNextTransition = StateTransitionAnimation.Transition.Outgoing;
-        } else if (outgoing == AlbumPage.class && incoming == SinglePhotoPage.class) {
-            mNextTransition = StateTransitionAnimation.Transition.PhotoIncoming;
-        } else {
-            mNextTransition = hint;
-        }
-    }
-
-    protected void performHapticFeedback(int feedbackConstant) {
-        mActivity.getWindow().getDecorView().performHapticFeedback(feedbackConstant,
-                HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING);
-    }
-
-    protected void onPause() {
-        if (0 != (mFlags & FLAG_SCREEN_ON_WHEN_PLUGGED)) {
-            ((Activity) mActivity).unregisterReceiver(mPowerIntentReceiver);
-        }
-        if (mNextTransition != StateTransitionAnimation.Transition.None) {
-            mActivity.getTransitionStore().put(KEY_TRANSITION_IN, mNextTransition);
-            PreparePageFadeoutTexture.prepareFadeOutTexture(mActivity, mContentPane);
-            mNextTransition = StateTransitionAnimation.Transition.None;
-        }
-    }
-
-    // should only be called by StateManager
-    void resume() {
-        AbstractGalleryActivity activity = mActivity;
-        ActionBar actionBar = activity.getActionBar();
-        if (actionBar != null) {
-            if ((mFlags & FLAG_HIDE_ACTION_BAR) != 0) {
-                actionBar.hide();
-            } else {
-                actionBar.show();
-            }
-            int stateCount = mActivity.getStateManager().getStateCount();
-            mActivity.getGalleryActionBar().setDisplayOptions(stateCount > 1, true);
-            // Default behavior, this can be overridden in ActivityState's onResume.
-            actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_STANDARD);
-        }
-
-        activity.invalidateOptionsMenu();
-
-        setScreenFlags();
-
-        boolean lightsOut = ((mFlags & FLAG_HIDE_STATUS_BAR) != 0);
-        mActivity.getGLRoot().setLightsOutMode(lightsOut);
-
-        ResultEntry entry = mReceivedResults;
-        if (entry != null) {
-            mReceivedResults = null;
-            onStateResult(entry.requestCode, entry.resultCode, entry.resultData);
-        }
-
-        if (0 != (mFlags & FLAG_SCREEN_ON_WHEN_PLUGGED)) {
-            // we need to know whether the device is plugged in to do this correctly
-            final IntentFilter filter = new IntentFilter();
-            filter.addAction(Intent.ACTION_BATTERY_CHANGED);
-            activity.registerReceiver(mPowerIntentReceiver, filter);
-        }
-
-        onResume();
-
-        // the transition store should be cleared after resume;
-        mActivity.getTransitionStore().clear();
-    }
-
-    // a subclass of ActivityState should override the method to resume itself
-    protected void onResume() {
-        RawTexture fade = mActivity.getTransitionStore().get(
-                PreparePageFadeoutTexture.KEY_FADE_TEXTURE);
-        mNextTransition = mActivity.getTransitionStore().get(
-                KEY_TRANSITION_IN, StateTransitionAnimation.Transition.None);
-        if (mNextTransition != StateTransitionAnimation.Transition.None) {
-            mIntroAnimation = new StateTransitionAnimation(mNextTransition, fade);
-            mNextTransition = StateTransitionAnimation.Transition.None;
-        }
-    }
-
-    protected boolean onCreateActionBar(Menu menu) {
-        // TODO: we should return false if there is no menu to show
-        //       this is a workaround for a bug in system
-        return true;
-    }
-
-    protected boolean onItemSelected(MenuItem item) {
-        return false;
-    }
-
-    protected void onDestroy() {
-        mDestroyed = true;
-    }
-
-    boolean isDestroyed() {
-        return mDestroyed;
-    }
-
-    public boolean isFinishing() {
-        return mIsFinishing;
-    }
-
-    protected MenuInflater getSupportMenuInflater() {
-        return mActivity.getMenuInflater();
-    }
-}
diff --git a/src/com/android/gallery3d/app/AlbumDataLoader.java b/src/com/android/gallery3d/app/AlbumDataLoader.java
deleted file mode 100644
index 28a8228..0000000
--- a/src/com/android/gallery3d/app/AlbumDataLoader.java
+++ /dev/null
@@ -1,397 +0,0 @@
-/*
- * Copyright (C) 2010 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.gallery3d.app;
-
-import android.os.Handler;
-import android.os.Message;
-import android.os.Process;
-
-import com.android.gallery3d.common.Utils;
-import com.android.gallery3d.data.ContentListener;
-import com.android.gallery3d.data.MediaItem;
-import com.android.gallery3d.data.MediaObject;
-import com.android.gallery3d.data.MediaSet;
-import com.android.gallery3d.data.Path;
-import com.android.gallery3d.ui.SynchronizedHandler;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.concurrent.Callable;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.FutureTask;
-
-public class AlbumDataLoader {
-    @SuppressWarnings("unused")
-    private static final String TAG = "AlbumDataAdapter";
-    private static final int DATA_CACHE_SIZE = 1000;
-
-    private static final int MSG_LOAD_START = 1;
-    private static final int MSG_LOAD_FINISH = 2;
-    private static final int MSG_RUN_OBJECT = 3;
-
-    private static final int MIN_LOAD_COUNT = 32;
-    private static final int MAX_LOAD_COUNT = 64;
-
-    private final MediaItem[] mData;
-    private final long[] mItemVersion;
-    private final long[] mSetVersion;
-
-    public static interface DataListener {
-        public void onContentChanged(int index);
-        public void onSizeChanged(int size);
-    }
-
-    private int mActiveStart = 0;
-    private int mActiveEnd = 0;
-
-    private int mContentStart = 0;
-    private int mContentEnd = 0;
-
-    private final MediaSet mSource;
-    private long mSourceVersion = MediaObject.INVALID_DATA_VERSION;
-
-    private final Handler mMainHandler;
-    private int mSize = 0;
-
-    private DataListener mDataListener;
-    private MySourceListener mSourceListener = new MySourceListener();
-    private LoadingListener mLoadingListener;
-
-    private ReloadTask mReloadTask;
-    // the data version on which last loading failed
-    private long mFailedVersion = MediaObject.INVALID_DATA_VERSION;
-
-    public AlbumDataLoader(AbstractGalleryActivity context, MediaSet mediaSet) {
-        mSource = mediaSet;
-
-        mData = new MediaItem[DATA_CACHE_SIZE];
-        mItemVersion = new long[DATA_CACHE_SIZE];
-        mSetVersion = new long[DATA_CACHE_SIZE];
-        Arrays.fill(mItemVersion, MediaObject.INVALID_DATA_VERSION);
-        Arrays.fill(mSetVersion, MediaObject.INVALID_DATA_VERSION);
-
-        mMainHandler = new SynchronizedHandler(context.getGLRoot()) {
-            @Override
-            public void handleMessage(Message message) {
-                switch (message.what) {
-                    case MSG_RUN_OBJECT:
-                        ((Runnable) message.obj).run();
-                        return;
-                    case MSG_LOAD_START:
-                        if (mLoadingListener != null) mLoadingListener.onLoadingStarted();
-                        return;
-                    case MSG_LOAD_FINISH:
-                        if (mLoadingListener != null) {
-                            boolean loadingFailed =
-                                    (mFailedVersion != MediaObject.INVALID_DATA_VERSION);
-                            mLoadingListener.onLoadingFinished(loadingFailed);
-                        }
-                        return;
-                }
-            }
-        };
-    }
-
-    public void resume() {
-        mSource.addContentListener(mSourceListener);
-        mReloadTask = new ReloadTask();
-        mReloadTask.start();
-    }
-
-    public void pause() {
-        mReloadTask.terminate();
-        mReloadTask = null;
-        mSource.removeContentListener(mSourceListener);
-    }
-
-    public MediaItem get(int index) {
-        if (!isActive(index)) {
-            return mSource.getMediaItem(index, 1).get(0);
-        }
-        return mData[index % mData.length];
-    }
-
-    public int getActiveStart() {
-        return mActiveStart;
-    }
-
-    public boolean isActive(int index) {
-        return index >= mActiveStart && index < mActiveEnd;
-    }
-
-    public int size() {
-        return mSize;
-    }
-
-    // Returns the index of the MediaItem with the given path or
-    // -1 if the path is not cached
-    public int findItem(Path id) {
-        for (int i = mContentStart; i < mContentEnd; i++) {
-            MediaItem item = mData[i % DATA_CACHE_SIZE];
-            if (item != null && id == item.getPath()) {
-                return i;
-            }
-        }
-        return -1;
-    }
-
-    private void clearSlot(int slotIndex) {
-        mData[slotIndex] = null;
-        mItemVersion[slotIndex] = MediaObject.INVALID_DATA_VERSION;
-        mSetVersion[slotIndex] = MediaObject.INVALID_DATA_VERSION;
-    }
-
-    private void setContentWindow(int contentStart, int contentEnd) {
-        if (contentStart == mContentStart && contentEnd == mContentEnd) return;
-        int end = mContentEnd;
-        int start = mContentStart;
-
-        // We need change the content window before calling reloadData(...)
-        synchronized (this) {
-            mContentStart = contentStart;
-            mContentEnd = contentEnd;
-        }
-        long[] itemVersion = mItemVersion;
-        long[] setVersion = mSetVersion;
-        if (contentStart >= end || start >= contentEnd) {
-            for (int i = start, n = end; i < n; ++i) {
-                clearSlot(i % DATA_CACHE_SIZE);
-            }
-        } else {
-            for (int i = start; i < contentStart; ++i) {
-                clearSlot(i % DATA_CACHE_SIZE);
-            }
-            for (int i = contentEnd, n = end; i < n; ++i) {
-                clearSlot(i % DATA_CACHE_SIZE);
-            }
-        }
-        if (mReloadTask != null) mReloadTask.notifyDirty();
-    }
-
-    public void setActiveWindow(int start, int end) {
-        if (start == mActiveStart && end == mActiveEnd) return;
-
-        Utils.assertTrue(start <= end
-                && end - start <= mData.length && end <= mSize);
-
-        int length = mData.length;
-        mActiveStart = start;
-        mActiveEnd = end;
-
-        // If no data is visible, keep the cache content
-        if (start == end) return;
-
-        int contentStart = Utils.clamp((start + end) / 2 - length / 2,
-                0, Math.max(0, mSize - length));
-        int contentEnd = Math.min(contentStart + length, mSize);
-        if (mContentStart > start || mContentEnd < end
-                || Math.abs(contentStart - mContentStart) > MIN_LOAD_COUNT) {
-            setContentWindow(contentStart, contentEnd);
-        }
-    }
-
-    private class MySourceListener implements ContentListener {
-        @Override
-        public void onContentDirty() {
-            if (mReloadTask != null) mReloadTask.notifyDirty();
-        }
-    }
-
-    public void setDataListener(DataListener listener) {
-        mDataListener = listener;
-    }
-
-    public void setLoadingListener(LoadingListener listener) {
-        mLoadingListener = listener;
-    }
-
-    private <T> T executeAndWait(Callable<T> callable) {
-        FutureTask<T> task = new FutureTask<T>(callable);
-        mMainHandler.sendMessage(
-                mMainHandler.obtainMessage(MSG_RUN_OBJECT, task));
-        try {
-            return task.get();
-        } catch (InterruptedException e) {
-            return null;
-        } catch (ExecutionException e) {
-            throw new RuntimeException(e);
-        }
-    }
-
-    private static class UpdateInfo {
-        public long version;
-        public int reloadStart;
-        public int reloadCount;
-
-        public int size;
-        public ArrayList<MediaItem> items;
-    }
-
-    private class GetUpdateInfo implements Callable<UpdateInfo> {
-        private final long mVersion;
-
-        public GetUpdateInfo(long version) {
-            mVersion = version;
-        }
-
-        @Override
-        public UpdateInfo call() throws Exception {
-            if (mFailedVersion == mVersion) {
-                // previous loading failed, return null to pause loading
-                return null;
-            }
-            UpdateInfo info = new UpdateInfo();
-            long version = mVersion;
-            info.version = mSourceVersion;
-            info.size = mSize;
-            long setVersion[] = mSetVersion;
-            for (int i = mContentStart, n = mContentEnd; i < n; ++i) {
-                int index = i % DATA_CACHE_SIZE;
-                if (setVersion[index] != version) {
-                    info.reloadStart = i;
-                    info.reloadCount = Math.min(MAX_LOAD_COUNT, n - i);
-                    return info;
-                }
-            }
-            return mSourceVersion == mVersion ? null : info;
-        }
-    }
-
-    private class UpdateContent implements Callable<Void> {
-
-        private UpdateInfo mUpdateInfo;
-
-        public UpdateContent(UpdateInfo info) {
-            mUpdateInfo = info;
-        }
-
-        @Override
-        public Void call() throws Exception {
-            UpdateInfo info = mUpdateInfo;
-            mSourceVersion = info.version;
-            if (mSize != info.size) {
-                mSize = info.size;
-                if (mDataListener != null) mDataListener.onSizeChanged(mSize);
-                if (mContentEnd > mSize) mContentEnd = mSize;
-                if (mActiveEnd > mSize) mActiveEnd = mSize;
-            }
-
-            ArrayList<MediaItem> items = info.items;
-
-            mFailedVersion = MediaObject.INVALID_DATA_VERSION;
-            if ((items == null) || items.isEmpty()) {
-                if (info.reloadCount > 0) {
-                    mFailedVersion = info.version;
-                    Log.d(TAG, "loading failed: " + mFailedVersion);
-                }
-                return null;
-            }
-            int start = Math.max(info.reloadStart, mContentStart);
-            int end = Math.min(info.reloadStart + items.size(), mContentEnd);
-
-            for (int i = start; i < end; ++i) {
-                int index = i % DATA_CACHE_SIZE;
-                mSetVersion[index] = info.version;
-                MediaItem updateItem = items.get(i - info.reloadStart);
-                long itemVersion = updateItem.getDataVersion();
-                if (mItemVersion[index] != itemVersion) {
-                    mItemVersion[index] = itemVersion;
-                    mData[index] = updateItem;
-                    if (mDataListener != null && i >= mActiveStart && i < mActiveEnd) {
-                        mDataListener.onContentChanged(i);
-                    }
-                }
-            }
-            return null;
-        }
-    }
-
-    /*
-     * The thread model of ReloadTask
-     *      *
-     * [Reload Task]       [Main Thread]
-     *       |                   |
-     * getUpdateInfo() -->       |           (synchronous call)
-     *     (wait) <----    getUpdateInfo()
-     *       |                   |
-     *   Load Data               |
-     *       |                   |
-     * updateContent() -->       |           (synchronous call)
-     *     (wait)          updateContent()
-     *       |                   |
-     *       |                   |
-     */
-    private class ReloadTask extends Thread {
-
-        private volatile boolean mActive = true;
-        private volatile boolean mDirty = true;
-        private boolean mIsLoading = false;
-
-        private void updateLoading(boolean loading) {
-            if (mIsLoading == loading) return;
-            mIsLoading = loading;
-            mMainHandler.sendEmptyMessage(loading ? MSG_LOAD_START : MSG_LOAD_FINISH);
-        }
-
-        @Override
-        public void run() {
-            Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
-
-            boolean updateComplete = false;
-            while (mActive) {
-                synchronized (this) {
-                    if (mActive && !mDirty && updateComplete) {
-                        updateLoading(false);
-                        if (mFailedVersion != MediaObject.INVALID_DATA_VERSION) {
-                            Log.d(TAG, "reload pause");
-                        }
-                        Utils.waitWithoutInterrupt(this);
-                        if (mActive && (mFailedVersion != MediaObject.INVALID_DATA_VERSION)) {
-                            Log.d(TAG, "reload resume");
-                        }
-                        continue;
-                    }
-                    mDirty = false;
-                }
-                updateLoading(true);
-                long version = mSource.reload();
-                UpdateInfo info = executeAndWait(new GetUpdateInfo(version));
-                updateComplete = info == null;
-                if (updateComplete) continue;
-                if (info.version != version) {
-                    info.size = mSource.getMediaItemCount();
-                    info.version = version;
-                }
-                if (info.reloadCount > 0) {
-                    info.items = mSource.getMediaItem(info.reloadStart, info.reloadCount);
-                }
-                executeAndWait(new UpdateContent(info));
-            }
-            updateLoading(false);
-        }
-
-        public synchronized void notifyDirty() {
-            mDirty = true;
-            notifyAll();
-        }
-
-        public synchronized void terminate() {
-            mActive = false;
-            notifyAll();
-        }
-    }
-}
diff --git a/src/com/android/gallery3d/app/AlbumPage.java b/src/com/android/gallery3d/app/AlbumPage.java
deleted file mode 100644
index 658abbb..0000000
--- a/src/com/android/gallery3d/app/AlbumPage.java
+++ /dev/null
@@ -1,786 +0,0 @@
-/*
- * Copyright (C) 2010 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.gallery3d.app;
-
-import android.app.Activity;
-import android.content.Context;
-import android.content.Intent;
-import android.graphics.Rect;
-import android.net.Uri;
-import android.os.Bundle;
-import android.os.Handler;
-import android.os.Message;
-import android.provider.MediaStore;
-import android.view.HapticFeedbackConstants;
-import android.view.Menu;
-import android.view.MenuInflater;
-import android.view.MenuItem;
-import android.widget.Toast;
-
-import com.android.gallery3d.R;
-import com.android.gallery3d.common.Utils;
-import com.android.gallery3d.data.DataManager;
-import com.android.gallery3d.data.MediaDetails;
-import com.android.gallery3d.data.MediaItem;
-import com.android.gallery3d.data.MediaObject;
-import com.android.gallery3d.data.MediaSet;
-import com.android.gallery3d.data.Path;
-import com.android.gallery3d.filtershow.crop.CropActivity;
-import com.android.gallery3d.filtershow.crop.CropExtras;
-import com.android.gallery3d.glrenderer.FadeTexture;
-import com.android.gallery3d.glrenderer.GLCanvas;
-import com.android.gallery3d.ui.ActionModeHandler;
-import com.android.gallery3d.ui.ActionModeHandler.ActionModeListener;
-import com.android.gallery3d.ui.AlbumSlotRenderer;
-import com.android.gallery3d.ui.DetailsHelper;
-import com.android.gallery3d.ui.DetailsHelper.CloseListener;
-import com.android.gallery3d.ui.GLRoot;
-import com.android.gallery3d.ui.GLView;
-import com.android.gallery3d.ui.PhotoFallbackEffect;
-import com.android.gallery3d.ui.RelativePosition;
-import com.android.gallery3d.ui.SelectionManager;
-import com.android.gallery3d.ui.SlotView;
-import com.android.gallery3d.ui.SynchronizedHandler;
-import com.android.gallery3d.util.Future;
-import com.android.gallery3d.util.GalleryUtils;
-import com.android.gallery3d.util.MediaSetUtils;
-
-
-public class AlbumPage extends ActivityState implements GalleryActionBar.ClusterRunner,
-        SelectionManager.SelectionListener, MediaSet.SyncListener, GalleryActionBar.OnAlbumModeSelectedListener {
-    @SuppressWarnings("unused")
-    private static final String TAG = "AlbumPage";
-
-    public static final String KEY_MEDIA_PATH = "media-path";
-    public static final String KEY_PARENT_MEDIA_PATH = "parent-media-path";
-    public static final String KEY_SET_CENTER = "set-center";
-    public static final String KEY_AUTO_SELECT_ALL = "auto-select-all";
-    public static final String KEY_SHOW_CLUSTER_MENU = "cluster-menu";
-    public static final String KEY_EMPTY_ALBUM = "empty-album";
-    public static final String KEY_RESUME_ANIMATION = "resume_animation";
-
-    private static final int REQUEST_SLIDESHOW = 1;
-    public static final int REQUEST_PHOTO = 2;
-    private static final int REQUEST_DO_ANIMATION = 3;
-
-    private static final int BIT_LOADING_RELOAD = 1;
-    private static final int BIT_LOADING_SYNC = 2;
-
-    private static final float USER_DISTANCE_METER = 0.3f;
-
-    private boolean mIsActive = false;
-    private AlbumSlotRenderer mAlbumView;
-    private Path mMediaSetPath;
-    private String mParentMediaSetString;
-    private SlotView mSlotView;
-
-    private AlbumDataLoader mAlbumDataAdapter;
-
-    protected SelectionManager mSelectionManager;
-
-    private boolean mGetContent;
-    private boolean mShowClusterMenu;
-
-    private ActionModeHandler mActionModeHandler;
-    private int mFocusIndex = 0;
-    private DetailsHelper mDetailsHelper;
-    private MyDetailsSource mDetailsSource;
-    private MediaSet mMediaSet;
-    private boolean mShowDetails;
-    private float mUserDistance; // in pixel
-    private Future<Integer> mSyncTask = null;
-    private boolean mLaunchedFromPhotoPage;
-    private boolean mInCameraApp;
-    private boolean mInCameraAndWantQuitOnPause;
-
-    private int mLoadingBits = 0;
-    private boolean mInitialSynced = false;
-    private int mSyncResult;
-    private boolean mLoadingFailed;
-    private RelativePosition mOpenCenter = new RelativePosition();
-
-    private Handler mHandler;
-    private static final int MSG_PICK_PHOTO = 0;
-
-    private PhotoFallbackEffect mResumeEffect;
-    private PhotoFallbackEffect.PositionProvider mPositionProvider =
-            new PhotoFallbackEffect.PositionProvider() {
-        @Override
-        public Rect getPosition(int index) {
-            Rect rect = mSlotView.getSlotRect(index);
-            Rect bounds = mSlotView.bounds();
-            rect.offset(bounds.left - mSlotView.getScrollX(),
-                    bounds.top - mSlotView.getScrollY());
-            return rect;
-        }
-
-        @Override
-        public int getItemIndex(Path path) {
-            int start = mSlotView.getVisibleStart();
-            int end = mSlotView.getVisibleEnd();
-            for (int i = start; i < end; ++i) {
-                MediaItem item = mAlbumDataAdapter.get(i);
-                if (item != null && item.getPath() == path) return i;
-            }
-            return -1;
-        }
-    };
-
-    @Override
-    protected int getBackgroundColorId() {
-        return R.color.album_background;
-    }
-
-    private final GLView mRootPane = new GLView() {
-        private final float mMatrix[] = new float[16];
-
-        @Override
-        protected void onLayout(
-                boolean changed, int left, int top, int right, int bottom) {
-
-            int slotViewTop = mActivity.getGalleryActionBar().getHeight();
-            int slotViewBottom = bottom - top;
-            int slotViewRight = right - left;
-
-            if (mShowDetails) {
-                mDetailsHelper.layout(left, slotViewTop, right, bottom);
-            } else {
-                mAlbumView.setHighlightItemPath(null);
-            }
-
-            // Set the mSlotView as a reference point to the open animation
-            mOpenCenter.setReferencePosition(0, slotViewTop);
-            mSlotView.layout(0, slotViewTop, slotViewRight, slotViewBottom);
-            GalleryUtils.setViewPointMatrix(mMatrix,
-                    (right - left) / 2, (bottom - top) / 2, -mUserDistance);
-        }
-
-        @Override
-        protected void render(GLCanvas canvas) {
-            canvas.save(GLCanvas.SAVE_FLAG_MATRIX);
-            canvas.multiplyMatrix(mMatrix, 0);
-            super.render(canvas);
-
-            if (mResumeEffect != null) {
-                boolean more = mResumeEffect.draw(canvas);
-                if (!more) {
-                    mResumeEffect = null;
-                    mAlbumView.setSlotFilter(null);
-                }
-                // We want to render one more time even when no more effect
-                // required. So that the animated thumbnails could be draw
-                // with declarations in super.render().
-                invalidate();
-            }
-            canvas.restore();
-        }
-    };
-
-    // This are the transitions we want:
-    //
-    // +--------+           +------------+    +-------+    +----------+
-    // | Camera |---------->| Fullscreen |--->| Album |--->| AlbumSet |
-    // |  View  | thumbnail |   Photo    | up | Page  | up |   Page   |
-    // +--------+           +------------+    +-------+    +----------+
-    //     ^                      |               |            ^  |
-    //     |                      |               |            |  |         close
-    //     +----------back--------+               +----back----+  +--back->  app
-    //
-    @Override
-    protected void onBackPressed() {
-        if (mShowDetails) {
-            hideDetails();
-        } else if (mSelectionManager.inSelectionMode()) {
-            mSelectionManager.leaveSelectionMode();
-        } else {
-            if(mLaunchedFromPhotoPage) {
-                mActivity.getTransitionStore().putIfNotPresent(
-                        PhotoPage.KEY_ALBUMPAGE_TRANSITION,
-                        PhotoPage.MSG_ALBUMPAGE_RESUMED);
-            }
-            // TODO: fix this regression
-            // mAlbumView.savePositions(PositionRepository.getInstance(mActivity));
-            if (mInCameraApp) {
-                super.onBackPressed();
-            } else {
-                onUpPressed();
-            }
-        }
-    }
-
-    private void onUpPressed() {
-        if (mInCameraApp) {
-            GalleryUtils.startGalleryActivity(mActivity);
-        } else if (mActivity.getStateManager().getStateCount() > 1) {
-            super.onBackPressed();
-        } else if (mParentMediaSetString != null) {
-            Bundle data = new Bundle(getData());
-            data.putString(AlbumSetPage.KEY_MEDIA_PATH, mParentMediaSetString);
-            mActivity.getStateManager().switchState(
-                    this, AlbumSetPage.class, data);
-        }
-    }
-
-    private void onDown(int index) {
-        mAlbumView.setPressedIndex(index);
-    }
-
-    private void onUp(boolean followedByLongPress) {
-        if (followedByLongPress) {
-            // Avoid showing press-up animations for long-press.
-            mAlbumView.setPressedIndex(-1);
-        } else {
-            mAlbumView.setPressedUp();
-        }
-    }
-
-    private void onSingleTapUp(int slotIndex) {
-        if (!mIsActive) return;
-
-        if (mSelectionManager.inSelectionMode()) {
-            MediaItem item = mAlbumDataAdapter.get(slotIndex);
-            if (item == null) return; // Item not ready yet, ignore the click
-            mSelectionManager.toggle(item.getPath());
-            mSlotView.invalidate();
-        } else {
-            // Render transition in pressed state
-            mAlbumView.setPressedIndex(slotIndex);
-            mAlbumView.setPressedUp();
-            mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG_PICK_PHOTO, slotIndex, 0),
-                    FadeTexture.DURATION);
-        }
-    }
-
-    private void pickPhoto(int slotIndex) {
-        pickPhoto(slotIndex, false);
-    }
-
-    private void pickPhoto(int slotIndex, boolean startInFilmstrip) {
-        if (!mIsActive) return;
-
-        if (!startInFilmstrip) {
-            // Launch photos in lights out mode
-            mActivity.getGLRoot().setLightsOutMode(true);
-        }
-
-        MediaItem item = mAlbumDataAdapter.get(slotIndex);
-        if (item == null) return; // Item not ready yet, ignore the click
-        if (mGetContent) {
-            onGetContent(item);
-        } else if (mLaunchedFromPhotoPage) {
-            TransitionStore transitions = mActivity.getTransitionStore();
-            transitions.put(
-                    PhotoPage.KEY_ALBUMPAGE_TRANSITION,
-                    PhotoPage.MSG_ALBUMPAGE_PICKED);
-            transitions.put(PhotoPage.KEY_INDEX_HINT, slotIndex);
-            onBackPressed();
-        } else {
-            // Get into the PhotoPage.
-            // mAlbumView.savePositions(PositionRepository.getInstance(mActivity));
-            Bundle data = new Bundle();
-            data.putInt(PhotoPage.KEY_INDEX_HINT, slotIndex);
-            data.putParcelable(PhotoPage.KEY_OPEN_ANIMATION_RECT,
-                    mSlotView.getSlotRect(slotIndex, mRootPane));
-            data.putString(PhotoPage.KEY_MEDIA_SET_PATH,
-                    mMediaSetPath.toString());
-            data.putString(PhotoPage.KEY_MEDIA_ITEM_PATH,
-                    item.getPath().toString());
-            data.putInt(PhotoPage.KEY_ALBUMPAGE_TRANSITION,
-                    PhotoPage.MSG_ALBUMPAGE_STARTED);
-            data.putBoolean(PhotoPage.KEY_START_IN_FILMSTRIP,
-                    startInFilmstrip);
-            data.putBoolean(PhotoPage.KEY_IN_CAMERA_ROLL, mMediaSet.isCameraRoll());
-            if (startInFilmstrip) {
-                mActivity.getStateManager().switchState(this, FilmstripPage.class, data);
-            } else {
-                mActivity.getStateManager().startStateForResult(
-                            SinglePhotoPage.class, REQUEST_PHOTO, data);
-            }
-        }
-    }
-
-    private void onGetContent(final MediaItem item) {
-        DataManager dm = mActivity.getDataManager();
-        Activity activity = mActivity;
-        if (mData.getString(Gallery.EXTRA_CROP) != null) {
-            Uri uri = dm.getContentUri(item.getPath());
-            Intent intent = new Intent(CropActivity.CROP_ACTION, uri)
-                    .addFlags(Intent.FLAG_ACTIVITY_FORWARD_RESULT)
-                    .putExtras(getData());
-            if (mData.getParcelable(MediaStore.EXTRA_OUTPUT) == null) {
-                intent.putExtra(CropExtras.KEY_RETURN_DATA, true);
-            }
-            activity.startActivity(intent);
-            activity.finish();
-        } else {
-            Intent intent = new Intent(null, item.getContentUri())
-                .addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
-            activity.setResult(Activity.RESULT_OK, intent);
-            activity.finish();
-        }
-    }
-
-    public void onLongTap(int slotIndex) {
-        if (mGetContent) return;
-        MediaItem item = mAlbumDataAdapter.get(slotIndex);
-        if (item == null) return;
-        mSelectionManager.setAutoLeaveSelectionMode(true);
-        mSelectionManager.toggle(item.getPath());
-        mSlotView.invalidate();
-    }
-
-    @Override
-    public void doCluster(int clusterType) {
-        String basePath = mMediaSet.getPath().toString();
-        String newPath = FilterUtils.newClusterPath(basePath, clusterType);
-        Bundle data = new Bundle(getData());
-        data.putString(AlbumSetPage.KEY_MEDIA_PATH, newPath);
-        if (mShowClusterMenu) {
-            Context context = mActivity.getAndroidContext();
-            data.putString(AlbumSetPage.KEY_SET_TITLE, mMediaSet.getName());
-            data.putString(AlbumSetPage.KEY_SET_SUBTITLE,
-                    GalleryActionBar.getClusterByTypeString(context, clusterType));
-        }
-
-        // mAlbumView.savePositions(PositionRepository.getInstance(mActivity));
-        mActivity.getStateManager().startStateForResult(
-                AlbumSetPage.class, REQUEST_DO_ANIMATION, data);
-    }
-
-    @Override
-    protected void onCreate(Bundle data, Bundle restoreState) {
-        super.onCreate(data, restoreState);
-        mUserDistance = GalleryUtils.meterToPixel(USER_DISTANCE_METER);
-        initializeViews();
-        initializeData(data);
-        mGetContent = data.getBoolean(Gallery.KEY_GET_CONTENT, false);
-        mShowClusterMenu = data.getBoolean(KEY_SHOW_CLUSTER_MENU, false);
-        mDetailsSource = new MyDetailsSource();
-        Context context = mActivity.getAndroidContext();
-
-        if (data.getBoolean(KEY_AUTO_SELECT_ALL)) {
-            mSelectionManager.selectAll();
-        }
-
-        mLaunchedFromPhotoPage =
-                mActivity.getStateManager().hasStateClass(FilmstripPage.class);
-        mInCameraApp = data.getBoolean(PhotoPage.KEY_APP_BRIDGE, false);
-
-        mHandler = new SynchronizedHandler(mActivity.getGLRoot()) {
-            @Override
-            public void handleMessage(Message message) {
-                switch (message.what) {
-                    case MSG_PICK_PHOTO: {
-                        pickPhoto(message.arg1);
-                        break;
-                    }
-                    default:
-                        throw new AssertionError(message.what);
-                }
-            }
-        };
-    }
-
-    @Override
-    protected void onResume() {
-        super.onResume();
-        mIsActive = true;
-
-        mResumeEffect = mActivity.getTransitionStore().get(KEY_RESUME_ANIMATION);
-        if (mResumeEffect != null) {
-            mAlbumView.setSlotFilter(mResumeEffect);
-            mResumeEffect.setPositionProvider(mPositionProvider);
-            mResumeEffect.start();
-        }
-
-        setContentPane(mRootPane);
-
-        boolean enableHomeButton = (mActivity.getStateManager().getStateCount() > 1) |
-                mParentMediaSetString != null;
-        GalleryActionBar actionBar = mActivity.getGalleryActionBar();
-        actionBar.setDisplayOptions(enableHomeButton, false);
-        if (!mGetContent) {
-            actionBar.enableAlbumModeMenu(GalleryActionBar.ALBUM_GRID_MODE_SELECTED, this);
-        }
-
-        // Set the reload bit here to prevent it exit this page in clearLoadingBit().
-        setLoadingBit(BIT_LOADING_RELOAD);
-        mLoadingFailed = false;
-        mAlbumDataAdapter.resume();
-
-        mAlbumView.resume();
-        mAlbumView.setPressedIndex(-1);
-        mActionModeHandler.resume();
-        if (!mInitialSynced) {
-            setLoadingBit(BIT_LOADING_SYNC);
-            mSyncTask = mMediaSet.requestSync(this);
-        }
-        mInCameraAndWantQuitOnPause = mInCameraApp;
-    }
-
-    @Override
-    protected void onPause() {
-        super.onPause();
-        mIsActive = false;
-
-        if (mSelectionManager.inSelectionMode()) {
-            mSelectionManager.leaveSelectionMode();
-        }
-        mAlbumView.setSlotFilter(null);
-        mActionModeHandler.pause();
-        mAlbumDataAdapter.pause();
-        mAlbumView.pause();
-        DetailsHelper.pause();
-        if (!mGetContent) {
-            mActivity.getGalleryActionBar().disableAlbumModeMenu(true);
-        }
-
-        if (mSyncTask != null) {
-            mSyncTask.cancel();
-            mSyncTask = null;
-            clearLoadingBit(BIT_LOADING_SYNC);
-        }
-    }
-
-    @Override
-    protected void onDestroy() {
-        super.onDestroy();
-        if (mAlbumDataAdapter != null) {
-            mAlbumDataAdapter.setLoadingListener(null);
-        }
-        mActionModeHandler.destroy();
-    }
-
-    private void initializeViews() {
-        mSelectionManager = new SelectionManager(mActivity, false);
-        mSelectionManager.setSelectionListener(this);
-        Config.AlbumPage config = Config.AlbumPage.get(mActivity);
-        mSlotView = new SlotView(mActivity, config.slotViewSpec);
-        mAlbumView = new AlbumSlotRenderer(mActivity, mSlotView,
-                mSelectionManager, config.placeholderColor);
-        mSlotView.setSlotRenderer(mAlbumView);
-        mRootPane.addComponent(mSlotView);
-        mSlotView.setListener(new SlotView.SimpleListener() {
-            @Override
-            public void onDown(int index) {
-                AlbumPage.this.onDown(index);
-            }
-
-            @Override
-            public void onUp(boolean followedByLongPress) {
-                AlbumPage.this.onUp(followedByLongPress);
-            }
-
-            @Override
-            public void onSingleTapUp(int slotIndex) {
-                AlbumPage.this.onSingleTapUp(slotIndex);
-            }
-
-            @Override
-            public void onLongTap(int slotIndex) {
-                AlbumPage.this.onLongTap(slotIndex);
-            }
-        });
-        mActionModeHandler = new ActionModeHandler(mActivity, mSelectionManager);
-        mActionModeHandler.setActionModeListener(new ActionModeListener() {
-            @Override
-            public boolean onActionItemClicked(MenuItem item) {
-                return onItemSelected(item);
-            }
-        });
-    }
-
-    private void initializeData(Bundle data) {
-        mMediaSetPath = Path.fromString(data.getString(KEY_MEDIA_PATH));
-        mParentMediaSetString = data.getString(KEY_PARENT_MEDIA_PATH);
-        mMediaSet = mActivity.getDataManager().getMediaSet(mMediaSetPath);
-        if (mMediaSet == null) {
-            Utils.fail("MediaSet is null. Path = %s", mMediaSetPath);
-        }
-        mSelectionManager.setSourceMediaSet(mMediaSet);
-        mAlbumDataAdapter = new AlbumDataLoader(mActivity, mMediaSet);
-        mAlbumDataAdapter.setLoadingListener(new MyLoadingListener());
-        mAlbumView.setModel(mAlbumDataAdapter);
-    }
-
-    private void showDetails() {
-        mShowDetails = true;
-        if (mDetailsHelper == null) {
-            mDetailsHelper = new DetailsHelper(mActivity, mRootPane, mDetailsSource);
-            mDetailsHelper.setCloseListener(new CloseListener() {
-                @Override
-                public void onClose() {
-                    hideDetails();
-                }
-            });
-        }
-        mDetailsHelper.show();
-    }
-
-    private void hideDetails() {
-        mShowDetails = false;
-        mDetailsHelper.hide();
-        mAlbumView.setHighlightItemPath(null);
-        mSlotView.invalidate();
-    }
-
-    @Override
-    protected boolean onCreateActionBar(Menu menu) {
-        GalleryActionBar actionBar = mActivity.getGalleryActionBar();
-        MenuInflater inflator = getSupportMenuInflater();
-        if (mGetContent) {
-            inflator.inflate(R.menu.pickup, menu);
-            int typeBits = mData.getInt(Gallery.KEY_TYPE_BITS,
-                    DataManager.INCLUDE_IMAGE);
-            actionBar.setTitle(GalleryUtils.getSelectionModePrompt(typeBits));
-        } else {
-            inflator.inflate(R.menu.album, menu);
-            actionBar.setTitle(mMediaSet.getName());
-
-            FilterUtils.setupMenuItems(actionBar, mMediaSetPath, true);
-
-            menu.findItem(R.id.action_group_by).setVisible(mShowClusterMenu);
-            menu.findItem(R.id.action_camera).setVisible(
-                    MediaSetUtils.isCameraSource(mMediaSetPath)
-                    && GalleryUtils.isCameraAvailable(mActivity));
-
-        }
-        actionBar.setSubtitle(null);
-        return true;
-    }
-
-    private void prepareAnimationBackToFilmstrip(int slotIndex) {
-        if (mAlbumDataAdapter == null || !mAlbumDataAdapter.isActive(slotIndex)) return;
-        MediaItem item = mAlbumDataAdapter.get(slotIndex);
-        if (item == null) return;
-        TransitionStore transitions = mActivity.getTransitionStore();
-        transitions.put(PhotoPage.KEY_INDEX_HINT, slotIndex);
-        transitions.put(PhotoPage.KEY_OPEN_ANIMATION_RECT,
-                mSlotView.getSlotRect(slotIndex, mRootPane));
-    }
-
-    private void switchToFilmstrip() {
-        if (mAlbumDataAdapter.size() < 1) return;
-        int targetPhoto = mSlotView.getVisibleStart();
-        prepareAnimationBackToFilmstrip(targetPhoto);
-        if(mLaunchedFromPhotoPage) {
-            onBackPressed();
-        } else {
-            pickPhoto(targetPhoto, true);
-        }
-    }
-
-    @Override
-    protected boolean onItemSelected(MenuItem item) {
-        switch (item.getItemId()) {
-            case android.R.id.home: {
-                onUpPressed();
-                return true;
-            }
-            case R.id.action_cancel:
-                mActivity.getStateManager().finishState(this);
-                return true;
-            case R.id.action_select:
-                mSelectionManager.setAutoLeaveSelectionMode(false);
-                mSelectionManager.enterSelectionMode();
-                return true;
-            case R.id.action_group_by: {
-                mActivity.getGalleryActionBar().showClusterDialog(this);
-                return true;
-            }
-            case R.id.action_slideshow: {
-                mInCameraAndWantQuitOnPause = false;
-                Bundle data = new Bundle();
-                data.putString(SlideshowPage.KEY_SET_PATH,
-                        mMediaSetPath.toString());
-                data.putBoolean(SlideshowPage.KEY_REPEAT, true);
-                mActivity.getStateManager().startStateForResult(
-                        SlideshowPage.class, REQUEST_SLIDESHOW, data);
-                return true;
-            }
-            case R.id.action_details: {
-                if (mShowDetails) {
-                    hideDetails();
-                } else {
-                    showDetails();
-                }
-                return true;
-            }
-            case R.id.action_camera: {
-                GalleryUtils.startCameraActivity(mActivity);
-                return true;
-            }
-            default:
-                return false;
-        }
-    }
-
-    @Override
-    protected void onStateResult(int request, int result, Intent data) {
-        switch (request) {
-            case REQUEST_SLIDESHOW: {
-                // data could be null, if there is no images in the album
-                if (data == null) return;
-                mFocusIndex = data.getIntExtra(SlideshowPage.KEY_PHOTO_INDEX, 0);
-                mSlotView.setCenterIndex(mFocusIndex);
-                break;
-            }
-            case REQUEST_PHOTO: {
-                if (data == null) return;
-                mFocusIndex = data.getIntExtra(PhotoPage.KEY_RETURN_INDEX_HINT, 0);
-                mSlotView.makeSlotVisible(mFocusIndex);
-                break;
-            }
-            case REQUEST_DO_ANIMATION: {
-                mSlotView.startRisingAnimation();
-                break;
-            }
-        }
-    }
-
-    @Override
-    public void onSelectionModeChange(int mode) {
-        switch (mode) {
-            case SelectionManager.ENTER_SELECTION_MODE: {
-                mActionModeHandler.startActionMode();
-                performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
-                break;
-            }
-            case SelectionManager.LEAVE_SELECTION_MODE: {
-                mActionModeHandler.finishActionMode();
-                mRootPane.invalidate();
-                break;
-            }
-            case SelectionManager.SELECT_ALL_MODE: {
-                mActionModeHandler.updateSupportedOperation();
-                mRootPane.invalidate();
-                break;
-            }
-        }
-    }
-
-    @Override
-    public void onSelectionChange(Path path, boolean selected) {
-        int count = mSelectionManager.getSelectedCount();
-        String format = mActivity.getResources().getQuantityString(
-                R.plurals.number_of_items_selected, count);
-        mActionModeHandler.setTitle(String.format(format, count));
-        mActionModeHandler.updateSupportedOperation(path, selected);
-    }
-
-    @Override
-    public void onSyncDone(final MediaSet mediaSet, final int resultCode) {
-        Log.d(TAG, "onSyncDone: " + Utils.maskDebugInfo(mediaSet.getName()) + " result="
-                + resultCode);
-        ((Activity) mActivity).runOnUiThread(new Runnable() {
-            @Override
-            public void run() {
-                GLRoot root = mActivity.getGLRoot();
-                root.lockRenderThread();
-                mSyncResult = resultCode;
-                try {
-                    if (resultCode == MediaSet.SYNC_RESULT_SUCCESS) {
-                        mInitialSynced = true;
-                    }
-                    clearLoadingBit(BIT_LOADING_SYNC);
-                    showSyncErrorIfNecessary(mLoadingFailed);
-                } finally {
-                    root.unlockRenderThread();
-                }
-            }
-        });
-    }
-
-    // Show sync error toast when all the following conditions are met:
-    // (1) both loading and sync are done,
-    // (2) sync result is error,
-    // (3) the page is still active, and
-    // (4) no photo is shown or loading fails.
-    private void showSyncErrorIfNecessary(boolean loadingFailed) {
-        if ((mLoadingBits == 0) && (mSyncResult == MediaSet.SYNC_RESULT_ERROR) && mIsActive
-                && (loadingFailed || (mAlbumDataAdapter.size() == 0))) {
-            Toast.makeText(mActivity, R.string.sync_album_error,
-                    Toast.LENGTH_LONG).show();
-        }
-    }
-
-    private void setLoadingBit(int loadTaskBit) {
-        mLoadingBits |= loadTaskBit;
-    }
-
-    private void clearLoadingBit(int loadTaskBit) {
-        mLoadingBits &= ~loadTaskBit;
-        if (mLoadingBits == 0 && mIsActive) {
-            if (mAlbumDataAdapter.size() == 0) {
-                Intent result = new Intent();
-                result.putExtra(KEY_EMPTY_ALBUM, true);
-                setStateResult(Activity.RESULT_OK, result);
-                mActivity.getStateManager().finishState(this);
-            }
-        }
-    }
-
-    private class MyLoadingListener implements LoadingListener {
-        @Override
-        public void onLoadingStarted() {
-            setLoadingBit(BIT_LOADING_RELOAD);
-            mLoadingFailed = false;
-        }
-
-        @Override
-        public void onLoadingFinished(boolean loadingFailed) {
-            clearLoadingBit(BIT_LOADING_RELOAD);
-            mLoadingFailed = loadingFailed;
-            showSyncErrorIfNecessary(loadingFailed);
-        }
-    }
-
-    private class MyDetailsSource implements DetailsHelper.DetailsSource {
-        private int mIndex;
-
-        @Override
-        public int size() {
-            return mAlbumDataAdapter.size();
-        }
-
-        @Override
-        public int setIndex() {
-            Path id = mSelectionManager.getSelected(false).get(0);
-            mIndex = mAlbumDataAdapter.findItem(id);
-            return mIndex;
-        }
-
-        @Override
-        public MediaDetails getDetails() {
-            // this relies on setIndex() being called beforehand
-            MediaObject item = mAlbumDataAdapter.get(mIndex);
-            if (item != null) {
-                mAlbumView.setHighlightItemPath(item.getPath());
-                return item.getDetails();
-            } else {
-                return null;
-            }
-        }
-    }
-
-    @Override
-    public void onAlbumModeSelected(int mode) {
-        if (mode == GalleryActionBar.ALBUM_FILMSTRIP_MODE_SELECTED) {
-            switchToFilmstrip();
-        }
-    }
-}
diff --git a/src/com/android/gallery3d/app/AlbumPicker.java b/src/com/android/gallery3d/app/AlbumPicker.java
deleted file mode 100644
index 65eb772..0000000
--- a/src/com/android/gallery3d/app/AlbumPicker.java
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright (C) 2011 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.gallery3d.app;
-
-import android.content.Intent;
-import android.os.Bundle;
-
-import com.android.gallery3d.R;
-import com.android.gallery3d.data.DataManager;
-
-public class AlbumPicker extends PickerActivity {
-
-    @Override
-    public void onCreate(Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-        setTitle(R.string.select_album);
-        Intent intent = getIntent();
-        Bundle extras = intent.getExtras();
-        Bundle data = extras == null ? new Bundle() : new Bundle(extras);
-
-        data.putBoolean(Gallery.KEY_GET_ALBUM, true);
-        data.putString(AlbumSetPage.KEY_MEDIA_PATH,
-                getDataManager().getTopSetPath(DataManager.INCLUDE_IMAGE));
-        getStateManager().startState(AlbumSetPage.class, data);
-    }
-}
diff --git a/src/com/android/gallery3d/app/AlbumSetDataLoader.java b/src/com/android/gallery3d/app/AlbumSetDataLoader.java
deleted file mode 100644
index cf380f8..0000000
--- a/src/com/android/gallery3d/app/AlbumSetDataLoader.java
+++ /dev/null
@@ -1,393 +0,0 @@
-/*
- * Copyright (C) 2010 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.gallery3d.app;
-
-import android.os.Handler;
-import android.os.Message;
-import android.os.Process;
-
-import com.android.gallery3d.common.Utils;
-import com.android.gallery3d.data.ContentListener;
-import com.android.gallery3d.data.MediaItem;
-import com.android.gallery3d.data.MediaObject;
-import com.android.gallery3d.data.MediaSet;
-import com.android.gallery3d.data.Path;
-import com.android.gallery3d.ui.SynchronizedHandler;
-
-import java.util.Arrays;
-import java.util.concurrent.Callable;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.FutureTask;
-
-public class AlbumSetDataLoader {
-    @SuppressWarnings("unused")
-    private static final String TAG = "AlbumSetDataAdapter";
-
-    private static final int INDEX_NONE = -1;
-
-    private static final int MIN_LOAD_COUNT = 4;
-
-    private static final int MSG_LOAD_START = 1;
-    private static final int MSG_LOAD_FINISH = 2;
-    private static final int MSG_RUN_OBJECT = 3;
-
-    public static interface DataListener {
-        public void onContentChanged(int index);
-        public void onSizeChanged(int size);
-    }
-
-    private final MediaSet[] mData;
-    private final MediaItem[] mCoverItem;
-    private final int[] mTotalCount;
-    private final long[] mItemVersion;
-    private final long[] mSetVersion;
-
-    private int mActiveStart = 0;
-    private int mActiveEnd = 0;
-
-    private int mContentStart = 0;
-    private int mContentEnd = 0;
-
-    private final MediaSet mSource;
-    private long mSourceVersion = MediaObject.INVALID_DATA_VERSION;
-    private int mSize;
-
-    private DataListener mDataListener;
-    private LoadingListener mLoadingListener;
-    private ReloadTask mReloadTask;
-
-    private final Handler mMainHandler;
-
-    private final MySourceListener mSourceListener = new MySourceListener();
-
-    public AlbumSetDataLoader(AbstractGalleryActivity activity, MediaSet albumSet, int cacheSize) {
-        mSource = Utils.checkNotNull(albumSet);
-        mCoverItem = new MediaItem[cacheSize];
-        mData = new MediaSet[cacheSize];
-        mTotalCount = new int[cacheSize];
-        mItemVersion = new long[cacheSize];
-        mSetVersion = new long[cacheSize];
-        Arrays.fill(mItemVersion, MediaObject.INVALID_DATA_VERSION);
-        Arrays.fill(mSetVersion, MediaObject.INVALID_DATA_VERSION);
-
-        mMainHandler = new SynchronizedHandler(activity.getGLRoot()) {
-            @Override
-            public void handleMessage(Message message) {
-                switch (message.what) {
-                    case MSG_RUN_OBJECT:
-                        ((Runnable) message.obj).run();
-                        return;
-                    case MSG_LOAD_START:
-                        if (mLoadingListener != null) mLoadingListener.onLoadingStarted();
-                        return;
-                    case MSG_LOAD_FINISH:
-                        if (mLoadingListener != null) mLoadingListener.onLoadingFinished(false);
-                        return;
-                }
-            }
-        };
-    }
-
-    public void pause() {
-        mReloadTask.terminate();
-        mReloadTask = null;
-        mSource.removeContentListener(mSourceListener);
-    }
-
-    public void resume() {
-        mSource.addContentListener(mSourceListener);
-        mReloadTask = new ReloadTask();
-        mReloadTask.start();
-    }
-
-    private void assertIsActive(int index) {
-        if (index < mActiveStart && index >= mActiveEnd) {
-            throw new IllegalArgumentException(String.format(
-                    "%s not in (%s, %s)", index, mActiveStart, mActiveEnd));
-        }
-    }
-
-    public MediaSet getMediaSet(int index) {
-        assertIsActive(index);
-        return mData[index % mData.length];
-    }
-
-    public MediaItem getCoverItem(int index) {
-        assertIsActive(index);
-        return mCoverItem[index % mCoverItem.length];
-    }
-
-    public int getTotalCount(int index) {
-        assertIsActive(index);
-        return mTotalCount[index % mTotalCount.length];
-    }
-
-    public int getActiveStart() {
-        return mActiveStart;
-    }
-
-    public boolean isActive(int index) {
-        return index >= mActiveStart && index < mActiveEnd;
-    }
-
-    public int size() {
-        return mSize;
-    }
-
-    // Returns the index of the MediaSet with the given path or
-    // -1 if the path is not cached
-    public int findSet(Path id) {
-        int length = mData.length;
-        for (int i = mContentStart; i < mContentEnd; i++) {
-            MediaSet set = mData[i % length];
-            if (set != null && id == set.getPath()) {
-                return i;
-            }
-        }
-        return -1;
-    }
-
-    private void clearSlot(int slotIndex) {
-        mData[slotIndex] = null;
-        mCoverItem[slotIndex] = null;
-        mTotalCount[slotIndex] = 0;
-        mItemVersion[slotIndex] = MediaObject.INVALID_DATA_VERSION;
-        mSetVersion[slotIndex] = MediaObject.INVALID_DATA_VERSION;
-    }
-
-    private void setContentWindow(int contentStart, int contentEnd) {
-        if (contentStart == mContentStart && contentEnd == mContentEnd) return;
-        int length = mCoverItem.length;
-
-        int start = this.mContentStart;
-        int end = this.mContentEnd;
-
-        mContentStart = contentStart;
-        mContentEnd = contentEnd;
-
-        if (contentStart >= end || start >= contentEnd) {
-            for (int i = start, n = end; i < n; ++i) {
-                clearSlot(i % length);
-            }
-        } else {
-            for (int i = start; i < contentStart; ++i) {
-                clearSlot(i % length);
-            }
-            for (int i = contentEnd, n = end; i < n; ++i) {
-                clearSlot(i % length);
-            }
-        }
-        mReloadTask.notifyDirty();
-    }
-
-    public void setActiveWindow(int start, int end) {
-        if (start == mActiveStart && end == mActiveEnd) return;
-
-        Utils.assertTrue(start <= end
-                && end - start <= mCoverItem.length && end <= mSize);
-
-        mActiveStart = start;
-        mActiveEnd = end;
-
-        int length = mCoverItem.length;
-        // If no data is visible, keep the cache content
-        if (start == end) return;
-
-        int contentStart = Utils.clamp((start + end) / 2 - length / 2,
-                0, Math.max(0, mSize - length));
-        int contentEnd = Math.min(contentStart + length, mSize);
-        if (mContentStart > start || mContentEnd < end
-                || Math.abs(contentStart - mContentStart) > MIN_LOAD_COUNT) {
-            setContentWindow(contentStart, contentEnd);
-        }
-    }
-
-    private class MySourceListener implements ContentListener {
-        @Override
-        public void onContentDirty() {
-            mReloadTask.notifyDirty();
-        }
-    }
-
-    public void setModelListener(DataListener listener) {
-        mDataListener = listener;
-    }
-
-    public void setLoadingListener(LoadingListener listener) {
-        mLoadingListener = listener;
-    }
-
-    private static class UpdateInfo {
-        public long version;
-        public int index;
-
-        public int size;
-        public MediaSet item;
-        public MediaItem cover;
-        public int totalCount;
-    }
-
-    private class GetUpdateInfo implements Callable<UpdateInfo> {
-
-        private final long mVersion;
-
-        public GetUpdateInfo(long version) {
-            mVersion = version;
-        }
-
-        private int getInvalidIndex(long version) {
-            long setVersion[] = mSetVersion;
-            int length = setVersion.length;
-            for (int i = mContentStart, n = mContentEnd; i < n; ++i) {
-                int index = i % length;
-                if (setVersion[i % length] != version) return i;
-            }
-            return INDEX_NONE;
-        }
-
-        @Override
-        public UpdateInfo call() throws Exception {
-            int index = getInvalidIndex(mVersion);
-            if (index == INDEX_NONE && mSourceVersion == mVersion) return null;
-            UpdateInfo info = new UpdateInfo();
-            info.version = mSourceVersion;
-            info.index = index;
-            info.size = mSize;
-            return info;
-        }
-    }
-
-    private class UpdateContent implements Callable<Void> {
-        private final UpdateInfo mUpdateInfo;
-
-        public UpdateContent(UpdateInfo info) {
-            mUpdateInfo = info;
-        }
-
-        @Override
-        public Void call() {
-            // Avoid notifying listeners of status change after pause
-            // Otherwise gallery will be in inconsistent state after resume.
-            if (mReloadTask == null) return null;
-            UpdateInfo info = mUpdateInfo;
-            mSourceVersion = info.version;
-            if (mSize != info.size) {
-                mSize = info.size;
-                if (mDataListener != null) mDataListener.onSizeChanged(mSize);
-                if (mContentEnd > mSize) mContentEnd = mSize;
-                if (mActiveEnd > mSize) mActiveEnd = mSize;
-            }
-            // Note: info.index could be INDEX_NONE, i.e., -1
-            if (info.index >= mContentStart && info.index < mContentEnd) {
-                int pos = info.index % mCoverItem.length;
-                mSetVersion[pos] = info.version;
-                long itemVersion = info.item.getDataVersion();
-                if (mItemVersion[pos] == itemVersion) return null;
-                mItemVersion[pos] = itemVersion;
-                mData[pos] = info.item;
-                mCoverItem[pos] = info.cover;
-                mTotalCount[pos] = info.totalCount;
-                if (mDataListener != null
-                        && info.index >= mActiveStart && info.index < mActiveEnd) {
-                    mDataListener.onContentChanged(info.index);
-                }
-            }
-            return null;
-        }
-    }
-
-    private <T> T executeAndWait(Callable<T> callable) {
-        FutureTask<T> task = new FutureTask<T>(callable);
-        mMainHandler.sendMessage(
-                mMainHandler.obtainMessage(MSG_RUN_OBJECT, task));
-        try {
-            return task.get();
-        } catch (InterruptedException e) {
-            return null;
-        } catch (ExecutionException e) {
-            throw new RuntimeException(e);
-        }
-    }
-
-    // TODO: load active range first
-    private class ReloadTask extends Thread {
-        private volatile boolean mActive = true;
-        private volatile boolean mDirty = true;
-        private volatile boolean mIsLoading = false;
-
-        private void updateLoading(boolean loading) {
-            if (mIsLoading == loading) return;
-            mIsLoading = loading;
-            mMainHandler.sendEmptyMessage(loading ? MSG_LOAD_START : MSG_LOAD_FINISH);
-        }
-
-        @Override
-        public void run() {
-            Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
-
-            boolean updateComplete = false;
-            while (mActive) {
-                synchronized (this) {
-                    if (mActive && !mDirty && updateComplete) {
-                        if (!mSource.isLoading()) updateLoading(false);
-                        Utils.waitWithoutInterrupt(this);
-                        continue;
-                    }
-                }
-                mDirty = false;
-                updateLoading(true);
-
-                long version = mSource.reload();
-                UpdateInfo info = executeAndWait(new GetUpdateInfo(version));
-                updateComplete = info == null;
-                if (updateComplete) continue;
-                if (info.version != version) {
-                    info.version = version;
-                    info.size = mSource.getSubMediaSetCount();
-
-                    // If the size becomes smaller after reload(), we may
-                    // receive from GetUpdateInfo an index which is too
-                    // big. Because the main thread is not aware of the size
-                    // change until we call UpdateContent.
-                    if (info.index >= info.size) {
-                        info.index = INDEX_NONE;
-                    }
-                }
-                if (info.index != INDEX_NONE) {
-                    info.item = mSource.getSubMediaSet(info.index);
-                    if (info.item == null) continue;
-                    info.cover = info.item.getCoverMediaItem();
-                    info.totalCount = info.item.getTotalMediaItemCount();
-                }
-                executeAndWait(new UpdateContent(info));
-            }
-            updateLoading(false);
-        }
-
-        public synchronized void notifyDirty() {
-            mDirty = true;
-            notifyAll();
-        }
-
-        public synchronized void terminate() {
-            mActive = false;
-            notifyAll();
-        }
-    }
-}
-
-
diff --git a/src/com/android/gallery3d/app/AlbumSetPage.java b/src/com/android/gallery3d/app/AlbumSetPage.java
deleted file mode 100644
index dd9d8ec..0000000
--- a/src/com/android/gallery3d/app/AlbumSetPage.java
+++ /dev/null
@@ -1,764 +0,0 @@
-/*
- * Copyright (C) 2010 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.gallery3d.app;
-
-import android.app.Activity;
-import android.content.Context;
-import android.content.Intent;
-import android.graphics.Rect;
-import android.os.Bundle;
-import android.os.Handler;
-import android.os.Message;
-import android.view.HapticFeedbackConstants;
-import android.view.Menu;
-import android.view.MenuInflater;
-import android.view.MenuItem;
-import android.view.View;
-import android.view.View.OnClickListener;
-import android.widget.Button;
-import android.widget.RelativeLayout;
-import android.widget.Toast;
-
-import com.android.gallery3d.R;
-import com.android.gallery3d.common.Utils;
-import com.android.gallery3d.data.DataManager;
-import com.android.gallery3d.data.MediaDetails;
-import com.android.gallery3d.data.MediaItem;
-import com.android.gallery3d.data.MediaObject;
-import com.android.gallery3d.data.MediaSet;
-import com.android.gallery3d.data.Path;
-import com.android.gallery3d.glrenderer.FadeTexture;
-import com.android.gallery3d.glrenderer.GLCanvas;
-import com.android.gallery3d.picasasource.PicasaSource;
-import com.android.gallery3d.settings.GallerySettings;
-import com.android.gallery3d.ui.ActionModeHandler;
-import com.android.gallery3d.ui.ActionModeHandler.ActionModeListener;
-import com.android.gallery3d.ui.AlbumSetSlotRenderer;
-import com.android.gallery3d.ui.DetailsHelper;
-import com.android.gallery3d.ui.DetailsHelper.CloseListener;
-import com.android.gallery3d.ui.GLRoot;
-import com.android.gallery3d.ui.GLView;
-import com.android.gallery3d.ui.SelectionManager;
-import com.android.gallery3d.ui.SlotView;
-import com.android.gallery3d.ui.SynchronizedHandler;
-import com.android.gallery3d.util.Future;
-import com.android.gallery3d.util.GalleryUtils;
-import com.android.gallery3d.util.HelpUtils;
-
-import java.lang.ref.WeakReference;
-import java.util.ArrayList;
-
-public class AlbumSetPage extends ActivityState implements
-        SelectionManager.SelectionListener, GalleryActionBar.ClusterRunner,
-        EyePosition.EyePositionListener, MediaSet.SyncListener {
-    @SuppressWarnings("unused")
-    private static final String TAG = "AlbumSetPage";
-
-    private static final int MSG_PICK_ALBUM = 1;
-
-    public static final String KEY_MEDIA_PATH = "media-path";
-    public static final String KEY_SET_TITLE = "set-title";
-    public static final String KEY_SET_SUBTITLE = "set-subtitle";
-    public static final String KEY_SELECTED_CLUSTER_TYPE = "selected-cluster";
-
-    private static final int DATA_CACHE_SIZE = 256;
-    private static final int REQUEST_DO_ANIMATION = 1;
-
-    private static final int BIT_LOADING_RELOAD = 1;
-    private static final int BIT_LOADING_SYNC = 2;
-
-    private boolean mIsActive = false;
-    private SlotView mSlotView;
-    private AlbumSetSlotRenderer mAlbumSetView;
-    private Config.AlbumSetPage mConfig;
-
-    private MediaSet mMediaSet;
-    private String mTitle;
-    private String mSubtitle;
-    private boolean mShowClusterMenu;
-    private GalleryActionBar mActionBar;
-    private int mSelectedAction;
-
-    protected SelectionManager mSelectionManager;
-    private AlbumSetDataLoader mAlbumSetDataAdapter;
-
-    private boolean mGetContent;
-    private boolean mGetAlbum;
-    private ActionModeHandler mActionModeHandler;
-    private DetailsHelper mDetailsHelper;
-    private MyDetailsSource mDetailsSource;
-    private boolean mShowDetails;
-    private EyePosition mEyePosition;
-    private Handler mHandler;
-
-    // The eyes' position of the user, the origin is at the center of the
-    // device and the unit is in pixels.
-    private float mX;
-    private float mY;
-    private float mZ;
-
-    private Future<Integer> mSyncTask = null;
-
-    private int mLoadingBits = 0;
-    private boolean mInitialSynced = false;
-
-    private Button mCameraButton;
-    private boolean mShowedEmptyToastForSelf = false;
-
-    @Override
-    protected int getBackgroundColorId() {
-        return R.color.albumset_background;
-    }
-
-    private final GLView mRootPane = new GLView() {
-        private final float mMatrix[] = new float[16];
-
-        @Override
-        protected void onLayout(
-                boolean changed, int left, int top, int right, int bottom) {
-            mEyePosition.resetPosition();
-
-            int slotViewTop = mActionBar.getHeight() + mConfig.paddingTop;
-            int slotViewBottom = bottom - top - mConfig.paddingBottom;
-            int slotViewRight = right - left;
-
-            if (mShowDetails) {
-                mDetailsHelper.layout(left, slotViewTop, right, bottom);
-            } else {
-                mAlbumSetView.setHighlightItemPath(null);
-            }
-
-            mSlotView.layout(0, slotViewTop, slotViewRight, slotViewBottom);
-        }
-
-        @Override
-        protected void render(GLCanvas canvas) {
-            canvas.save(GLCanvas.SAVE_FLAG_MATRIX);
-            GalleryUtils.setViewPointMatrix(mMatrix,
-                    getWidth() / 2 + mX, getHeight() / 2 + mY, mZ);
-            canvas.multiplyMatrix(mMatrix, 0);
-            super.render(canvas);
-            canvas.restore();
-        }
-    };
-
-    @Override
-    public void onEyePositionChanged(float x, float y, float z) {
-        mRootPane.lockRendering();
-        mX = x;
-        mY = y;
-        mZ = z;
-        mRootPane.unlockRendering();
-        mRootPane.invalidate();
-    }
-
-    @Override
-    public void onBackPressed() {
-        if (mShowDetails) {
-            hideDetails();
-        } else if (mSelectionManager.inSelectionMode()) {
-            mSelectionManager.leaveSelectionMode();
-        } else {
-            super.onBackPressed();
-        }
-    }
-
-    private void getSlotCenter(int slotIndex, int center[]) {
-        Rect offset = new Rect();
-        mRootPane.getBoundsOf(mSlotView, offset);
-        Rect r = mSlotView.getSlotRect(slotIndex);
-        int scrollX = mSlotView.getScrollX();
-        int scrollY = mSlotView.getScrollY();
-        center[0] = offset.left + (r.left + r.right) / 2 - scrollX;
-        center[1] = offset.top + (r.top + r.bottom) / 2 - scrollY;
-    }
-
-    public void onSingleTapUp(int slotIndex) {
-        if (!mIsActive) return;
-
-        if (mSelectionManager.inSelectionMode()) {
-            MediaSet targetSet = mAlbumSetDataAdapter.getMediaSet(slotIndex);
-            if (targetSet == null) return; // Content is dirty, we shall reload soon
-            mSelectionManager.toggle(targetSet.getPath());
-            mSlotView.invalidate();
-        } else {
-            // Show pressed-up animation for the single-tap.
-            mAlbumSetView.setPressedIndex(slotIndex);
-            mAlbumSetView.setPressedUp();
-            mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG_PICK_ALBUM, slotIndex, 0),
-                    FadeTexture.DURATION);
-        }
-    }
-
-    private static boolean albumShouldOpenInFilmstrip(MediaSet album) {
-        int itemCount = album.getMediaItemCount();
-        ArrayList<MediaItem> list = (itemCount == 1) ? album.getMediaItem(0, 1) : null;
-        // open in film strip only if there's one item in the album and the item exists
-        return (list != null && !list.isEmpty());
-    }
-
-    WeakReference<Toast> mEmptyAlbumToast = null;
-
-    private void showEmptyAlbumToast(int toastLength) {
-        Toast toast;
-        if (mEmptyAlbumToast != null) {
-            toast = mEmptyAlbumToast.get();
-            if (toast != null) {
-                toast.show();
-                return;
-            }
-        }
-        toast = Toast.makeText(mActivity, R.string.empty_album, toastLength);
-        mEmptyAlbumToast = new WeakReference<Toast>(toast);
-        toast.show();
-    }
-
-    private void hideEmptyAlbumToast() {
-        if (mEmptyAlbumToast != null) {
-            Toast toast = mEmptyAlbumToast.get();
-            if (toast != null) toast.cancel();
-        }
-    }
-
-    private void pickAlbum(int slotIndex) {
-        if (!mIsActive) return;
-
-        MediaSet targetSet = mAlbumSetDataAdapter.getMediaSet(slotIndex);
-        if (targetSet == null) return; // Content is dirty, we shall reload soon
-        if (targetSet.getTotalMediaItemCount() == 0) {
-            showEmptyAlbumToast(Toast.LENGTH_SHORT);
-            return;
-        }
-        hideEmptyAlbumToast();
-
-        String mediaPath = targetSet.getPath().toString();
-
-        Bundle data = new Bundle(getData());
-        int[] center = new int[2];
-        getSlotCenter(slotIndex, center);
-        data.putIntArray(AlbumPage.KEY_SET_CENTER, center);
-        if (mGetAlbum && targetSet.isLeafAlbum()) {
-            Activity activity = mActivity;
-            Intent result = new Intent()
-                    .putExtra(AlbumPicker.KEY_ALBUM_PATH, targetSet.getPath().toString());
-            activity.setResult(Activity.RESULT_OK, result);
-            activity.finish();
-        } else if (targetSet.getSubMediaSetCount() > 0) {
-            data.putString(AlbumSetPage.KEY_MEDIA_PATH, mediaPath);
-            mActivity.getStateManager().startStateForResult(
-                    AlbumSetPage.class, REQUEST_DO_ANIMATION, data);
-        } else {
-            if (!mGetContent && albumShouldOpenInFilmstrip(targetSet)) {
-                data.putParcelable(PhotoPage.KEY_OPEN_ANIMATION_RECT,
-                        mSlotView.getSlotRect(slotIndex, mRootPane));
-                data.putInt(PhotoPage.KEY_INDEX_HINT, 0);
-                data.putString(PhotoPage.KEY_MEDIA_SET_PATH,
-                        mediaPath);
-                data.putBoolean(PhotoPage.KEY_START_IN_FILMSTRIP, true);
-                data.putBoolean(PhotoPage.KEY_IN_CAMERA_ROLL, targetSet.isCameraRoll());
-                mActivity.getStateManager().startStateForResult(
-                        FilmstripPage.class, AlbumPage.REQUEST_PHOTO, data);
-                return;
-            }
-            data.putString(AlbumPage.KEY_MEDIA_PATH, mediaPath);
-
-            // We only show cluster menu in the first AlbumPage in stack
-            boolean inAlbum = mActivity.getStateManager().hasStateClass(AlbumPage.class);
-            data.putBoolean(AlbumPage.KEY_SHOW_CLUSTER_MENU, !inAlbum);
-            mActivity.getStateManager().startStateForResult(
-                    AlbumPage.class, REQUEST_DO_ANIMATION, data);
-        }
-    }
-
-    private void onDown(int index) {
-        mAlbumSetView.setPressedIndex(index);
-    }
-
-    private void onUp(boolean followedByLongPress) {
-        if (followedByLongPress) {
-            // Avoid showing press-up animations for long-press.
-            mAlbumSetView.setPressedIndex(-1);
-        } else {
-            mAlbumSetView.setPressedUp();
-        }
-    }
-
-    public void onLongTap(int slotIndex) {
-        if (mGetContent || mGetAlbum) return;
-        MediaSet set = mAlbumSetDataAdapter.getMediaSet(slotIndex);
-        if (set == null) return;
-        mSelectionManager.setAutoLeaveSelectionMode(true);
-        mSelectionManager.toggle(set.getPath());
-        mSlotView.invalidate();
-    }
-
-    @Override
-    public void doCluster(int clusterType) {
-        String basePath = mMediaSet.getPath().toString();
-        String newPath = FilterUtils.switchClusterPath(basePath, clusterType);
-        Bundle data = new Bundle(getData());
-        data.putString(AlbumSetPage.KEY_MEDIA_PATH, newPath);
-        data.putInt(KEY_SELECTED_CLUSTER_TYPE, clusterType);
-        mActivity.getStateManager().switchState(this, AlbumSetPage.class, data);
-    }
-
-    @Override
-    public void onCreate(Bundle data, Bundle restoreState) {
-        super.onCreate(data, restoreState);
-        initializeViews();
-        initializeData(data);
-        Context context = mActivity.getAndroidContext();
-        mGetContent = data.getBoolean(Gallery.KEY_GET_CONTENT, false);
-        mGetAlbum = data.getBoolean(Gallery.KEY_GET_ALBUM, false);
-        mTitle = data.getString(AlbumSetPage.KEY_SET_TITLE);
-        mSubtitle = data.getString(AlbumSetPage.KEY_SET_SUBTITLE);
-        mEyePosition = new EyePosition(context, this);
-        mDetailsSource = new MyDetailsSource();
-        mActionBar = mActivity.getGalleryActionBar();
-        mSelectedAction = data.getInt(AlbumSetPage.KEY_SELECTED_CLUSTER_TYPE,
-                FilterUtils.CLUSTER_BY_ALBUM);
-
-        mHandler = new SynchronizedHandler(mActivity.getGLRoot()) {
-            @Override
-            public void handleMessage(Message message) {
-                switch (message.what) {
-                    case MSG_PICK_ALBUM: {
-                        pickAlbum(message.arg1);
-                        break;
-                    }
-                    default: throw new AssertionError(message.what);
-                }
-            }
-        };
-    }
-
-    @Override
-    public void onDestroy() {
-        super.onDestroy();
-        cleanupCameraButton();
-        mActionModeHandler.destroy();
-    }
-
-    private boolean setupCameraButton() {
-        if (!GalleryUtils.isCameraAvailable(mActivity)) return false;
-        RelativeLayout galleryRoot = (RelativeLayout) ((Activity) mActivity)
-                .findViewById(R.id.gallery_root);
-        if (galleryRoot == null) return false;
-
-        mCameraButton = new Button(mActivity);
-        mCameraButton.setText(R.string.camera_label);
-        mCameraButton.setCompoundDrawablesWithIntrinsicBounds(0, R.drawable.frame_overlay_gallery_camera, 0, 0);
-        mCameraButton.setOnClickListener(new OnClickListener() {
-            @Override
-            public void onClick(View arg0) {
-                GalleryUtils.startCameraActivity(mActivity);
-            }
-        });
-        RelativeLayout.LayoutParams lp = new RelativeLayout.LayoutParams(
-                RelativeLayout.LayoutParams.WRAP_CONTENT,
-                RelativeLayout.LayoutParams.WRAP_CONTENT);
-        lp.addRule(RelativeLayout.CENTER_IN_PARENT);
-        galleryRoot.addView(mCameraButton, lp);
-        return true;
-    }
-
-    private void cleanupCameraButton() {
-        if (mCameraButton == null) return;
-        RelativeLayout galleryRoot = (RelativeLayout) ((Activity) mActivity)
-                .findViewById(R.id.gallery_root);
-        if (galleryRoot == null) return;
-        galleryRoot.removeView(mCameraButton);
-        mCameraButton = null;
-    }
-
-    private void showCameraButton() {
-        if (mCameraButton == null && !setupCameraButton()) return;
-        mCameraButton.setVisibility(View.VISIBLE);
-    }
-
-    private void hideCameraButton() {
-        if (mCameraButton == null) return;
-        mCameraButton.setVisibility(View.GONE);
-    }
-
-    private void clearLoadingBit(int loadingBit) {
-        mLoadingBits &= ~loadingBit;
-        if (mLoadingBits == 0 && mIsActive) {
-            if (mAlbumSetDataAdapter.size() == 0) {
-                // If this is not the top of the gallery folder hierarchy,
-                // tell the parent AlbumSetPage instance to handle displaying
-                // the empty album toast, otherwise show it within this
-                // instance
-                if (mActivity.getStateManager().getStateCount() > 1) {
-                    Intent result = new Intent();
-                    result.putExtra(AlbumPage.KEY_EMPTY_ALBUM, true);
-                    setStateResult(Activity.RESULT_OK, result);
-                    mActivity.getStateManager().finishState(this);
-                } else {
-                    mShowedEmptyToastForSelf = true;
-                    showEmptyAlbumToast(Toast.LENGTH_LONG);
-                    mSlotView.invalidate();
-                    showCameraButton();
-                }
-                return;
-            }
-        }
-        // Hide the empty album toast if we are in the root instance of
-        // AlbumSetPage and the album is no longer empty (for instance,
-        // after a sync is completed and web albums have been synced)
-        if (mShowedEmptyToastForSelf) {
-            mShowedEmptyToastForSelf = false;
-            hideEmptyAlbumToast();
-            hideCameraButton();
-        }
-    }
-
-    private void setLoadingBit(int loadingBit) {
-        mLoadingBits |= loadingBit;
-    }
-
-    @Override
-    public void onPause() {
-        super.onPause();
-        mIsActive = false;
-        mAlbumSetDataAdapter.pause();
-        mAlbumSetView.pause();
-        mActionModeHandler.pause();
-        mEyePosition.pause();
-        DetailsHelper.pause();
-        // Call disableClusterMenu to avoid receiving callback after paused.
-        // Don't hide menu here otherwise the list menu will disappear earlier than
-        // the action bar, which is janky and unwanted behavior.
-        mActionBar.disableClusterMenu(false);
-        if (mSyncTask != null) {
-            mSyncTask.cancel();
-            mSyncTask = null;
-            clearLoadingBit(BIT_LOADING_SYNC);
-        }
-    }
-
-    @Override
-    public void onResume() {
-        super.onResume();
-        mIsActive = true;
-        setContentPane(mRootPane);
-
-        // Set the reload bit here to prevent it exit this page in clearLoadingBit().
-        setLoadingBit(BIT_LOADING_RELOAD);
-        mAlbumSetDataAdapter.resume();
-
-        mAlbumSetView.resume();
-        mEyePosition.resume();
-        mActionModeHandler.resume();
-        if (mShowClusterMenu) {
-            mActionBar.enableClusterMenu(mSelectedAction, this);
-        }
-        if (!mInitialSynced) {
-            setLoadingBit(BIT_LOADING_SYNC);
-            mSyncTask = mMediaSet.requestSync(AlbumSetPage.this);
-        }
-    }
-
-    private void initializeData(Bundle data) {
-        String mediaPath = data.getString(AlbumSetPage.KEY_MEDIA_PATH);
-        mMediaSet = mActivity.getDataManager().getMediaSet(mediaPath);
-        mSelectionManager.setSourceMediaSet(mMediaSet);
-        mAlbumSetDataAdapter = new AlbumSetDataLoader(
-                mActivity, mMediaSet, DATA_CACHE_SIZE);
-        mAlbumSetDataAdapter.setLoadingListener(new MyLoadingListener());
-        mAlbumSetView.setModel(mAlbumSetDataAdapter);
-    }
-
-    private void initializeViews() {
-        mSelectionManager = new SelectionManager(mActivity, true);
-        mSelectionManager.setSelectionListener(this);
-
-        mConfig = Config.AlbumSetPage.get(mActivity);
-        mSlotView = new SlotView(mActivity, mConfig.slotViewSpec);
-        mAlbumSetView = new AlbumSetSlotRenderer(
-                mActivity, mSelectionManager, mSlotView, mConfig.labelSpec,
-                mConfig.placeholderColor);
-        mSlotView.setSlotRenderer(mAlbumSetView);
-        mSlotView.setListener(new SlotView.SimpleListener() {
-            @Override
-            public void onDown(int index) {
-                AlbumSetPage.this.onDown(index);
-            }
-
-            @Override
-            public void onUp(boolean followedByLongPress) {
-                AlbumSetPage.this.onUp(followedByLongPress);
-            }
-
-            @Override
-            public void onSingleTapUp(int slotIndex) {
-                AlbumSetPage.this.onSingleTapUp(slotIndex);
-            }
-
-            @Override
-            public void onLongTap(int slotIndex) {
-                AlbumSetPage.this.onLongTap(slotIndex);
-            }
-        });
-
-        mActionModeHandler = new ActionModeHandler(mActivity, mSelectionManager);
-        mActionModeHandler.setActionModeListener(new ActionModeListener() {
-            @Override
-            public boolean onActionItemClicked(MenuItem item) {
-                return onItemSelected(item);
-            }
-        });
-        mRootPane.addComponent(mSlotView);
-    }
-
-    @Override
-    protected boolean onCreateActionBar(Menu menu) {
-        Activity activity = mActivity;
-        final boolean inAlbum = mActivity.getStateManager().hasStateClass(AlbumPage.class);
-        MenuInflater inflater = getSupportMenuInflater();
-
-        if (mGetContent) {
-            inflater.inflate(R.menu.pickup, menu);
-            int typeBits = mData.getInt(
-                    Gallery.KEY_TYPE_BITS, DataManager.INCLUDE_IMAGE);
-            mActionBar.setTitle(GalleryUtils.getSelectionModePrompt(typeBits));
-        } else  if (mGetAlbum) {
-            inflater.inflate(R.menu.pickup, menu);
-            mActionBar.setTitle(R.string.select_album);
-        } else {
-            inflater.inflate(R.menu.albumset, menu);
-            boolean wasShowingClusterMenu = mShowClusterMenu;
-            mShowClusterMenu = !inAlbum;
-            boolean selectAlbums = !inAlbum &&
-                    mActionBar.getClusterTypeAction() == FilterUtils.CLUSTER_BY_ALBUM;
-            MenuItem selectItem = menu.findItem(R.id.action_select);
-            selectItem.setTitle(activity.getString(
-                    selectAlbums ? R.string.select_album : R.string.select_group));
-
-            MenuItem cameraItem = menu.findItem(R.id.action_camera);
-            cameraItem.setVisible(GalleryUtils.isCameraAvailable(activity));
-
-            FilterUtils.setupMenuItems(mActionBar, mMediaSet.getPath(), false);
-
-            Intent helpIntent = HelpUtils.getHelpIntent(activity);
-
-            MenuItem helpItem = menu.findItem(R.id.action_general_help);
-            helpItem.setVisible(helpIntent != null);
-            if (helpIntent != null) helpItem.setIntent(helpIntent);
-
-            mActionBar.setTitle(mTitle);
-            mActionBar.setSubtitle(mSubtitle);
-            if (mShowClusterMenu != wasShowingClusterMenu) {
-                if (mShowClusterMenu) {
-                    mActionBar.enableClusterMenu(mSelectedAction, this);
-                } else {
-                    mActionBar.disableClusterMenu(true);
-                }
-            }
-        }
-        return true;
-    }
-
-    @Override
-    protected boolean onItemSelected(MenuItem item) {
-        Activity activity = mActivity;
-        switch (item.getItemId()) {
-            case R.id.action_cancel:
-                activity.setResult(Activity.RESULT_CANCELED);
-                activity.finish();
-                return true;
-            case R.id.action_select:
-                mSelectionManager.setAutoLeaveSelectionMode(false);
-                mSelectionManager.enterSelectionMode();
-                return true;
-            case R.id.action_details:
-                if (mAlbumSetDataAdapter.size() != 0) {
-                    if (mShowDetails) {
-                        hideDetails();
-                    } else {
-                        showDetails();
-                    }
-                } else {
-                    Toast.makeText(activity,
-                            activity.getText(R.string.no_albums_alert),
-                            Toast.LENGTH_SHORT).show();
-                }
-                return true;
-            case R.id.action_camera: {
-                GalleryUtils.startCameraActivity(activity);
-                return true;
-            }
-            case R.id.action_manage_offline: {
-                Bundle data = new Bundle();
-                String mediaPath = mActivity.getDataManager().getTopSetPath(
-                    DataManager.INCLUDE_ALL);
-                data.putString(AlbumSetPage.KEY_MEDIA_PATH, mediaPath);
-                mActivity.getStateManager().startState(ManageCachePage.class, data);
-                return true;
-            }
-            case R.id.action_sync_picasa_albums: {
-                PicasaSource.requestSync(activity);
-                return true;
-            }
-            case R.id.action_settings: {
-                activity.startActivity(new Intent(activity, GallerySettings.class));
-                return true;
-            }
-            default:
-                return false;
-        }
-    }
-
-    @Override
-    protected void onStateResult(int requestCode, int resultCode, Intent data) {
-        if (data != null && data.getBooleanExtra(AlbumPage.KEY_EMPTY_ALBUM, false)) {
-            showEmptyAlbumToast(Toast.LENGTH_SHORT);
-        }
-        switch (requestCode) {
-            case REQUEST_DO_ANIMATION: {
-                mSlotView.startRisingAnimation();
-            }
-        }
-    }
-
-    private String getSelectedString() {
-        int count = mSelectionManager.getSelectedCount();
-        int action = mActionBar.getClusterTypeAction();
-        int string = action == FilterUtils.CLUSTER_BY_ALBUM
-                ? R.plurals.number_of_albums_selected
-                : R.plurals.number_of_groups_selected;
-        String format = mActivity.getResources().getQuantityString(string, count);
-        return String.format(format, count);
-    }
-
-    @Override
-    public void onSelectionModeChange(int mode) {
-        switch (mode) {
-            case SelectionManager.ENTER_SELECTION_MODE: {
-                mActionBar.disableClusterMenu(true);
-                mActionModeHandler.startActionMode();
-                performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
-                break;
-            }
-            case SelectionManager.LEAVE_SELECTION_MODE: {
-                mActionModeHandler.finishActionMode();
-                if (mShowClusterMenu) {
-                    mActionBar.enableClusterMenu(mSelectedAction, this);
-                }
-                mRootPane.invalidate();
-                break;
-            }
-            case SelectionManager.SELECT_ALL_MODE: {
-                mActionModeHandler.updateSupportedOperation();
-                mRootPane.invalidate();
-                break;
-            }
-        }
-    }
-
-    @Override
-    public void onSelectionChange(Path path, boolean selected) {
-        mActionModeHandler.setTitle(getSelectedString());
-        mActionModeHandler.updateSupportedOperation(path, selected);
-    }
-
-    private void hideDetails() {
-        mShowDetails = false;
-        mDetailsHelper.hide();
-        mAlbumSetView.setHighlightItemPath(null);
-        mSlotView.invalidate();
-    }
-
-    private void showDetails() {
-        mShowDetails = true;
-        if (mDetailsHelper == null) {
-            mDetailsHelper = new DetailsHelper(mActivity, mRootPane, mDetailsSource);
-            mDetailsHelper.setCloseListener(new CloseListener() {
-                @Override
-                public void onClose() {
-                    hideDetails();
-                }
-            });
-        }
-        mDetailsHelper.show();
-    }
-
-    @Override
-    public void onSyncDone(final MediaSet mediaSet, final int resultCode) {
-        if (resultCode == MediaSet.SYNC_RESULT_ERROR) {
-            Log.d(TAG, "onSyncDone: " + Utils.maskDebugInfo(mediaSet.getName()) + " result="
-                    + resultCode);
-        }
-        ((Activity) mActivity).runOnUiThread(new Runnable() {
-            @Override
-            public void run() {
-                GLRoot root = mActivity.getGLRoot();
-                root.lockRenderThread();
-                try {
-                    if (resultCode == MediaSet.SYNC_RESULT_SUCCESS) {
-                        mInitialSynced = true;
-                    }
-                    clearLoadingBit(BIT_LOADING_SYNC);
-                    if (resultCode == MediaSet.SYNC_RESULT_ERROR && mIsActive) {
-                        Log.w(TAG, "failed to load album set");
-                    }
-                } finally {
-                    root.unlockRenderThread();
-                }
-            }
-        });
-    }
-
-    private class MyLoadingListener implements LoadingListener {
-        @Override
-        public void onLoadingStarted() {
-            setLoadingBit(BIT_LOADING_RELOAD);
-        }
-
-        @Override
-        public void onLoadingFinished(boolean loadingFailed) {
-            clearLoadingBit(BIT_LOADING_RELOAD);
-        }
-    }
-
-    private class MyDetailsSource implements DetailsHelper.DetailsSource {
-        private int mIndex;
-
-        @Override
-        public int size() {
-            return mAlbumSetDataAdapter.size();
-        }
-
-        @Override
-        public int setIndex() {
-            Path id = mSelectionManager.getSelected(false).get(0);
-            mIndex = mAlbumSetDataAdapter.findSet(id);
-            return mIndex;
-        }
-
-        @Override
-        public MediaDetails getDetails() {
-            MediaObject item = mAlbumSetDataAdapter.getMediaSet(mIndex);
-            if (item != null) {
-                mAlbumSetView.setHighlightItemPath(item.getPath());
-                return item.getDetails();
-            } else {
-                return null;
-            }
-        }
-    }
-}
diff --git a/src/com/android/gallery3d/app/AppBridge.java b/src/com/android/gallery3d/app/AppBridge.java
deleted file mode 100644
index ee55fa6..0000000
--- a/src/com/android/gallery3d/app/AppBridge.java
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * 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.gallery3d.app;
-
-import android.graphics.Rect;
-import android.os.Parcel;
-import android.os.Parcelable;
-
-import com.android.gallery3d.ui.ScreenNail;
-
-// This is the bridge to connect a PhotoPage to the external environment.
-public abstract class AppBridge implements Parcelable {
-    @Override
-    public int describeContents() {
-        return 0;
-    }
-
-    @Override
-    public void writeToParcel(Parcel dest, int flags) {
-    }
-
-    //////////////////////////////////////////////////////////////////////////
-    //  These are requests sent from PhotoPage to the app
-    //////////////////////////////////////////////////////////////////////////
-
-    public abstract boolean isPanorama();
-    public abstract boolean isStaticCamera();
-    public abstract ScreenNail attachScreenNail();
-    public abstract void detachScreenNail();
-
-    // Return true if the tap is consumed.
-    public abstract boolean onSingleTapUp(int x, int y);
-
-    // This is used to notify that the screen nail will be drawn in full screen
-    // or not in next draw() call.
-    public abstract void onFullScreenChanged(boolean full);
-
-    //////////////////////////////////////////////////////////////////////////
-    //  These are requests send from app to PhotoPage
-    //////////////////////////////////////////////////////////////////////////
-
-    public interface Server {
-        // Set the camera frame relative to GLRootView.
-        public void setCameraRelativeFrame(Rect frame);
-        // Switch to the previous or next picture using the capture animation.
-        // The offset is -1 to switch to the previous picture, 1 to switch to
-        // the next picture.
-        public boolean switchWithCaptureAnimation(int offset);
-        // Enable or disable the swiping gestures (the default is enabled).
-        public void setSwipingEnabled(boolean enabled);
-        // Notify that the ScreenNail is changed.
-        public void notifyScreenNailChanged();
-        // Add a new media item to the secure album.
-        public void addSecureAlbumItem(boolean isVideo, int id);
-    }
-
-    // If server is null, the services are not available.
-    public abstract void setServer(Server server);
-}
diff --git a/src/com/android/gallery3d/app/BatchService.java b/src/com/android/gallery3d/app/BatchService.java
deleted file mode 100644
index 564001d..0000000
--- a/src/com/android/gallery3d/app/BatchService.java
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * 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.gallery3d.app;
-
-import android.app.Service;
-import android.content.Intent;
-import android.os.Binder;
-import android.os.IBinder;
-
-import com.android.gallery3d.util.ThreadPool;
-
-public class BatchService extends Service {
-
-    public class LocalBinder extends Binder {
-        BatchService getService() {
-            return BatchService.this;
-        }
-    }
-
-    private final IBinder mBinder = new LocalBinder();
-    private ThreadPool mThreadPool = new ThreadPool(1, 1);
-
-    @Override
-    public IBinder onBind(Intent intent) {
-        return mBinder;
-    }
-
-    // The threadpool returned by getThreadPool must have only 1 thread
-    // running at a time, as MenuExecutor (atrociously) depends on this
-    // guarantee for synchronization.
-    public ThreadPool getThreadPool() {
-        return mThreadPool;
-    }
-}
diff --git a/src/com/android/gallery3d/app/CommonControllerOverlay.java b/src/com/android/gallery3d/app/CommonControllerOverlay.java
deleted file mode 100644
index 9adb4e7..0000000
--- a/src/com/android/gallery3d/app/CommonControllerOverlay.java
+++ /dev/null
@@ -1,346 +0,0 @@
-/*
- * 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.gallery3d.app;
-
-import android.content.Context;
-import android.content.res.Resources;
-import android.graphics.Rect;
-import android.view.Gravity;
-import android.view.KeyEvent;
-import android.view.MotionEvent;
-import android.view.View;
-import android.view.View.OnClickListener;
-import android.widget.FrameLayout;
-import android.widget.ImageView;
-import android.widget.ImageView.ScaleType;
-import android.widget.LinearLayout;
-import android.widget.ProgressBar;
-import android.widget.RelativeLayout;
-import android.widget.TextView;
-
-import com.android.gallery3d.R;
-
-/**
- * The common playback controller for the Movie Player or Video Trimming.
- */
-public abstract class CommonControllerOverlay extends FrameLayout implements
-        ControllerOverlay,
-        OnClickListener,
-        TimeBar.Listener {
-
-    protected enum State {
-        PLAYING,
-        PAUSED,
-        ENDED,
-        ERROR,
-        LOADING
-    }
-
-    private static final float ERROR_MESSAGE_RELATIVE_PADDING = 1.0f / 6;
-
-    protected Listener mListener;
-
-    protected final View mBackground;
-    protected TimeBar mTimeBar;
-
-    protected View mMainView;
-    protected final LinearLayout mLoadingView;
-    protected final TextView mErrorView;
-    protected final ImageView mPlayPauseReplayView;
-
-    protected State mState;
-
-    protected boolean mCanReplay = true;
-
-    public void setSeekable(boolean canSeek) {
-        mTimeBar.setSeekable(canSeek);
-    }
-
-    public CommonControllerOverlay(Context context) {
-        super(context);
-
-        mState = State.LOADING;
-        // TODO: Move the following layout code into xml file.
-        LayoutParams wrapContent =
-                new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
-        LayoutParams matchParent =
-                new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
-
-        mBackground = new View(context);
-        mBackground.setBackgroundColor(context.getResources().getColor(R.color.darker_transparent));
-        addView(mBackground, matchParent);
-
-        // Depending on the usage, the timeBar can show a single scrubber, or
-        // multiple ones for trimming.
-        createTimeBar(context);
-        addView(mTimeBar, wrapContent);
-        mTimeBar.setContentDescription(
-                context.getResources().getString(R.string.accessibility_time_bar));
-        mLoadingView = new LinearLayout(context);
-        mLoadingView.setOrientation(LinearLayout.VERTICAL);
-        mLoadingView.setGravity(Gravity.CENTER_HORIZONTAL);
-        ProgressBar spinner = new ProgressBar(context);
-        spinner.setIndeterminate(true);
-        mLoadingView.addView(spinner, wrapContent);
-        TextView loadingText = createOverlayTextView(context);
-        loadingText.setText(R.string.loading_video);
-        mLoadingView.addView(loadingText, wrapContent);
-        addView(mLoadingView, wrapContent);
-
-        mPlayPauseReplayView = new ImageView(context);
-        mPlayPauseReplayView.setImageResource(R.drawable.ic_vidcontrol_play);
-        mPlayPauseReplayView.setContentDescription(
-                context.getResources().getString(R.string.accessibility_play_video));
-        mPlayPauseReplayView.setBackgroundResource(R.drawable.bg_vidcontrol);
-        mPlayPauseReplayView.setScaleType(ScaleType.CENTER);
-        mPlayPauseReplayView.setFocusable(true);
-        mPlayPauseReplayView.setClickable(true);
-        mPlayPauseReplayView.setOnClickListener(this);
-        addView(mPlayPauseReplayView, wrapContent);
-
-        mErrorView = createOverlayTextView(context);
-        addView(mErrorView, matchParent);
-
-        RelativeLayout.LayoutParams params =
-                new RelativeLayout.LayoutParams(
-                        LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
-        setLayoutParams(params);
-        hide();
-    }
-
-    abstract protected void createTimeBar(Context context);
-
-    private TextView createOverlayTextView(Context context) {
-        TextView view = new TextView(context);
-        view.setGravity(Gravity.CENTER);
-        view.setTextColor(0xFFFFFFFF);
-        view.setPadding(0, 15, 0, 15);
-        return view;
-    }
-
-    @Override
-    public void setListener(Listener listener) {
-        this.mListener = listener;
-    }
-
-    @Override
-    public void setCanReplay(boolean canReplay) {
-        this.mCanReplay = canReplay;
-    }
-
-    @Override
-    public View getView() {
-        return this;
-    }
-
-    @Override
-    public void showPlaying() {
-        mState = State.PLAYING;
-        showMainView(mPlayPauseReplayView);
-    }
-
-    @Override
-    public void showPaused() {
-        mState = State.PAUSED;
-        showMainView(mPlayPauseReplayView);
-    }
-
-    @Override
-    public void showEnded() {
-        mState = State.ENDED;
-        if (mCanReplay) showMainView(mPlayPauseReplayView);
-    }
-
-    @Override
-    public void showLoading() {
-        mState = State.LOADING;
-        showMainView(mLoadingView);
-    }
-
-    @Override
-    public void showErrorMessage(String message) {
-        mState = State.ERROR;
-        int padding = (int) (getMeasuredWidth() * ERROR_MESSAGE_RELATIVE_PADDING);
-        mErrorView.setPadding(
-                padding, mErrorView.getPaddingTop(), padding, mErrorView.getPaddingBottom());
-        mErrorView.setText(message);
-        showMainView(mErrorView);
-    }
-
-    @Override
-    public void setTimes(int currentTime, int totalTime,
-            int trimStartTime, int trimEndTime) {
-        mTimeBar.setTime(currentTime, totalTime, trimStartTime, trimEndTime);
-    }
-
-    public void hide() {
-        mPlayPauseReplayView.setVisibility(View.INVISIBLE);
-        mLoadingView.setVisibility(View.INVISIBLE);
-        mBackground.setVisibility(View.INVISIBLE);
-        mTimeBar.setVisibility(View.INVISIBLE);
-        setVisibility(View.INVISIBLE);
-        setFocusable(true);
-        requestFocus();
-    }
-
-    private void showMainView(View view) {
-        mMainView = view;
-        mErrorView.setVisibility(mMainView == mErrorView ? View.VISIBLE : View.INVISIBLE);
-        mLoadingView.setVisibility(mMainView == mLoadingView ? View.VISIBLE : View.INVISIBLE);
-        mPlayPauseReplayView.setVisibility(
-                mMainView == mPlayPauseReplayView ? View.VISIBLE : View.INVISIBLE);
-        show();
-    }
-
-    @Override
-    public void show() {
-        updateViews();
-        setVisibility(View.VISIBLE);
-        setFocusable(false);
-    }
-
-    @Override
-    public void onClick(View view) {
-        if (mListener != null) {
-            if (view == mPlayPauseReplayView) {
-                if (mState == State.ENDED) {
-                    if (mCanReplay) {
-                        mListener.onReplay();
-                    }
-                } else if (mState == State.PAUSED || mState == State.PLAYING) {
-                    mListener.onPlayPause();
-                }
-            }
-        }
-    }
-
-    @Override
-    public boolean onKeyDown(int keyCode, KeyEvent event) {
-        return super.onKeyDown(keyCode, event);
-    }
-
-    @Override
-    public boolean onTouchEvent(MotionEvent event) {
-        if (super.onTouchEvent(event)) {
-            return true;
-        }
-        return false;
-    }
-
-    // The paddings of 4 sides which covered by system components. E.g.
-    // +-----------------+\
-    // | Action Bar | insets.top
-    // +-----------------+/
-    // | |
-    // | Content Area | insets.right = insets.left = 0
-    // | |
-    // +-----------------+\
-    // | Navigation Bar | insets.bottom
-    // +-----------------+/
-    // Please see View.fitSystemWindows() for more details.
-    private final Rect mWindowInsets = new Rect();
-
-    @Override
-    protected boolean fitSystemWindows(Rect insets) {
-        // We don't set the paddings of this View, otherwise,
-        // the content will get cropped outside window
-        mWindowInsets.set(insets);
-        return true;
-    }
-
-    @Override
-    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
-        Rect insets = mWindowInsets;
-        int pl = insets.left; // the left paddings
-        int pr = insets.right;
-        int pt = insets.top;
-        int pb = insets.bottom;
-
-        int h = bottom - top;
-        int w = right - left;
-        boolean error = mErrorView.getVisibility() == View.VISIBLE;
-
-        int y = h - pb;
-        // Put both TimeBar and Background just above the bottom system
-        // component.
-        // But extend the background to the width of the screen, since we don't
-        // care if it will be covered by a system component and it looks better.
-        mBackground.layout(0, y - mTimeBar.getBarHeight(), w, y);
-        mTimeBar.layout(pl, y - mTimeBar.getPreferredHeight(), w - pr, y);
-
-        // Put the play/pause/next/ previous button in the center of the screen
-        layoutCenteredView(mPlayPauseReplayView, 0, 0, w, h);
-
-        if (mMainView != null) {
-            layoutCenteredView(mMainView, 0, 0, w, h);
-        }
-    }
-
-    private void layoutCenteredView(View view, int l, int t, int r, int b) {
-        int cw = view.getMeasuredWidth();
-        int ch = view.getMeasuredHeight();
-        int cl = (r - l - cw) / 2;
-        int ct = (b - t - ch) / 2;
-        view.layout(cl, ct, cl + cw, ct + ch);
-    }
-
-    @Override
-    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
-        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
-        measureChildren(widthMeasureSpec, heightMeasureSpec);
-    }
-
-    protected void updateViews() {
-        mBackground.setVisibility(View.VISIBLE);
-        mTimeBar.setVisibility(View.VISIBLE);
-        Resources resources = getContext().getResources();
-        int imageResource = R.drawable.ic_vidcontrol_reload;
-        String contentDescription = resources.getString(R.string.accessibility_reload_video);
-        if (mState == State.PAUSED) {
-            imageResource = R.drawable.ic_vidcontrol_play;
-            contentDescription = resources.getString(R.string.accessibility_play_video);
-        } else if (mState == State.PLAYING) {
-            imageResource = R.drawable.ic_vidcontrol_pause;
-            contentDescription = resources.getString(R.string.accessibility_pause_video);
-        }
-
-        mPlayPauseReplayView.setImageResource(imageResource);
-        mPlayPauseReplayView.setContentDescription(contentDescription);
-        mPlayPauseReplayView.setVisibility(
-                (mState != State.LOADING && mState != State.ERROR &&
-                !(mState == State.ENDED && !mCanReplay))
-                ? View.VISIBLE : View.GONE);
-        requestLayout();
-    }
-
-    // TimeBar listener
-
-    @Override
-    public void onScrubbingStart() {
-        mListener.onSeekStart();
-    }
-
-    @Override
-    public void onScrubbingMove(int time) {
-        mListener.onSeekMove(time);
-    }
-
-    @Override
-    public void onScrubbingEnd(int time, int trimStartTime, int trimEndTime) {
-        mListener.onSeekEnd(time, trimStartTime, trimEndTime);
-    }
-}
diff --git a/src/com/android/gallery3d/app/Config.java b/src/com/android/gallery3d/app/Config.java
deleted file mode 100644
index 7183acc..0000000
--- a/src/com/android/gallery3d/app/Config.java
+++ /dev/null
@@ -1,127 +0,0 @@
-/*
- * Copyright (C) 2010 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.gallery3d.app;
-
-import android.content.Context;
-import android.content.res.Resources;
-
-import com.android.gallery3d.R;
-import com.android.gallery3d.ui.AlbumSetSlotRenderer;
-import com.android.gallery3d.ui.SlotView;
-
-final class Config {
-    public static class AlbumSetPage {
-        private static AlbumSetPage sInstance;
-
-        public SlotView.Spec slotViewSpec;
-        public AlbumSetSlotRenderer.LabelSpec labelSpec;
-        public int paddingTop;
-        public int paddingBottom;
-        public int placeholderColor;
-
-        public static synchronized AlbumSetPage get(Context context) {
-            if (sInstance == null) {
-                sInstance = new AlbumSetPage(context);
-            }
-            return sInstance;
-        }
-
-        private AlbumSetPage(Context context) {
-            Resources r = context.getResources();
-
-            placeholderColor = r.getColor(R.color.albumset_placeholder);
-
-            slotViewSpec = new SlotView.Spec();
-            slotViewSpec.rowsLand = r.getInteger(R.integer.albumset_rows_land);
-            slotViewSpec.rowsPort = r.getInteger(R.integer.albumset_rows_port);
-            slotViewSpec.slotGap = r.getDimensionPixelSize(R.dimen.albumset_slot_gap);
-            slotViewSpec.slotHeightAdditional = 0;
-
-            paddingTop = r.getDimensionPixelSize(R.dimen.albumset_padding_top);
-            paddingBottom = r.getDimensionPixelSize(R.dimen.albumset_padding_bottom);
-
-            labelSpec = new AlbumSetSlotRenderer.LabelSpec();
-            labelSpec.labelBackgroundHeight = r.getDimensionPixelSize(
-                    R.dimen.albumset_label_background_height);
-            labelSpec.titleOffset = r.getDimensionPixelSize(
-                    R.dimen.albumset_title_offset);
-            labelSpec.countOffset = r.getDimensionPixelSize(
-                    R.dimen.albumset_count_offset);
-            labelSpec.titleFontSize = r.getDimensionPixelSize(
-                    R.dimen.albumset_title_font_size);
-            labelSpec.countFontSize = r.getDimensionPixelSize(
-                    R.dimen.albumset_count_font_size);
-            labelSpec.leftMargin = r.getDimensionPixelSize(
-                    R.dimen.albumset_left_margin);
-            labelSpec.titleRightMargin = r.getDimensionPixelSize(
-                    R.dimen.albumset_title_right_margin);
-            labelSpec.iconSize = r.getDimensionPixelSize(
-                    R.dimen.albumset_icon_size);
-            labelSpec.backgroundColor = r.getColor(
-                    R.color.albumset_label_background);
-            labelSpec.titleColor = r.getColor(R.color.albumset_label_title);
-            labelSpec.countColor = r.getColor(R.color.albumset_label_count);
-        }
-    }
-
-    public static class AlbumPage {
-        private static AlbumPage sInstance;
-
-        public SlotView.Spec slotViewSpec;
-        public int placeholderColor;
-
-        public static synchronized AlbumPage get(Context context) {
-            if (sInstance == null) {
-                sInstance = new AlbumPage(context);
-            }
-            return sInstance;
-        }
-
-        private AlbumPage(Context context) {
-            Resources r = context.getResources();
-
-            placeholderColor = r.getColor(R.color.album_placeholder);
-
-            slotViewSpec = new SlotView.Spec();
-            slotViewSpec.rowsLand = r.getInteger(R.integer.album_rows_land);
-            slotViewSpec.rowsPort = r.getInteger(R.integer.album_rows_port);
-            slotViewSpec.slotGap = r.getDimensionPixelSize(R.dimen.album_slot_gap);
-        }
-    }
-
-    public static class ManageCachePage extends AlbumSetPage {
-        private static ManageCachePage sInstance;
-
-        public final int cachePinSize;
-        public final int cachePinMargin;
-
-        public static synchronized ManageCachePage get(Context context) {
-            if (sInstance == null) {
-                sInstance = new ManageCachePage(context);
-            }
-            return sInstance;
-        }
-
-        public ManageCachePage(Context context) {
-            super(context);
-            Resources r = context.getResources();
-            cachePinSize = r.getDimensionPixelSize(R.dimen.cache_pin_size);
-            cachePinMargin = r.getDimensionPixelSize(R.dimen.cache_pin_margin);
-        }
-    }
-}
-
diff --git a/src/com/android/gallery3d/app/ControllerOverlay.java b/src/com/android/gallery3d/app/ControllerOverlay.java
deleted file mode 100644
index 078f59e..0000000
--- a/src/com/android/gallery3d/app/ControllerOverlay.java
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Copyright (C) 2011 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.gallery3d.app;
-
-import android.view.View;
-
-public interface ControllerOverlay {
-
-  interface Listener {
-    void onPlayPause();
-    void onSeekStart();
-    void onSeekMove(int time);
-    void onSeekEnd(int time, int trimStartTime, int trimEndTime);
-    void onShown();
-    void onHidden();
-    void onReplay();
-  }
-
-  void setListener(Listener listener);
-
-  void setCanReplay(boolean canReplay);
-
-  /**
-   * @return The overlay view that should be added to the player.
-   */
-  View getView();
-
-  void show();
-
-  void showPlaying();
-
-  void showPaused();
-
-  void showEnded();
-
-  void showLoading();
-
-  void showErrorMessage(String message);
-
-  void setTimes(int currentTime, int totalTime,
-          int trimStartTime, int trimEndTime);
-}
diff --git a/src/com/android/gallery3d/app/DialogPicker.java b/src/com/android/gallery3d/app/DialogPicker.java
deleted file mode 100644
index 7ca86e5..0000000
--- a/src/com/android/gallery3d/app/DialogPicker.java
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright (C) 2010 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.gallery3d.app;
-
-import android.content.Intent;
-import android.os.Bundle;
-
-import com.android.gallery3d.util.GalleryUtils;
-
-public class DialogPicker extends PickerActivity {
-
-    @Override
-    public void onCreate(Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-
-        int typeBits = GalleryUtils.determineTypeBits(this, getIntent());
-        setTitle(GalleryUtils.getSelectionModePrompt(typeBits));
-        Intent intent = getIntent();
-        Bundle extras = intent.getExtras();
-        Bundle data = extras == null ? new Bundle() : new Bundle(extras);
-
-        data.putBoolean(Gallery.KEY_GET_CONTENT, true);
-        data.putString(AlbumSetPage.KEY_MEDIA_PATH,
-                getDataManager().getTopSetPath(typeBits));
-        getStateManager().startState(AlbumSetPage.class, data);
-    }
-}
diff --git a/src/com/android/gallery3d/app/EyePosition.java b/src/com/android/gallery3d/app/EyePosition.java
deleted file mode 100644
index d99d97b..0000000
--- a/src/com/android/gallery3d/app/EyePosition.java
+++ /dev/null
@@ -1,226 +0,0 @@
-/*
- * Copyright (C) 2010 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.gallery3d.app;
-
-import android.content.Context;
-import android.hardware.Sensor;
-import android.hardware.SensorEvent;
-import android.hardware.SensorEventListener;
-import android.hardware.SensorManager;
-import android.os.SystemClock;
-import android.util.FloatMath;
-import android.view.Display;
-import android.view.Surface;
-import android.view.WindowManager;
-
-import com.android.gallery3d.common.Utils;
-import com.android.gallery3d.util.GalleryUtils;
-
-public class EyePosition {
-    @SuppressWarnings("unused")
-    private static final String TAG = "EyePosition";
-
-    public interface EyePositionListener {
-        public void onEyePositionChanged(float x, float y, float z);
-    }
-
-    private static final float GYROSCOPE_THRESHOLD = 0.15f;
-    private static final float GYROSCOPE_LIMIT = 10f;
-    private static final int GYROSCOPE_SETTLE_DOWN = 15;
-    private static final float GYROSCOPE_RESTORE_FACTOR = 0.995f;
-
-    private static final float USER_ANGEL = (float) Math.toRadians(10);
-    private static final float USER_ANGEL_COS = FloatMath.cos(USER_ANGEL);
-    private static final float USER_ANGEL_SIN = FloatMath.sin(USER_ANGEL);
-    private static final float MAX_VIEW_RANGE = (float) 0.5;
-    private static final int NOT_STARTED = -1;
-
-    private static final float USER_DISTANCE_METER = 0.3f;
-
-    private Context mContext;
-    private EyePositionListener mListener;
-    private Display mDisplay;
-    // The eyes' position of the user, the origin is at the center of the
-    // device and the unit is in pixels.
-    private float mX;
-    private float mY;
-    private float mZ;
-
-    private final float mUserDistance; // in pixel
-    private final float mLimit;
-    private long mStartTime = NOT_STARTED;
-    private Sensor mSensor;
-    private PositionListener mPositionListener = new PositionListener();
-
-    private int mGyroscopeCountdown = 0;
-
-    public EyePosition(Context context, EyePositionListener listener) {
-        mContext = context;
-        mListener = listener;
-        mUserDistance = GalleryUtils.meterToPixel(USER_DISTANCE_METER);
-        mLimit = mUserDistance * MAX_VIEW_RANGE;
-
-        WindowManager wManager = (WindowManager) mContext
-                .getSystemService(Context.WINDOW_SERVICE);
-        mDisplay = wManager.getDefaultDisplay();
-
-        // The 3D effect where the photo albums fan out in 3D based on angle
-        // of device tilt is currently disabled.
-/*
-        SensorManager sManager = (SensorManager) mContext
-                .getSystemService(Context.SENSOR_SERVICE);
-        mSensor = sManager.getDefaultSensor(Sensor.TYPE_GYROSCOPE);
-        if (mSensor == null) {
-            Log.w(TAG, "no gyroscope, use accelerometer instead");
-            mSensor = sManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
-        }
-        if (mSensor == null) {
-            Log.w(TAG, "no sensor available");
-        }
-*/
-    }
-
-    public void resetPosition() {
-        mStartTime = NOT_STARTED;
-        mX = mY = 0;
-        mZ = -mUserDistance;
-        mListener.onEyePositionChanged(mX, mY, mZ);
-    }
-
-    /*
-     * We assume the user is at the following position
-     *
-     *              /|\  user's eye
-     *               |   /
-     *   -G(gravity) |  /
-     *               |_/
-     *             / |/_____\ -Y (-y direction of device)
-     *     user angel
-     */
-    private void onAccelerometerChanged(float gx, float gy, float gz) {
-
-        float x = gx, y = gy, z = gz;
-
-        switch (mDisplay.getRotation()) {
-            case Surface.ROTATION_90: x = -gy; y= gx; break;
-            case Surface.ROTATION_180: x = -gx; y = -gy; break;
-            case Surface.ROTATION_270: x = gy; y = -gx; break;
-        }
-
-        float temp = x * x + y * y + z * z;
-        float t = -y /temp;
-
-        float tx = t * x;
-        float ty = -1 + t * y;
-        float tz = t * z;
-
-        float length = FloatMath.sqrt(tx * tx + ty * ty + tz * tz);
-        float glength = FloatMath.sqrt(temp);
-
-        mX = Utils.clamp((x * USER_ANGEL_COS / glength
-                + tx * USER_ANGEL_SIN / length) * mUserDistance,
-                -mLimit, mLimit);
-        mY = -Utils.clamp((y * USER_ANGEL_COS / glength
-                + ty * USER_ANGEL_SIN / length) * mUserDistance,
-                -mLimit, mLimit);
-        mZ = -FloatMath.sqrt(
-                mUserDistance * mUserDistance - mX * mX - mY * mY);
-        mListener.onEyePositionChanged(mX, mY, mZ);
-    }
-
-    private void onGyroscopeChanged(float gx, float gy, float gz) {
-        long now = SystemClock.elapsedRealtime();
-        float distance = (gx > 0 ? gx : -gx) + (gy > 0 ? gy : - gy);
-        if (distance < GYROSCOPE_THRESHOLD
-                || distance > GYROSCOPE_LIMIT || mGyroscopeCountdown > 0) {
-            --mGyroscopeCountdown;
-            mStartTime = now;
-            float limit = mUserDistance / 20f;
-            if (mX > limit || mX < -limit || mY > limit || mY < -limit) {
-                mX *= GYROSCOPE_RESTORE_FACTOR;
-                mY *= GYROSCOPE_RESTORE_FACTOR;
-                mZ = (float) -Math.sqrt(
-                        mUserDistance * mUserDistance - mX * mX - mY * mY);
-                mListener.onEyePositionChanged(mX, mY, mZ);
-            }
-            return;
-        }
-
-        float t = (now - mStartTime) / 1000f * mUserDistance * (-mZ);
-        mStartTime = now;
-
-        float x = -gy, y = -gx;
-        switch (mDisplay.getRotation()) {
-            case Surface.ROTATION_90: x = -gx; y= gy; break;
-            case Surface.ROTATION_180: x = gy; y = gx; break;
-            case Surface.ROTATION_270: x = gx; y = -gy; break;
-        }
-
-        mX = Utils.clamp((float) (mX + x * t / Math.hypot(mZ, mX)),
-                -mLimit, mLimit) * GYROSCOPE_RESTORE_FACTOR;
-        mY = Utils.clamp((float) (mY + y * t / Math.hypot(mZ, mY)),
-                -mLimit, mLimit) * GYROSCOPE_RESTORE_FACTOR;
-
-        mZ = -FloatMath.sqrt(
-                mUserDistance * mUserDistance - mX * mX - mY * mY);
-        mListener.onEyePositionChanged(mX, mY, mZ);
-    }
-
-    private class PositionListener implements SensorEventListener {
-        @Override
-        public void onAccuracyChanged(Sensor sensor, int accuracy) {
-        }
-
-        @Override
-        public void onSensorChanged(SensorEvent event) {
-            switch (event.sensor.getType()) {
-                case Sensor.TYPE_GYROSCOPE: {
-                    onGyroscopeChanged(
-                            event.values[0], event.values[1], event.values[2]);
-                    break;
-                }
-                case Sensor.TYPE_ACCELEROMETER: {
-                    onAccelerometerChanged(
-                            event.values[0], event.values[1], event.values[2]);
-                }
-            }
-        }
-    }
-
-    public void pause() {
-        if (mSensor != null) {
-            SensorManager sManager = (SensorManager) mContext
-                    .getSystemService(Context.SENSOR_SERVICE);
-            sManager.unregisterListener(mPositionListener);
-        }
-    }
-
-    public void resume() {
-        if (mSensor != null) {
-            SensorManager sManager = (SensorManager) mContext
-                    .getSystemService(Context.SENSOR_SERVICE);
-            sManager.registerListener(mPositionListener,
-                    mSensor, SensorManager.SENSOR_DELAY_GAME);
-        }
-
-        mStartTime = NOT_STARTED;
-        mGyroscopeCountdown = GYROSCOPE_SETTLE_DOWN;
-        mX = mY = 0;
-        mZ = -mUserDistance;
-        mListener.onEyePositionChanged(mX, mY, mZ);
-    }
-}
diff --git a/src/com/android/gallery3d/app/FilmstripPage.java b/src/com/android/gallery3d/app/FilmstripPage.java
deleted file mode 100644
index a9726cd..0000000
--- a/src/com/android/gallery3d/app/FilmstripPage.java
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- * 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.gallery3d.app;
-
-public class FilmstripPage extends PhotoPage {
-
-}
diff --git a/src/com/android/gallery3d/app/FilterUtils.java b/src/com/android/gallery3d/app/FilterUtils.java
deleted file mode 100644
index bc28a9c..0000000
--- a/src/com/android/gallery3d/app/FilterUtils.java
+++ /dev/null
@@ -1,257 +0,0 @@
-/*
- * Copyright (C) 2010 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.gallery3d.app;
-
-import com.android.gallery3d.R;
-import com.android.gallery3d.data.MediaObject;
-import com.android.gallery3d.data.Path;
-
-// This class handles filtering and clustering.
-//
-// We allow at most only one filter operation at a time (Currently it
-// doesn't make sense to use more than one). Also each clustering operation
-// can be applied at most once. In addition, there is one more constraint
-// ("fixed set constraint") described below.
-//
-// A clustered album (not including album set) and its base sets are fixed.
-// For example,
-//
-// /cluster/{base_set}/time/7
-//
-// This set and all sets inside base_set (recursively) are fixed because
-// 1. We can not change this set to use another clustering condition (like
-//    changing "time" to "location").
-// 2. Neither can we change any set in the base_set.
-// The reason is in both cases the 7th set may not exist in the new clustering.
-// ---------------------
-// newPath operation: create a new path based on a source path and put an extra
-// condition on top of it:
-//
-// T = newFilterPath(S, filterType);
-// T = newClusterPath(S, clusterType);
-//
-// Similar functions can be used to replace the current condition (if there is one).
-//
-// T = switchFilterPath(S, filterType);
-// T = switchClusterPath(S, clusterType);
-//
-// For all fixed set in the path defined above, if some clusterType and
-// filterType are already used, they cannot not be used as parameter for these
-// functions. setupMenuItems() makes sure those types cannot be selected.
-//
-public class FilterUtils {
-    @SuppressWarnings("unused")
-    private static final String TAG = "FilterUtils";
-
-    public static final int CLUSTER_BY_ALBUM = 1;
-    public static final int CLUSTER_BY_TIME = 2;
-    public static final int CLUSTER_BY_LOCATION = 4;
-    public static final int CLUSTER_BY_TAG = 8;
-    public static final int CLUSTER_BY_SIZE = 16;
-    public static final int CLUSTER_BY_FACE = 32;
-
-    public static final int FILTER_IMAGE_ONLY = 1;
-    public static final int FILTER_VIDEO_ONLY = 2;
-    public static final int FILTER_ALL = 4;
-
-    // These are indices of the return values of getAppliedFilters().
-    // The _F suffix means "fixed".
-    private static final int CLUSTER_TYPE = 0;
-    private static final int FILTER_TYPE = 1;
-    private static final int CLUSTER_TYPE_F = 2;
-    private static final int FILTER_TYPE_F = 3;
-    private static final int CLUSTER_CURRENT_TYPE = 4;
-    private static final int FILTER_CURRENT_TYPE = 5;
-
-    public static void setupMenuItems(GalleryActionBar actionBar, Path path, boolean inAlbum) {
-        int[] result = new int[6];
-        getAppliedFilters(path, result);
-        int ctype = result[CLUSTER_TYPE];
-        int ftype = result[FILTER_TYPE];
-        int ftypef = result[FILTER_TYPE_F];
-        int ccurrent = result[CLUSTER_CURRENT_TYPE];
-        int fcurrent = result[FILTER_CURRENT_TYPE];
-
-        setMenuItemApplied(actionBar, CLUSTER_BY_TIME,
-                (ctype & CLUSTER_BY_TIME) != 0, (ccurrent & CLUSTER_BY_TIME) != 0);
-        setMenuItemApplied(actionBar, CLUSTER_BY_LOCATION,
-                (ctype & CLUSTER_BY_LOCATION) != 0, (ccurrent & CLUSTER_BY_LOCATION) != 0);
-        setMenuItemApplied(actionBar, CLUSTER_BY_TAG,
-                (ctype & CLUSTER_BY_TAG) != 0, (ccurrent & CLUSTER_BY_TAG) != 0);
-        setMenuItemApplied(actionBar, CLUSTER_BY_FACE,
-                (ctype & CLUSTER_BY_FACE) != 0, (ccurrent & CLUSTER_BY_FACE) != 0);
-
-        actionBar.setClusterItemVisibility(CLUSTER_BY_ALBUM, !inAlbum || ctype == 0);
-
-        setMenuItemApplied(actionBar, R.id.action_cluster_album, ctype == 0,
-                ccurrent == 0);
-
-        // A filtering is available if it's not applied, and the old filtering
-        // (if any) is not fixed.
-        setMenuItemAppliedEnabled(actionBar, R.string.show_images_only,
-                (ftype & FILTER_IMAGE_ONLY) != 0,
-                (ftype & FILTER_IMAGE_ONLY) == 0 && ftypef == 0,
-                (fcurrent & FILTER_IMAGE_ONLY) != 0);
-        setMenuItemAppliedEnabled(actionBar, R.string.show_videos_only,
-                (ftype & FILTER_VIDEO_ONLY) != 0,
-                (ftype & FILTER_VIDEO_ONLY) == 0 && ftypef == 0,
-                (fcurrent & FILTER_VIDEO_ONLY) != 0);
-        setMenuItemAppliedEnabled(actionBar, R.string.show_all,
-                ftype == 0, ftype != 0 && ftypef == 0, fcurrent == 0);
-    }
-
-    // Gets the filters applied in the path.
-    private static void getAppliedFilters(Path path, int[] result) {
-        getAppliedFilters(path, result, false);
-    }
-
-    private static void getAppliedFilters(Path path, int[] result, boolean underCluster) {
-        String[] segments = path.split();
-        // Recurse into sub media sets.
-        for (int i = 0; i < segments.length; i++) {
-            if (segments[i].startsWith("{")) {
-                String[] sets = Path.splitSequence(segments[i]);
-                for (int j = 0; j < sets.length; j++) {
-                    Path sub = Path.fromString(sets[j]);
-                    getAppliedFilters(sub, result, underCluster);
-                }
-            }
-        }
-
-        // update current selection
-        if (segments[0].equals("cluster")) {
-            // if this is a clustered album, set underCluster to true.
-            if (segments.length == 4) {
-                underCluster = true;
-            }
-
-            int ctype = toClusterType(segments[2]);
-            result[CLUSTER_TYPE] |= ctype;
-            result[CLUSTER_CURRENT_TYPE] = ctype;
-            if (underCluster) {
-                result[CLUSTER_TYPE_F] |= ctype;
-            }
-        }
-    }
-
-    private static int toClusterType(String s) {
-        if (s.equals("time")) {
-            return CLUSTER_BY_TIME;
-        } else if (s.equals("location")) {
-            return CLUSTER_BY_LOCATION;
-        } else if (s.equals("tag")) {
-            return CLUSTER_BY_TAG;
-        } else if (s.equals("size")) {
-            return CLUSTER_BY_SIZE;
-        } else if (s.equals("face")) {
-            return CLUSTER_BY_FACE;
-        }
-        return 0;
-    }
-
-    private static void setMenuItemApplied(
-            GalleryActionBar model, int id, boolean applied, boolean updateTitle) {
-        model.setClusterItemEnabled(id, !applied);
-    }
-
-    private static void setMenuItemAppliedEnabled(GalleryActionBar model, int id, boolean applied, boolean enabled, boolean updateTitle) {
-        model.setClusterItemEnabled(id, enabled);
-    }
-
-    // Add a specified filter to the path.
-    public static String newFilterPath(String base, int filterType) {
-        int mediaType;
-        switch (filterType) {
-            case FILTER_IMAGE_ONLY:
-                mediaType = MediaObject.MEDIA_TYPE_IMAGE;
-                break;
-            case FILTER_VIDEO_ONLY:
-                mediaType = MediaObject.MEDIA_TYPE_VIDEO;
-                break;
-            default:  /* FILTER_ALL */
-                return base;
-        }
-
-        return "/filter/mediatype/" + mediaType + "/{" + base + "}";
-    }
-
-    // Add a specified clustering to the path.
-    public static String newClusterPath(String base, int clusterType) {
-        String kind;
-        switch (clusterType) {
-            case CLUSTER_BY_TIME:
-                kind = "time";
-                break;
-            case CLUSTER_BY_LOCATION:
-                kind = "location";
-                break;
-            case CLUSTER_BY_TAG:
-                kind = "tag";
-                break;
-            case CLUSTER_BY_SIZE:
-                kind = "size";
-                break;
-            case CLUSTER_BY_FACE:
-                kind = "face";
-                break;
-            default: /* CLUSTER_BY_ALBUM */
-                return base;
-        }
-
-        return "/cluster/{" + base + "}/" + kind;
-    }
-
-    // Change the topmost clustering to the specified type.
-    public static String switchClusterPath(String base, int clusterType) {
-        return newClusterPath(removeOneClusterFromPath(base), clusterType);
-    }
-
-    // Remove the topmost clustering (if any) from the path.
-    private static String removeOneClusterFromPath(String base) {
-        boolean[] done = new boolean[1];
-        return removeOneClusterFromPath(base, done);
-    }
-
-    private static String removeOneClusterFromPath(String base, boolean[] done) {
-        if (done[0]) return base;
-
-        String[] segments = Path.split(base);
-        if (segments[0].equals("cluster")) {
-            done[0] = true;
-            return Path.splitSequence(segments[1])[0];
-        }
-
-        StringBuilder sb = new StringBuilder();
-        for (int i = 0; i < segments.length; i++) {
-            sb.append("/");
-            if (segments[i].startsWith("{")) {
-                sb.append("{");
-                String[] sets = Path.splitSequence(segments[i]);
-                for (int j = 0; j < sets.length; j++) {
-                    if (j > 0) {
-                        sb.append(",");
-                    }
-                    sb.append(removeOneClusterFromPath(sets[j], done));
-                }
-                sb.append("}");
-            } else {
-                sb.append(segments[i]);
-            }
-        }
-        return sb.toString();
-    }
-}
diff --git a/src/com/android/gallery3d/app/Gallery.java b/src/com/android/gallery3d/app/Gallery.java
deleted file mode 100644
index baef56b..0000000
--- a/src/com/android/gallery3d/app/Gallery.java
+++ /dev/null
@@ -1,274 +0,0 @@
-/*
- * Copyright (C) 2009 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.gallery3d.app;
-
-import android.app.Dialog;
-import android.content.ContentResolver;
-import android.content.DialogInterface;
-import android.content.DialogInterface.OnCancelListener;
-import android.content.Intent;
-import android.net.Uri;
-import android.os.Bundle;
-import android.view.InputDevice;
-import android.view.MotionEvent;
-import android.view.View;
-import android.view.Window;
-import android.view.WindowManager;
-import android.widget.Toast;
-
-import com.android.gallery3d.R;
-import com.android.gallery3d.common.Utils;
-import com.android.gallery3d.data.DataManager;
-import com.android.gallery3d.data.MediaItem;
-import com.android.gallery3d.data.MediaSet;
-import com.android.gallery3d.data.Path;
-import com.android.gallery3d.picasasource.PicasaSource;
-import com.android.gallery3d.util.GalleryUtils;
-
-public final class Gallery extends AbstractGalleryActivity implements OnCancelListener {
-    public static final String EXTRA_SLIDESHOW = "slideshow";
-    public static final String EXTRA_DREAM = "dream";
-    public static final String EXTRA_CROP = "crop";
-
-    public static final String ACTION_REVIEW = "com.android.camera.action.REVIEW";
-    public static final String KEY_GET_CONTENT = "get-content";
-    public static final String KEY_GET_ALBUM = "get-album";
-    public static final String KEY_TYPE_BITS = "type-bits";
-    public static final String KEY_MEDIA_TYPES = "mediaTypes";
-    public static final String KEY_DISMISS_KEYGUARD = "dismiss-keyguard";
-
-    private static final String TAG = "Gallery";
-    private Dialog mVersionCheckDialog;
-
-    @Override
-    protected void onCreate(Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-        requestWindowFeature(Window.FEATURE_ACTION_BAR);
-        requestWindowFeature(Window.FEATURE_ACTION_BAR_OVERLAY);
-
-        if (getIntent().getBooleanExtra(KEY_DISMISS_KEYGUARD, false)) {
-            getWindow().addFlags(
-                    WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD);
-        }
-
-        setContentView(R.layout.main);
-
-        if (savedInstanceState != null) {
-            getStateManager().restoreFromState(savedInstanceState);
-        } else {
-            initializeByIntent();
-        }
-    }
-
-    private void initializeByIntent() {
-        Intent intent = getIntent();
-        String action = intent.getAction();
-
-        if (Intent.ACTION_GET_CONTENT.equalsIgnoreCase(action)) {
-            startGetContent(intent);
-        } else if (Intent.ACTION_PICK.equalsIgnoreCase(action)) {
-            // We do NOT really support the PICK intent. Handle it as
-            // the GET_CONTENT. However, we need to translate the type
-            // in the intent here.
-            Log.w(TAG, "action PICK is not supported");
-            String type = Utils.ensureNotNull(intent.getType());
-            if (type.startsWith("vnd.android.cursor.dir/")) {
-                if (type.endsWith("/image")) intent.setType("image/*");
-                if (type.endsWith("/video")) intent.setType("video/*");
-            }
-            startGetContent(intent);
-        } else if (Intent.ACTION_VIEW.equalsIgnoreCase(action)
-                || ACTION_REVIEW.equalsIgnoreCase(action)){
-            startViewAction(intent);
-        } else {
-            startDefaultPage();
-        }
-    }
-
-    public void startDefaultPage() {
-        PicasaSource.showSignInReminder(this);
-        Bundle data = new Bundle();
-        data.putString(AlbumSetPage.KEY_MEDIA_PATH,
-                getDataManager().getTopSetPath(DataManager.INCLUDE_ALL));
-        getStateManager().startState(AlbumSetPage.class, data);
-        mVersionCheckDialog = PicasaSource.getVersionCheckDialog(this);
-        if (mVersionCheckDialog != null) {
-            mVersionCheckDialog.setOnCancelListener(this);
-        }
-    }
-
-    private void startGetContent(Intent intent) {
-        Bundle data = intent.getExtras() != null
-                ? new Bundle(intent.getExtras())
-                : new Bundle();
-        data.putBoolean(KEY_GET_CONTENT, true);
-        int typeBits = GalleryUtils.determineTypeBits(this, intent);
-        data.putInt(KEY_TYPE_BITS, typeBits);
-        data.putString(AlbumSetPage.KEY_MEDIA_PATH,
-                getDataManager().getTopSetPath(typeBits));
-        getStateManager().startState(AlbumSetPage.class, data);
-    }
-
-    private String getContentType(Intent intent) {
-        String type = intent.getType();
-        if (type != null) {
-            return GalleryUtils.MIME_TYPE_PANORAMA360.equals(type)
-                ? MediaItem.MIME_TYPE_JPEG : type;
-        }
-
-        Uri uri = intent.getData();
-        try {
-            return getContentResolver().getType(uri);
-        } catch (Throwable t) {
-            Log.w(TAG, "get type fail", t);
-            return null;
-        }
-    }
-
-    private void startViewAction(Intent intent) {
-        Boolean slideshow = intent.getBooleanExtra(EXTRA_SLIDESHOW, false);
-        if (slideshow) {
-            getActionBar().hide();
-            DataManager manager = getDataManager();
-            Path path = manager.findPathByUri(intent.getData(), intent.getType());
-            if (path == null || manager.getMediaObject(path)
-                    instanceof MediaItem) {
-                path = Path.fromString(
-                        manager.getTopSetPath(DataManager.INCLUDE_IMAGE));
-            }
-            Bundle data = new Bundle();
-            data.putString(SlideshowPage.KEY_SET_PATH, path.toString());
-            data.putBoolean(SlideshowPage.KEY_RANDOM_ORDER, true);
-            data.putBoolean(SlideshowPage.KEY_REPEAT, true);
-            if (intent.getBooleanExtra(EXTRA_DREAM, false)) {
-                data.putBoolean(SlideshowPage.KEY_DREAM, true);
-            }
-            getStateManager().startState(SlideshowPage.class, data);
-        } else {
-            Bundle data = new Bundle();
-            DataManager dm = getDataManager();
-            Uri uri = intent.getData();
-            String contentType = getContentType(intent);
-            if (contentType == null) {
-                Toast.makeText(this,
-                        R.string.no_such_item, Toast.LENGTH_LONG).show();
-                finish();
-                return;
-            }
-            if (uri == null) {
-                int typeBits = GalleryUtils.determineTypeBits(this, intent);
-                data.putInt(KEY_TYPE_BITS, typeBits);
-                data.putString(AlbumSetPage.KEY_MEDIA_PATH,
-                        getDataManager().getTopSetPath(typeBits));
-                getStateManager().startState(AlbumSetPage.class, data);
-            } else if (contentType.startsWith(
-                    ContentResolver.CURSOR_DIR_BASE_TYPE)) {
-                int mediaType = intent.getIntExtra(KEY_MEDIA_TYPES, 0);
-                if (mediaType != 0) {
-                    uri = uri.buildUpon().appendQueryParameter(
-                            KEY_MEDIA_TYPES, String.valueOf(mediaType))
-                            .build();
-                }
-                Path setPath = dm.findPathByUri(uri, null);
-                MediaSet mediaSet = null;
-                if (setPath != null) {
-                    mediaSet = (MediaSet) dm.getMediaObject(setPath);
-                }
-                if (mediaSet != null) {
-                    if (mediaSet.isLeafAlbum()) {
-                        data.putString(AlbumPage.KEY_MEDIA_PATH, setPath.toString());
-                        data.putString(AlbumPage.KEY_PARENT_MEDIA_PATH,
-                                dm.getTopSetPath(DataManager.INCLUDE_ALL));
-                        getStateManager().startState(AlbumPage.class, data);
-                    } else {
-                        data.putString(AlbumSetPage.KEY_MEDIA_PATH, setPath.toString());
-                        getStateManager().startState(AlbumSetPage.class, data);
-                    }
-                } else {
-                    startDefaultPage();
-                }
-            } else {
-                Path itemPath = dm.findPathByUri(uri, contentType);
-                Path albumPath = dm.getDefaultSetOf(itemPath);
-
-                data.putString(PhotoPage.KEY_MEDIA_ITEM_PATH, itemPath.toString());
-
-                // TODO: Make the parameter "SingleItemOnly" public so other
-                //       activities can reference it.
-                boolean singleItemOnly = (albumPath == null)
-                        || intent.getBooleanExtra("SingleItemOnly", false);
-                if (!singleItemOnly) {
-                    data.putString(PhotoPage.KEY_MEDIA_SET_PATH, albumPath.toString());
-                    // when FLAG_ACTIVITY_NEW_TASK is set, (e.g. when intent is fired
-                    // from notification), back button should behave the same as up button
-                    // rather than taking users back to the home screen
-                    if (intent.getBooleanExtra(PhotoPage.KEY_TREAT_BACK_AS_UP, false)
-                            || ((intent.getFlags() & Intent.FLAG_ACTIVITY_NEW_TASK) != 0)) {
-                        data.putBoolean(PhotoPage.KEY_TREAT_BACK_AS_UP, true);
-                    }
-                }
-
-                getStateManager().startState(SinglePhotoPage.class, data);
-            }
-        }
-    }
-
-    @Override
-    protected void onResume() {
-        Utils.assertTrue(getStateManager().getStateCount() > 0);
-        super.onResume();
-        if (mVersionCheckDialog != null) {
-            mVersionCheckDialog.show();
-        }
-    }
-
-    @Override
-    protected void onPause() {
-        super.onPause();
-        if (mVersionCheckDialog != null) {
-            mVersionCheckDialog.dismiss();
-        }
-    }
-
-    @Override
-    public void onCancel(DialogInterface dialog) {
-        if (dialog == mVersionCheckDialog) {
-            mVersionCheckDialog = null;
-        }
-    }
-
-    @Override
-    public boolean onGenericMotionEvent(MotionEvent event) {
-        final boolean isTouchPad = (event.getSource()
-                & InputDevice.SOURCE_CLASS_POSITION) != 0;
-        if (isTouchPad) {
-            float maxX = event.getDevice().getMotionRange(MotionEvent.AXIS_X).getMax();
-            float maxY = event.getDevice().getMotionRange(MotionEvent.AXIS_Y).getMax();
-            View decor = getWindow().getDecorView();
-            float scaleX = decor.getWidth() / maxX;
-            float scaleY = decor.getHeight() / maxY;
-            float x = event.getX() * scaleX;
-            //x = decor.getWidth() - x; // invert x
-            float y = event.getY() * scaleY;
-            //y = decor.getHeight() - y; // invert y
-            MotionEvent touchEvent = MotionEvent.obtain(event.getDownTime(),
-                    event.getEventTime(), event.getAction(), x, y, event.getMetaState());
-            return dispatchTouchEvent(touchEvent);
-        }
-        return super.onGenericMotionEvent(event);
-    }
-}
diff --git a/src/com/android/gallery3d/app/GalleryActionBar.java b/src/com/android/gallery3d/app/GalleryActionBar.java
deleted file mode 100644
index 588f584..0000000
--- a/src/com/android/gallery3d/app/GalleryActionBar.java
+++ /dev/null
@@ -1,438 +0,0 @@
-/*
- * Copyright (C) 2011 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.gallery3d.app;
-
-import android.annotation.TargetApi;
-import android.app.ActionBar;
-import android.app.ActionBar.OnMenuVisibilityListener;
-import android.app.ActionBar.OnNavigationListener;
-import android.app.Activity;
-import android.app.AlertDialog;
-import android.content.Context;
-import android.content.DialogInterface;
-import android.content.Intent;
-import android.content.res.Resources;
-import android.view.LayoutInflater;
-import android.view.Menu;
-import android.view.MenuItem;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.BaseAdapter;
-import android.widget.ShareActionProvider;
-import android.widget.TextView;
-import android.widget.TwoLineListItem;
-
-import com.android.gallery3d.R;
-import com.android.gallery3d.common.ApiHelper;
-
-import java.util.ArrayList;
-
-public class GalleryActionBar implements OnNavigationListener {
-    @SuppressWarnings("unused")
-    private static final String TAG = "GalleryActionBar";
-
-    private ClusterRunner mClusterRunner;
-    private CharSequence[] mTitles;
-    private ArrayList<Integer> mActions;
-    private Context mContext;
-    private LayoutInflater mInflater;
-    private AbstractGalleryActivity mActivity;
-    private ActionBar mActionBar;
-    private int mCurrentIndex;
-    private ClusterAdapter mAdapter = new ClusterAdapter();
-
-    private AlbumModeAdapter mAlbumModeAdapter;
-    private OnAlbumModeSelectedListener mAlbumModeListener;
-    private int mLastAlbumModeSelected;
-    private CharSequence [] mAlbumModes;
-    public static final int ALBUM_FILMSTRIP_MODE_SELECTED = 0;
-    public static final int ALBUM_GRID_MODE_SELECTED = 1;
-
-    public interface ClusterRunner {
-        public void doCluster(int id);
-    }
-
-    public interface OnAlbumModeSelectedListener {
-        public void onAlbumModeSelected(int mode);
-    }
-
-    private static class ActionItem {
-        public int action;
-        public boolean enabled;
-        public boolean visible;
-        public int spinnerTitle;
-        public int dialogTitle;
-        public int clusterBy;
-
-        public ActionItem(int action, boolean applied, boolean enabled, int title,
-                int clusterBy) {
-            this(action, applied, enabled, title, title, clusterBy);
-        }
-
-        public ActionItem(int action, boolean applied, boolean enabled, int spinnerTitle,
-                int dialogTitle, int clusterBy) {
-            this.action = action;
-            this.enabled = enabled;
-            this.spinnerTitle = spinnerTitle;
-            this.dialogTitle = dialogTitle;
-            this.clusterBy = clusterBy;
-            this.visible = true;
-        }
-    }
-
-    private static final ActionItem[] sClusterItems = new ActionItem[] {
-        new ActionItem(FilterUtils.CLUSTER_BY_ALBUM, true, false, R.string.albums,
-                R.string.group_by_album),
-        new ActionItem(FilterUtils.CLUSTER_BY_LOCATION, true, false,
-                R.string.locations, R.string.location, R.string.group_by_location),
-        new ActionItem(FilterUtils.CLUSTER_BY_TIME, true, false, R.string.times,
-                R.string.time, R.string.group_by_time),
-        new ActionItem(FilterUtils.CLUSTER_BY_FACE, true, false, R.string.people,
-                R.string.group_by_faces),
-        new ActionItem(FilterUtils.CLUSTER_BY_TAG, true, false, R.string.tags,
-                R.string.group_by_tags)
-    };
-
-    private class ClusterAdapter extends BaseAdapter {
-
-        @Override
-        public int getCount() {
-            return sClusterItems.length;
-        }
-
-        @Override
-        public Object getItem(int position) {
-            return sClusterItems[position];
-        }
-
-        @Override
-        public long getItemId(int position) {
-            return sClusterItems[position].action;
-        }
-
-        @Override
-        public View getView(int position, View convertView, ViewGroup parent) {
-            if (convertView == null) {
-                convertView = mInflater.inflate(R.layout.action_bar_text,
-                        parent, false);
-            }
-            TextView view = (TextView) convertView;
-            view.setText(sClusterItems[position].spinnerTitle);
-            return convertView;
-        }
-    }
-
-    private class AlbumModeAdapter extends BaseAdapter {
-        @Override
-        public int getCount() {
-            return mAlbumModes.length;
-        }
-
-        @Override
-        public Object getItem(int position) {
-            return mAlbumModes[position];
-        }
-
-        @Override
-        public long getItemId(int position) {
-            return position;
-        }
-
-        @Override
-        public View getView(int position, View convertView, ViewGroup parent) {
-            if (convertView == null) {
-                convertView = mInflater.inflate(R.layout.action_bar_two_line_text,
-                        parent, false);
-            }
-            TwoLineListItem view = (TwoLineListItem) convertView;
-            view.getText1().setText(mActionBar.getTitle());
-            view.getText2().setText((CharSequence) getItem(position));
-            return convertView;
-        }
-
-        @Override
-        public View getDropDownView(int position, View convertView, ViewGroup parent) {
-            if (convertView == null) {
-                convertView = mInflater.inflate(R.layout.action_bar_text,
-                        parent, false);
-            }
-            TextView view = (TextView) convertView;
-            view.setText((CharSequence) getItem(position));
-            return convertView;
-        }
-    }
-
-    public static String getClusterByTypeString(Context context, int type) {
-        for (ActionItem item : sClusterItems) {
-            if (item.action == type) {
-                return context.getString(item.clusterBy);
-            }
-        }
-        return null;
-    }
-
-    public GalleryActionBar(AbstractGalleryActivity activity) {
-        mActionBar = activity.getActionBar();
-        mContext = activity.getAndroidContext();
-        mActivity = activity;
-        mInflater = ((Activity) mActivity).getLayoutInflater();
-        mCurrentIndex = 0;
-    }
-
-    private void createDialogData() {
-        ArrayList<CharSequence> titles = new ArrayList<CharSequence>();
-        mActions = new ArrayList<Integer>();
-        for (ActionItem item : sClusterItems) {
-            if (item.enabled && item.visible) {
-                titles.add(mContext.getString(item.dialogTitle));
-                mActions.add(item.action);
-            }
-        }
-        mTitles = new CharSequence[titles.size()];
-        titles.toArray(mTitles);
-    }
-
-    public int getHeight() {
-        return mActionBar != null ? mActionBar.getHeight() : 0;
-    }
-
-    public void setClusterItemEnabled(int id, boolean enabled) {
-        for (ActionItem item : sClusterItems) {
-            if (item.action == id) {
-                item.enabled = enabled;
-                return;
-            }
-        }
-    }
-
-    public void setClusterItemVisibility(int id, boolean visible) {
-        for (ActionItem item : sClusterItems) {
-            if (item.action == id) {
-                item.visible = visible;
-                return;
-            }
-        }
-    }
-
-    public int getClusterTypeAction() {
-        return sClusterItems[mCurrentIndex].action;
-    }
-
-    public void enableClusterMenu(int action, ClusterRunner runner) {
-        if (mActionBar != null) {
-            // Don't set cluster runner until action bar is ready.
-            mClusterRunner = null;
-            mActionBar.setListNavigationCallbacks(mAdapter, this);
-            mActionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_LIST);
-            setSelectedAction(action);
-            mClusterRunner = runner;
-        }
-    }
-
-    // The only use case not to hideMenu in this method is to ensure
-    // all elements disappear at the same time when exiting gallery.
-    // hideMenu should always be true in all other cases.
-    public void disableClusterMenu(boolean hideMenu) {
-        if (mActionBar != null) {
-            mClusterRunner = null;
-            if (hideMenu) {
-                mActionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_STANDARD);
-            }
-        }
-    }
-
-    public void onConfigurationChanged() {
-        if (mActionBar != null && mAlbumModeListener != null) {
-            OnAlbumModeSelectedListener listener = mAlbumModeListener;
-            enableAlbumModeMenu(mLastAlbumModeSelected, listener);
-        }
-    }
-
-    public void enableAlbumModeMenu(int selected, OnAlbumModeSelectedListener listener) {
-        if (mActionBar != null) {
-            if (mAlbumModeAdapter == null) {
-                // Initialize the album mode options if they haven't been already
-                Resources res = mActivity.getResources();
-                mAlbumModes = new CharSequence[] {
-                        res.getString(R.string.switch_photo_filmstrip),
-                        res.getString(R.string.switch_photo_grid)};
-                mAlbumModeAdapter = new AlbumModeAdapter();
-            }
-            mAlbumModeListener = null;
-            mLastAlbumModeSelected = selected;
-            mActionBar.setListNavigationCallbacks(mAlbumModeAdapter, this);
-            mActionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_LIST);
-            mActionBar.setSelectedNavigationItem(selected);
-            mAlbumModeListener = listener;
-        }
-    }
-
-    public void disableAlbumModeMenu(boolean hideMenu) {
-        if (mActionBar != null) {
-            mAlbumModeListener = null;
-            if (hideMenu) {
-                mActionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_STANDARD);
-            }
-        }
-    }
-
-    public void showClusterDialog(final ClusterRunner clusterRunner) {
-        createDialogData();
-        final ArrayList<Integer> actions = mActions;
-        new AlertDialog.Builder(mContext).setTitle(R.string.group_by).setItems(
-                mTitles, new DialogInterface.OnClickListener() {
-            @Override
-            public void onClick(DialogInterface dialog, int which) {
-                // Need to lock rendering when operations invoked by system UI (main thread) are
-                // modifying slot data used in GL thread for rendering.
-                mActivity.getGLRoot().lockRenderThread();
-                try {
-                    clusterRunner.doCluster(actions.get(which).intValue());
-                } finally {
-                    mActivity.getGLRoot().unlockRenderThread();
-                }
-            }
-        }).create().show();
-    }
-
-    @TargetApi(ApiHelper.VERSION_CODES.ICE_CREAM_SANDWICH)
-    private void setHomeButtonEnabled(boolean enabled) {
-        if (mActionBar != null) mActionBar.setHomeButtonEnabled(enabled);
-    }
-
-    public void setDisplayOptions(boolean displayHomeAsUp, boolean showTitle) {
-        if (mActionBar == null) return;
-        int options = 0;
-        if (displayHomeAsUp) options |= ActionBar.DISPLAY_HOME_AS_UP;
-        if (showTitle) options |= ActionBar.DISPLAY_SHOW_TITLE;
-
-        mActionBar.setDisplayOptions(options,
-                ActionBar.DISPLAY_HOME_AS_UP | ActionBar.DISPLAY_SHOW_TITLE);
-        mActionBar.setHomeButtonEnabled(displayHomeAsUp);
-    }
-
-    public void setTitle(String title) {
-        if (mActionBar != null) mActionBar.setTitle(title);
-    }
-
-    public void setTitle(int titleId) {
-        if (mActionBar != null) {
-            mActionBar.setTitle(mContext.getString(titleId));
-        }
-    }
-
-    public void setSubtitle(String title) {
-        if (mActionBar != null) mActionBar.setSubtitle(title);
-    }
-
-    public void show() {
-        if (mActionBar != null) mActionBar.show();
-    }
-
-    public void hide() {
-        if (mActionBar != null) mActionBar.hide();
-    }
-
-    public void addOnMenuVisibilityListener(OnMenuVisibilityListener listener) {
-        if (mActionBar != null) mActionBar.addOnMenuVisibilityListener(listener);
-    }
-
-    public void removeOnMenuVisibilityListener(OnMenuVisibilityListener listener) {
-        if (mActionBar != null) mActionBar.removeOnMenuVisibilityListener(listener);
-    }
-
-    public boolean setSelectedAction(int type) {
-        if (mActionBar == null) return false;
-
-        for (int i = 0, n = sClusterItems.length; i < n; i++) {
-            ActionItem item = sClusterItems[i];
-            if (item.action == type) {
-                mActionBar.setSelectedNavigationItem(i);
-                mCurrentIndex = i;
-                return true;
-            }
-        }
-        return false;
-    }
-
-    @Override
-    public boolean onNavigationItemSelected(int itemPosition, long itemId) {
-        if (itemPosition != mCurrentIndex && mClusterRunner != null
-                || mAlbumModeListener != null) {
-            // Need to lock rendering when operations invoked by system UI (main thread) are
-            // modifying slot data used in GL thread for rendering.
-            mActivity.getGLRoot().lockRenderThread();
-            try {
-                if (mAlbumModeListener != null) {
-                    mAlbumModeListener.onAlbumModeSelected(itemPosition);
-                } else {
-                    mClusterRunner.doCluster(sClusterItems[itemPosition].action);
-                }
-            } finally {
-                mActivity.getGLRoot().unlockRenderThread();
-            }
-        }
-        return false;
-    }
-
-    private Menu mActionBarMenu;
-    private ShareActionProvider mSharePanoramaActionProvider;
-    private ShareActionProvider mShareActionProvider;
-    private Intent mSharePanoramaIntent;
-    private Intent mShareIntent;
-
-    public void createActionBarMenu(int menuRes, Menu menu) {
-        mActivity.getMenuInflater().inflate(menuRes, menu);
-        mActionBarMenu = menu;
-
-        MenuItem item = menu.findItem(R.id.action_share_panorama);
-        if (item != null) {
-            mSharePanoramaActionProvider = (ShareActionProvider)
-                item.getActionProvider();
-            mSharePanoramaActionProvider
-                .setShareHistoryFileName("panorama_share_history.xml");
-            mSharePanoramaActionProvider.setShareIntent(mSharePanoramaIntent);
-        }
-
-        item = menu.findItem(R.id.action_share);
-        if (item != null) {
-            mShareActionProvider = (ShareActionProvider)
-                item.getActionProvider();
-            mShareActionProvider
-                .setShareHistoryFileName("share_history.xml");
-            mShareActionProvider.setShareIntent(mShareIntent);
-        }
-    }
-
-    public Menu getMenu() {
-        return mActionBarMenu;
-    }
-
-    public void setShareIntents(Intent sharePanoramaIntent, Intent shareIntent,
-        ShareActionProvider.OnShareTargetSelectedListener onShareListener) {
-        mSharePanoramaIntent = sharePanoramaIntent;
-        if (mSharePanoramaActionProvider != null) {
-            mSharePanoramaActionProvider.setShareIntent(sharePanoramaIntent);
-        }
-        mShareIntent = shareIntent;
-        if (mShareActionProvider != null) {
-            mShareActionProvider.setShareIntent(shareIntent);
-            mShareActionProvider.setOnShareTargetSelectedListener(
-                onShareListener);
-        }
-    }
-}
diff --git a/src/com/android/gallery3d/app/GalleryApp.java b/src/com/android/gallery3d/app/GalleryApp.java
deleted file mode 100644
index b56b8a8..0000000
--- a/src/com/android/gallery3d/app/GalleryApp.java
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright (C) 2010 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.gallery3d.app;
-
-import android.content.ContentResolver;
-import android.content.Context;
-import android.content.res.Resources;
-import android.os.Looper;
-
-import com.android.gallery3d.data.DataManager;
-import com.android.gallery3d.data.DownloadCache;
-import com.android.gallery3d.data.ImageCacheService;
-import com.android.gallery3d.util.ThreadPool;
-
-public interface GalleryApp {
-    public DataManager getDataManager();
-
-    public StitchingProgressManager getStitchingProgressManager();
-    public ImageCacheService getImageCacheService();
-    public DownloadCache getDownloadCache();
-    public ThreadPool getThreadPool();
-
-    public Context getAndroidContext();
-    public Looper getMainLooper();
-    public ContentResolver getContentResolver();
-    public Resources getResources();
-}
diff --git a/src/com/android/gallery3d/app/GalleryAppImpl.java b/src/com/android/gallery3d/app/GalleryAppImpl.java
deleted file mode 100644
index 2abdaa0..0000000
--- a/src/com/android/gallery3d/app/GalleryAppImpl.java
+++ /dev/null
@@ -1,127 +0,0 @@
-/*
- * Copyright (C) 2010 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.gallery3d.app;
-
-import android.app.Application;
-import android.content.Context;
-import android.os.AsyncTask;
-
-import com.android.gallery3d.data.DataManager;
-import com.android.gallery3d.data.DownloadCache;
-import com.android.gallery3d.data.ImageCacheService;
-import com.android.gallery3d.gadget.WidgetUtils;
-import com.android.gallery3d.picasasource.PicasaSource;
-import com.android.gallery3d.util.GalleryUtils;
-import com.android.gallery3d.util.LightCycleHelper;
-import com.android.gallery3d.util.ThreadPool;
-import com.android.gallery3d.util.UsageStatistics;
-import com.android.photos.data.MediaCache;
-
-import java.io.File;
-
-public class GalleryAppImpl extends Application implements GalleryApp {
-
-    private static final String DOWNLOAD_FOLDER = "download";
-    private static final long DOWNLOAD_CAPACITY = 64 * 1024 * 1024; // 64M
-
-    private ImageCacheService mImageCacheService;
-    private Object mLock = new Object();
-    private DataManager mDataManager;
-    private ThreadPool mThreadPool;
-    private DownloadCache mDownloadCache;
-    private StitchingProgressManager mStitchingProgressManager;
-
-    @Override
-    public void onCreate() {
-        super.onCreate();
-        com.android.camera.Util.initialize(this);
-        initializeAsyncTask();
-        GalleryUtils.initialize(this);
-        WidgetUtils.initialize(this);
-        PicasaSource.initialize(this);
-        UsageStatistics.initialize(this);
-        MediaCache.initialize(this);
-
-        mStitchingProgressManager = LightCycleHelper.createStitchingManagerInstance(this);
-        if (mStitchingProgressManager != null) {
-            mStitchingProgressManager.addChangeListener(getDataManager());
-        }
-    }
-
-    @Override
-    public Context getAndroidContext() {
-        return this;
-    }
-
-    @Override
-    public synchronized DataManager getDataManager() {
-        if (mDataManager == null) {
-            mDataManager = new DataManager(this);
-            mDataManager.initializeSourceMap();
-        }
-        return mDataManager;
-    }
-
-    @Override
-    public StitchingProgressManager getStitchingProgressManager() {
-        return mStitchingProgressManager;
-    }
-
-    @Override
-    public ImageCacheService getImageCacheService() {
-        // This method may block on file I/O so a dedicated lock is needed here.
-        synchronized (mLock) {
-            if (mImageCacheService == null) {
-                mImageCacheService = new ImageCacheService(getAndroidContext());
-            }
-            return mImageCacheService;
-        }
-    }
-
-    @Override
-    public synchronized ThreadPool getThreadPool() {
-        if (mThreadPool == null) {
-            mThreadPool = new ThreadPool();
-        }
-        return mThreadPool;
-    }
-
-    @Override
-    public synchronized DownloadCache getDownloadCache() {
-        if (mDownloadCache == null) {
-            File cacheDir = new File(getExternalCacheDir(), DOWNLOAD_FOLDER);
-
-            if (!cacheDir.isDirectory()) cacheDir.mkdirs();
-
-            if (!cacheDir.isDirectory()) {
-                throw new RuntimeException(
-                        "fail to create: " + cacheDir.getAbsolutePath());
-            }
-            mDownloadCache = new DownloadCache(this, cacheDir, DOWNLOAD_CAPACITY);
-        }
-        return mDownloadCache;
-    }
-
-    private void initializeAsyncTask() {
-        // AsyncTask class needs to be loaded in UI thread.
-        // So we load it here to comply the rule.
-        try {
-            Class.forName(AsyncTask.class.getName());
-        } catch (ClassNotFoundException e) {
-        }
-    }
-}
diff --git a/src/com/android/gallery3d/app/GalleryContext.java b/src/com/android/gallery3d/app/GalleryContext.java
deleted file mode 100644
index 06f4fe4..0000000
--- a/src/com/android/gallery3d/app/GalleryContext.java
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright (C) 2010 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.gallery3d.app;
-
-import android.content.Context;
-import android.content.res.Resources;
-import android.os.Looper;
-
-import com.android.gallery3d.data.DataManager;
-import com.android.gallery3d.util.ThreadPool;
-
-public interface GalleryContext {
-    public DataManager getDataManager();
-
-    public Context getAndroidContext();
-
-    public Looper getMainLooper();
-    public Resources getResources();
-    public ThreadPool getThreadPool();
-}
diff --git a/src/com/android/gallery3d/app/LoadingListener.java b/src/com/android/gallery3d/app/LoadingListener.java
deleted file mode 100644
index e94df93..0000000
--- a/src/com/android/gallery3d/app/LoadingListener.java
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * Copyright (C) 2010 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.gallery3d.app;
-
-public interface LoadingListener {
-    public void onLoadingStarted();
-    /**
-     * Called when loading is complete or no further progress can be made.
-     *
-     * @param loadingFailed true if data source cannot provide requested data
-     */
-    public void onLoadingFinished(boolean loadingFailed);
-}
diff --git a/src/com/android/gallery3d/app/Log.java b/src/com/android/gallery3d/app/Log.java
deleted file mode 100644
index 07a8ea5..0000000
--- a/src/com/android/gallery3d/app/Log.java
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Copyright (C) 2010 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.gallery3d.app;
-
-public class Log {
-    public static int v(String tag, String msg) {
-        return android.util.Log.v(tag, msg);
-    }
-    public static int v(String tag, String msg, Throwable tr) {
-        return android.util.Log.v(tag, msg, tr);
-    }
-    public static int d(String tag, String msg) {
-        return android.util.Log.d(tag, msg);
-    }
-    public static int d(String tag, String msg, Throwable tr) {
-        return android.util.Log.d(tag, msg, tr);
-    }
-    public static int i(String tag, String msg) {
-        return android.util.Log.i(tag, msg);
-    }
-    public static int i(String tag, String msg, Throwable tr) {
-        return android.util.Log.i(tag, msg, tr);
-    }
-    public static int w(String tag, String msg) {
-        return android.util.Log.w(tag, msg);
-    }
-    public static int w(String tag, String msg, Throwable tr) {
-        return android.util.Log.w(tag, msg, tr);
-    }
-    public static int w(String tag, Throwable tr) {
-        return android.util.Log.w(tag, tr);
-    }
-    public static int e(String tag, String msg) {
-        return android.util.Log.e(tag, msg);
-    }
-    public static int e(String tag, String msg, Throwable tr) {
-        return android.util.Log.e(tag, msg, tr);
-    }
-}
diff --git a/src/com/android/gallery3d/app/ManageCachePage.java b/src/com/android/gallery3d/app/ManageCachePage.java
deleted file mode 100644
index 4f5c358..0000000
--- a/src/com/android/gallery3d/app/ManageCachePage.java
+++ /dev/null
@@ -1,419 +0,0 @@
-/*
- * Copyright (C) 2010 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.gallery3d.app;
-
-import android.app.Activity;
-import android.content.res.Configuration;
-import android.os.Bundle;
-import android.os.Handler;
-import android.os.Message;
-import android.text.format.Formatter;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.View.OnClickListener;
-import android.widget.FrameLayout;
-import android.widget.ProgressBar;
-import android.widget.TextView;
-import android.widget.Toast;
-
-import com.android.gallery3d.R;
-import com.android.gallery3d.common.Utils;
-import com.android.gallery3d.data.MediaObject;
-import com.android.gallery3d.data.MediaSet;
-import com.android.gallery3d.data.Path;
-import com.android.gallery3d.glrenderer.GLCanvas;
-import com.android.gallery3d.ui.CacheStorageUsageInfo;
-import com.android.gallery3d.ui.GLRoot;
-import com.android.gallery3d.ui.GLView;
-import com.android.gallery3d.ui.ManageCacheDrawer;
-import com.android.gallery3d.ui.MenuExecutor;
-import com.android.gallery3d.ui.SelectionManager;
-import com.android.gallery3d.ui.SlotView;
-import com.android.gallery3d.ui.SynchronizedHandler;
-import com.android.gallery3d.util.Future;
-import com.android.gallery3d.util.GalleryUtils;
-import com.android.gallery3d.util.ThreadPool.Job;
-import com.android.gallery3d.util.ThreadPool.JobContext;
-
-import java.util.ArrayList;
-
-public class ManageCachePage extends ActivityState implements
-        SelectionManager.SelectionListener, MenuExecutor.ProgressListener,
-        EyePosition.EyePositionListener, OnClickListener {
-    public static final String KEY_MEDIA_PATH = "media-path";
-
-    @SuppressWarnings("unused")
-    private static final String TAG = "ManageCachePage";
-
-    private static final int DATA_CACHE_SIZE = 256;
-    private static final int MSG_REFRESH_STORAGE_INFO = 1;
-    private static final int MSG_REQUEST_LAYOUT = 2;
-    private static final int PROGRESS_BAR_MAX = 10000;
-
-    private SlotView mSlotView;
-    private MediaSet mMediaSet;
-
-    protected SelectionManager mSelectionManager;
-    protected ManageCacheDrawer mSelectionDrawer;
-    private AlbumSetDataLoader mAlbumSetDataAdapter;
-
-    private EyePosition mEyePosition;
-
-    // The eyes' position of the user, the origin is at the center of the
-    // device and the unit is in pixels.
-    private float mX;
-    private float mY;
-    private float mZ;
-
-    private int mAlbumCountToMakeAvailableOffline;
-    private View mFooterContent;
-    private CacheStorageUsageInfo mCacheStorageInfo;
-    private Future<Void> mUpdateStorageInfo;
-    private Handler mHandler;
-    private boolean mLayoutReady = false;
-
-    @Override
-    protected int getBackgroundColorId() {
-        return R.color.cache_background;
-    }
-
-    private GLView mRootPane = new GLView() {
-        private float mMatrix[] = new float[16];
-
-        @Override
-        protected void renderBackground(GLCanvas view) {
-            view.clearBuffer(getBackgroundColor());
-        }
-
-        @Override
-        protected void onLayout(
-                boolean changed, int left, int top, int right, int bottom) {
-            // Hack: our layout depends on other components on the screen.
-            // We assume the other components will complete before we get a change
-            // to run a message in main thread.
-            if (!mLayoutReady) {
-                mHandler.sendEmptyMessage(MSG_REQUEST_LAYOUT);
-                return;
-            }
-            mLayoutReady = false;
-
-            mEyePosition.resetPosition();
-            int slotViewTop = mActivity.getGalleryActionBar().getHeight();
-            int slotViewBottom = bottom - top;
-
-            View footer = mActivity.findViewById(R.id.footer);
-            if (footer != null) {
-                int location[] = {0, 0};
-                footer.getLocationOnScreen(location);
-                slotViewBottom = location[1];
-            }
-
-            mSlotView.layout(0, slotViewTop, right - left, slotViewBottom);
-        }
-
-        @Override
-        protected void render(GLCanvas canvas) {
-            canvas.save(GLCanvas.SAVE_FLAG_MATRIX);
-            GalleryUtils.setViewPointMatrix(mMatrix,
-                        getWidth() / 2 + mX, getHeight() / 2 + mY, mZ);
-            canvas.multiplyMatrix(mMatrix, 0);
-            super.render(canvas);
-            canvas.restore();
-        }
-    };
-
-    @Override
-    public void onEyePositionChanged(float x, float y, float z) {
-        mRootPane.lockRendering();
-        mX = x;
-        mY = y;
-        mZ = z;
-        mRootPane.unlockRendering();
-        mRootPane.invalidate();
-    }
-
-    private void onDown(int index) {
-        mSelectionDrawer.setPressedIndex(index);
-    }
-
-    private void onUp() {
-        mSelectionDrawer.setPressedIndex(-1);
-    }
-
-    public void onSingleTapUp(int slotIndex) {
-        MediaSet targetSet = mAlbumSetDataAdapter.getMediaSet(slotIndex);
-        if (targetSet == null) return; // Content is dirty, we shall reload soon
-
-        // ignore selection action if the target set does not support cache
-        // operation (like a local album).
-        if ((targetSet.getSupportedOperations()
-                & MediaSet.SUPPORT_CACHE) == 0) {
-            showToastForLocalAlbum();
-            return;
-        }
-
-        Path path = targetSet.getPath();
-        boolean isFullyCached =
-                (targetSet.getCacheFlag() == MediaObject.CACHE_FLAG_FULL);
-        boolean isSelected = mSelectionManager.isItemSelected(path);
-
-        if (!isFullyCached) {
-            // We only count the media sets that will be made available offline
-            // in this session.
-            if (isSelected) {
-                --mAlbumCountToMakeAvailableOffline;
-            } else {
-                ++mAlbumCountToMakeAvailableOffline;
-            }
-        }
-
-        long sizeOfTarget = targetSet.getCacheSize();
-        mCacheStorageInfo.increaseTargetCacheSize(
-                (isFullyCached ^ isSelected) ? -sizeOfTarget : sizeOfTarget);
-        refreshCacheStorageInfo();
-
-        mSelectionManager.toggle(path);
-        mSlotView.invalidate();
-    }
-
-    @Override
-    public void onCreate(Bundle data, Bundle restoreState) {
-        super.onCreate(data, restoreState);
-        mCacheStorageInfo = new CacheStorageUsageInfo(mActivity);
-        initializeViews();
-        initializeData(data);
-        mEyePosition = new EyePosition(mActivity.getAndroidContext(), this);
-        mHandler = new SynchronizedHandler(mActivity.getGLRoot()) {
-            @Override
-            public void handleMessage(Message message) {
-                switch (message.what) {
-                    case MSG_REFRESH_STORAGE_INFO:
-                        refreshCacheStorageInfo();
-                        break;
-                    case MSG_REQUEST_LAYOUT: {
-                        mLayoutReady = true;
-                        removeMessages(MSG_REQUEST_LAYOUT);
-                        mRootPane.requestLayout();
-                        break;
-                    }
-                }
-            }
-        };
-    }
-
-    @Override
-    public void onConfigurationChanged(Configuration config) {
-        // We use different layout resources for different configs
-        initializeFooterViews();
-        FrameLayout layout = (FrameLayout) ((Activity) mActivity).findViewById(R.id.footer);
-        if (layout.getVisibility() == View.VISIBLE) {
-            layout.removeAllViews();
-            layout.addView(mFooterContent);
-        }
-    }
-
-    @Override
-    public void onPause() {
-        super.onPause();
-        mAlbumSetDataAdapter.pause();
-        mSelectionDrawer.pause();
-        mEyePosition.pause();
-
-        if (mUpdateStorageInfo != null) {
-            mUpdateStorageInfo.cancel();
-            mUpdateStorageInfo = null;
-        }
-        mHandler.removeMessages(MSG_REFRESH_STORAGE_INFO);
-
-        FrameLayout layout = (FrameLayout) ((Activity) mActivity).findViewById(R.id.footer);
-        layout.removeAllViews();
-        layout.setVisibility(View.INVISIBLE);
-    }
-
-    private Job<Void> mUpdateStorageInfoJob = new Job<Void>() {
-        @Override
-        public Void run(JobContext jc) {
-            mCacheStorageInfo.loadStorageInfo(jc);
-            if (!jc.isCancelled()) {
-                mHandler.sendEmptyMessage(MSG_REFRESH_STORAGE_INFO);
-            }
-            return null;
-        }
-    };
-
-    @Override
-    public void onResume() {
-        super.onResume();
-        setContentPane(mRootPane);
-        mAlbumSetDataAdapter.resume();
-        mSelectionDrawer.resume();
-        mEyePosition.resume();
-        mUpdateStorageInfo = mActivity.getThreadPool().submit(mUpdateStorageInfoJob);
-        FrameLayout layout = (FrameLayout) ((Activity) mActivity).findViewById(R.id.footer);
-        layout.addView(mFooterContent);
-        layout.setVisibility(View.VISIBLE);
-    }
-
-    private void initializeData(Bundle data) {
-        String mediaPath = data.getString(ManageCachePage.KEY_MEDIA_PATH);
-        mMediaSet = mActivity.getDataManager().getMediaSet(mediaPath);
-        mSelectionManager.setSourceMediaSet(mMediaSet);
-
-        // We will always be in selection mode in this page.
-        mSelectionManager.setAutoLeaveSelectionMode(false);
-        mSelectionManager.enterSelectionMode();
-
-        mAlbumSetDataAdapter = new AlbumSetDataLoader(
-                mActivity, mMediaSet, DATA_CACHE_SIZE);
-        mSelectionDrawer.setModel(mAlbumSetDataAdapter);
-    }
-
-    private void initializeViews() {
-        Activity activity = mActivity;
-
-        mSelectionManager = new SelectionManager(mActivity, true);
-        mSelectionManager.setSelectionListener(this);
-
-        Config.ManageCachePage config = Config.ManageCachePage.get(activity);
-        mSlotView = new SlotView(mActivity, config.slotViewSpec);
-        mSelectionDrawer = new ManageCacheDrawer(mActivity, mSelectionManager, mSlotView,
-                config.labelSpec, config.cachePinSize, config.cachePinMargin);
-        mSlotView.setSlotRenderer(mSelectionDrawer);
-        mSlotView.setListener(new SlotView.SimpleListener() {
-            @Override
-            public void onDown(int index) {
-                ManageCachePage.this.onDown(index);
-            }
-
-            @Override
-            public void onUp(boolean followedByLongPress) {
-                ManageCachePage.this.onUp();
-            }
-
-            @Override
-            public void onSingleTapUp(int slotIndex) {
-                ManageCachePage.this.onSingleTapUp(slotIndex);
-            }
-        });
-        mRootPane.addComponent(mSlotView);
-        initializeFooterViews();
-    }
-
-    private void initializeFooterViews() {
-        Activity activity = mActivity;
-
-        LayoutInflater inflater = activity.getLayoutInflater();
-        mFooterContent = inflater.inflate(R.layout.manage_offline_bar, null);
-
-        mFooterContent.findViewById(R.id.done).setOnClickListener(this);
-        refreshCacheStorageInfo();
-    }
-
-    @Override
-    public void onClick(View view) {
-        Utils.assertTrue(view.getId() == R.id.done);
-        GLRoot root = mActivity.getGLRoot();
-        root.lockRenderThread();
-        try {
-            ArrayList<Path> ids = mSelectionManager.getSelected(false);
-            if (ids.size() == 0) {
-                onBackPressed();
-                return;
-            }
-            showToast();
-
-            MenuExecutor menuExecutor = new MenuExecutor(mActivity, mSelectionManager);
-            menuExecutor.startAction(R.id.action_toggle_full_caching,
-                    R.string.process_caching_requests, this);
-        } finally {
-            root.unlockRenderThread();
-        }
-    }
-
-    private void showToast() {
-        if (mAlbumCountToMakeAvailableOffline > 0) {
-            Activity activity = mActivity;
-            Toast.makeText(activity, activity.getResources().getQuantityString(
-                    R.plurals.make_albums_available_offline,
-                    mAlbumCountToMakeAvailableOffline),
-                    Toast.LENGTH_SHORT).show();
-        }
-    }
-
-    private void showToastForLocalAlbum() {
-        Activity activity = mActivity;
-        Toast.makeText(activity, activity.getResources().getString(
-            R.string.try_to_set_local_album_available_offline),
-            Toast.LENGTH_SHORT).show();
-    }
-
-    private void refreshCacheStorageInfo() {
-        ProgressBar progressBar = (ProgressBar) mFooterContent.findViewById(R.id.progress);
-        TextView status = (TextView) mFooterContent.findViewById(R.id.status);
-        progressBar.setMax(PROGRESS_BAR_MAX);
-        long totalBytes = mCacheStorageInfo.getTotalBytes();
-        long usedBytes = mCacheStorageInfo.getUsedBytes();
-        long expectedBytes = mCacheStorageInfo.getExpectedUsedBytes();
-        long freeBytes = mCacheStorageInfo.getFreeBytes();
-
-        Activity activity = mActivity;
-        if (totalBytes == 0) {
-            progressBar.setProgress(0);
-            progressBar.setSecondaryProgress(0);
-
-            // TODO: get the string translated
-            String label = activity.getString(R.string.free_space_format, "-");
-            status.setText(label);
-        } else {
-            progressBar.setProgress((int) (usedBytes * PROGRESS_BAR_MAX / totalBytes));
-            progressBar.setSecondaryProgress(
-                    (int) (expectedBytes * PROGRESS_BAR_MAX / totalBytes));
-            String label = activity.getString(R.string.free_space_format,
-                    Formatter.formatFileSize(activity, freeBytes));
-            status.setText(label);
-        }
-    }
-
-    @Override
-    public void onProgressComplete(int result) {
-        onBackPressed();
-    }
-
-    @Override
-    public void onProgressUpdate(int index) {
-    }
-
-    @Override
-    public void onSelectionModeChange(int mode) {
-    }
-
-    @Override
-    public void onSelectionChange(Path path, boolean selected) {
-    }
-
-    @Override
-    public void onConfirmDialogDismissed(boolean confirmed) {
-    }
-
-    @Override
-    public void onConfirmDialogShown() {
-    }
-
-    @Override
-    public void onProgressStart() {
-    }
-}
diff --git a/src/com/android/gallery3d/app/MovieActivity.java b/src/com/android/gallery3d/app/MovieActivity.java
deleted file mode 100644
index 40edbbe..0000000
--- a/src/com/android/gallery3d/app/MovieActivity.java
+++ /dev/null
@@ -1,263 +0,0 @@
-/*
- * Copyright (C) 2007 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.gallery3d.app;
-
-import android.annotation.TargetApi;
-import android.app.ActionBar;
-import android.app.Activity;
-import android.content.AsyncQueryHandler;
-import android.content.ContentResolver;
-import android.content.Intent;
-import android.content.pm.ActivityInfo;
-import android.database.Cursor;
-import android.graphics.Bitmap;
-import android.graphics.drawable.BitmapDrawable;
-import android.media.AudioManager;
-import android.net.Uri;
-import android.os.Build;
-import android.os.Bundle;
-import android.provider.MediaStore;
-import android.provider.OpenableColumns;
-import android.view.KeyEvent;
-import android.view.Menu;
-import android.view.MenuItem;
-import android.view.View;
-import android.view.Window;
-import android.view.WindowManager;
-import android.widget.ShareActionProvider;
-
-import com.android.gallery3d.R;
-import com.android.gallery3d.common.ApiHelper;
-import com.android.gallery3d.common.Utils;
-
-/**
- * This activity plays a video from a specified URI.
- *
- * The client of this activity can pass a logo bitmap in the intent (KEY_LOGO_BITMAP)
- * to set the action bar logo so the playback process looks more seamlessly integrated with
- * the original activity.
- */
-public class MovieActivity extends Activity {
-    @SuppressWarnings("unused")
-    private static final String TAG = "MovieActivity";
-    public static final String KEY_LOGO_BITMAP = "logo-bitmap";
-    public static final String KEY_TREAT_UP_AS_BACK = "treat-up-as-back";
-
-    private MoviePlayer mPlayer;
-    private boolean mFinishOnCompletion;
-    private Uri mUri;
-    private boolean mTreatUpAsBack;
-
-    @TargetApi(Build.VERSION_CODES.JELLY_BEAN)
-    private void setSystemUiVisibility(View rootView) {
-        if (ApiHelper.HAS_VIEW_SYSTEM_UI_FLAG_LAYOUT_STABLE) {
-            rootView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE
-                    | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
-                    | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION);
-        }
-    }
-
-    @Override
-    public void onCreate(Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-
-        requestWindowFeature(Window.FEATURE_ACTION_BAR);
-        requestWindowFeature(Window.FEATURE_ACTION_BAR_OVERLAY);
-
-        setContentView(R.layout.movie_view);
-        View rootView = findViewById(R.id.movie_view_root);
-
-        setSystemUiVisibility(rootView);
-
-        Intent intent = getIntent();
-        initializeActionBar(intent);
-        mFinishOnCompletion = intent.getBooleanExtra(
-                MediaStore.EXTRA_FINISH_ON_COMPLETION, true);
-        mTreatUpAsBack = intent.getBooleanExtra(KEY_TREAT_UP_AS_BACK, false);
-        mPlayer = new MoviePlayer(rootView, this, intent.getData(), savedInstanceState,
-                !mFinishOnCompletion) {
-            @Override
-            public void onCompletion() {
-                if (mFinishOnCompletion) {
-                    finish();
-                }
-            }
-        };
-        if (intent.hasExtra(MediaStore.EXTRA_SCREEN_ORIENTATION)) {
-            int orientation = intent.getIntExtra(
-                    MediaStore.EXTRA_SCREEN_ORIENTATION,
-                    ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
-            if (orientation != getRequestedOrientation()) {
-                setRequestedOrientation(orientation);
-            }
-        }
-        Window win = getWindow();
-        WindowManager.LayoutParams winParams = win.getAttributes();
-        winParams.buttonBrightness = WindowManager.LayoutParams.BRIGHTNESS_OVERRIDE_OFF;
-        winParams.flags |= WindowManager.LayoutParams.FLAG_FULLSCREEN;
-        win.setAttributes(winParams);
-
-        // We set the background in the theme to have the launching animation.
-        // But for the performance (and battery), we remove the background here.
-        win.setBackgroundDrawable(null);
-    }
-
-    private void setActionBarLogoFromIntent(Intent intent) {
-        Bitmap logo = intent.getParcelableExtra(KEY_LOGO_BITMAP);
-        if (logo != null) {
-            getActionBar().setLogo(
-                    new BitmapDrawable(getResources(), logo));
-        }
-    }
-
-    private void initializeActionBar(Intent intent) {
-        mUri = intent.getData();
-        final ActionBar actionBar = getActionBar();
-        if (actionBar == null) {
-            return;
-        }
-        setActionBarLogoFromIntent(intent);
-        actionBar.setDisplayOptions(
-                ActionBar.DISPLAY_HOME_AS_UP,
-                ActionBar.DISPLAY_HOME_AS_UP);
-
-        String title = intent.getStringExtra(Intent.EXTRA_TITLE);
-        if (title != null) {
-            actionBar.setTitle(title);
-        } else {
-            // Displays the filename as title, reading the filename from the
-            // interface: {@link android.provider.OpenableColumns#DISPLAY_NAME}.
-            AsyncQueryHandler queryHandler =
-                    new AsyncQueryHandler(getContentResolver()) {
-                @Override
-                protected void onQueryComplete(int token, Object cookie,
-                        Cursor cursor) {
-                    try {
-                        if ((cursor != null) && cursor.moveToFirst()) {
-                            String displayName = cursor.getString(0);
-
-                            // Just show empty title if other apps don't set
-                            // DISPLAY_NAME
-                            actionBar.setTitle((displayName == null) ? "" :
-                                    displayName);
-                        }
-                    } finally {
-                        Utils.closeSilently(cursor);
-                    }
-                }
-            };
-            queryHandler.startQuery(0, null, mUri,
-                    new String[] {OpenableColumns.DISPLAY_NAME}, null, null,
-                    null);
-        }
-    }
-
-    @Override
-    public boolean onCreateOptionsMenu(Menu menu) {
-        super.onCreateOptionsMenu(menu);
-        getMenuInflater().inflate(R.menu.movie, menu);
-
-        // Document says EXTRA_STREAM should be a content: Uri
-        // So, we only share the video if it's "content:".
-        MenuItem shareItem = menu.findItem(R.id.action_share);
-        if (ContentResolver.SCHEME_CONTENT.equals(mUri.getScheme())) {
-            shareItem.setVisible(true);
-            ((ShareActionProvider) shareItem.getActionProvider())
-                    .setShareIntent(createShareIntent());
-        } else {
-            shareItem.setVisible(false);
-        }
-        return true;
-    }
-
-    private Intent createShareIntent() {
-        Intent intent = new Intent(Intent.ACTION_SEND);
-        intent.setType("video/*");
-        intent.putExtra(Intent.EXTRA_STREAM, mUri);
-        return intent;
-    }
-
-    @Override
-    public boolean onOptionsItemSelected(MenuItem item) {
-        int id = item.getItemId();
-        if (id == android.R.id.home) {
-            if (mTreatUpAsBack) {
-                finish();
-            } else {
-                startActivity(new Intent(this, Gallery.class));
-                finish();
-            }
-            return true;
-        } else if (id == R.id.action_share) {
-            startActivity(Intent.createChooser(createShareIntent(),
-                    getString(R.string.share)));
-            return true;
-        }
-        return false;
-    }
-
-    @Override
-    public void onStart() {
-        ((AudioManager) getSystemService(AUDIO_SERVICE))
-                .requestAudioFocus(null, AudioManager.STREAM_MUSIC,
-                AudioManager.AUDIOFOCUS_GAIN_TRANSIENT);
-        super.onStart();
-    }
-
-    @Override
-    protected void onStop() {
-        ((AudioManager) getSystemService(AUDIO_SERVICE))
-                .abandonAudioFocus(null);
-        super.onStop();
-    }
-
-    @Override
-    public void onPause() {
-        mPlayer.onPause();
-        super.onPause();
-    }
-
-    @Override
-    public void onResume() {
-        mPlayer.onResume();
-        super.onResume();
-    }
-
-    @Override
-    public void onSaveInstanceState(Bundle outState) {
-        super.onSaveInstanceState(outState);
-        mPlayer.onSaveInstanceState(outState);
-    }
-
-    @Override
-    public void onDestroy() {
-        mPlayer.onDestroy();
-        super.onDestroy();
-    }
-
-    @Override
-    public boolean onKeyDown(int keyCode, KeyEvent event) {
-        return mPlayer.onKeyDown(keyCode, event)
-                || super.onKeyDown(keyCode, event);
-    }
-
-    @Override
-    public boolean onKeyUp(int keyCode, KeyEvent event) {
-        return mPlayer.onKeyUp(keyCode, event)
-                || super.onKeyUp(keyCode, event);
-    }
-}
diff --git a/src/com/android/gallery3d/app/MovieControllerOverlay.java b/src/com/android/gallery3d/app/MovieControllerOverlay.java
deleted file mode 100644
index f01e619..0000000
--- a/src/com/android/gallery3d/app/MovieControllerOverlay.java
+++ /dev/null
@@ -1,185 +0,0 @@
-/*
- * Copyright (C) 2011 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.gallery3d.app;
-
-import android.content.Context;
-import android.os.Handler;
-import android.view.KeyEvent;
-import android.view.MotionEvent;
-import android.view.View;
-import android.view.animation.Animation;
-import android.view.animation.Animation.AnimationListener;
-import android.view.animation.AnimationUtils;
-import com.android.gallery3d.R;
-
-/**
- * The playback controller for the Movie Player.
- */
-public class MovieControllerOverlay extends CommonControllerOverlay implements
-        AnimationListener {
-
-    private boolean hidden;
-
-    private final Handler handler;
-    private final Runnable startHidingRunnable;
-    private final Animation hideAnimation;
-
-    public MovieControllerOverlay(Context context) {
-        super(context);
-
-        handler = new Handler();
-        startHidingRunnable = new Runnable() {
-                @Override
-            public void run() {
-                startHiding();
-            }
-        };
-
-        hideAnimation = AnimationUtils.loadAnimation(context, R.anim.player_out);
-        hideAnimation.setAnimationListener(this);
-
-        hide();
-    }
-
-    @Override
-    protected void createTimeBar(Context context) {
-        mTimeBar = new TimeBar(context, this);
-    }
-
-    @Override
-    public void hide() {
-        boolean wasHidden = hidden;
-        hidden = true;
-        super.hide();
-        if (mListener != null && wasHidden != hidden) {
-            mListener.onHidden();
-        }
-    }
-
-
-    @Override
-    public void show() {
-        boolean wasHidden = hidden;
-        hidden = false;
-        super.show();
-        if (mListener != null && wasHidden != hidden) {
-            mListener.onShown();
-        }
-        maybeStartHiding();
-    }
-
-    private void maybeStartHiding() {
-        cancelHiding();
-        if (mState == State.PLAYING) {
-            handler.postDelayed(startHidingRunnable, 2500);
-        }
-    }
-
-    private void startHiding() {
-        startHideAnimation(mBackground);
-        startHideAnimation(mTimeBar);
-        startHideAnimation(mPlayPauseReplayView);
-    }
-
-    private void startHideAnimation(View view) {
-        if (view.getVisibility() == View.VISIBLE) {
-            view.startAnimation(hideAnimation);
-        }
-    }
-
-    private void cancelHiding() {
-        handler.removeCallbacks(startHidingRunnable);
-        mBackground.setAnimation(null);
-        mTimeBar.setAnimation(null);
-        mPlayPauseReplayView.setAnimation(null);
-    }
-
-    @Override
-    public void onAnimationStart(Animation animation) {
-        // Do nothing.
-    }
-
-    @Override
-    public void onAnimationRepeat(Animation animation) {
-        // Do nothing.
-    }
-
-    @Override
-    public void onAnimationEnd(Animation animation) {
-        hide();
-    }
-
-    @Override
-    public boolean onKeyDown(int keyCode, KeyEvent event) {
-        if (hidden) {
-            show();
-        }
-        return super.onKeyDown(keyCode, event);
-    }
-
-    @Override
-    public boolean onTouchEvent(MotionEvent event) {
-        if (super.onTouchEvent(event)) {
-            return true;
-        }
-
-        if (hidden) {
-            show();
-            return true;
-        }
-        switch (event.getAction()) {
-            case MotionEvent.ACTION_DOWN:
-                cancelHiding();
-                if (mState == State.PLAYING || mState == State.PAUSED) {
-                    mListener.onPlayPause();
-                }
-                break;
-            case MotionEvent.ACTION_UP:
-                maybeStartHiding();
-                break;
-        }
-        return true;
-    }
-
-    @Override
-    protected void updateViews() {
-        if (hidden) {
-            return;
-        }
-        super.updateViews();
-    }
-
-    // TimeBar listener
-
-    @Override
-    public void onScrubbingStart() {
-        cancelHiding();
-        super.onScrubbingStart();
-    }
-
-    @Override
-    public void onScrubbingMove(int time) {
-        cancelHiding();
-        super.onScrubbingMove(time);
-    }
-
-    @Override
-    public void onScrubbingEnd(int time, int trimStartTime, int trimEndTime) {
-        maybeStartHiding();
-        super.onScrubbingEnd(time, trimStartTime, trimEndTime);
-    }
-}
diff --git a/src/com/android/gallery3d/app/MoviePlayer.java b/src/com/android/gallery3d/app/MoviePlayer.java
deleted file mode 100644
index ce91834..0000000
--- a/src/com/android/gallery3d/app/MoviePlayer.java
+++ /dev/null
@@ -1,525 +0,0 @@
-/*
- * Copyright (C) 2009 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.gallery3d.app;
-
-import android.annotation.TargetApi;
-import android.app.AlertDialog;
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.DialogInterface;
-import android.content.DialogInterface.OnCancelListener;
-import android.content.DialogInterface.OnClickListener;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.media.AudioManager;
-import android.media.MediaPlayer;
-import android.net.Uri;
-import android.os.Build;
-import android.os.Bundle;
-import android.os.Handler;
-import android.view.KeyEvent;
-import android.view.MotionEvent;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.VideoView;
-
-import com.android.gallery3d.R;
-import com.android.gallery3d.common.ApiHelper;
-import com.android.gallery3d.common.BlobCache;
-import com.android.gallery3d.util.CacheManager;
-import com.android.gallery3d.util.GalleryUtils;
-
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.DataInputStream;
-import java.io.DataOutputStream;
-
-public class MoviePlayer implements
-        MediaPlayer.OnErrorListener, MediaPlayer.OnCompletionListener,
-        ControllerOverlay.Listener {
-    @SuppressWarnings("unused")
-    private static final String TAG = "MoviePlayer";
-
-    private static final String KEY_VIDEO_POSITION = "video-position";
-    private static final String KEY_RESUMEABLE_TIME = "resumeable-timeout";
-
-    // These are constants in KeyEvent, appearing on API level 11.
-    private static final int KEYCODE_MEDIA_PLAY = 126;
-    private static final int KEYCODE_MEDIA_PAUSE = 127;
-
-    // Copied from MediaPlaybackService in the Music Player app.
-    private static final String SERVICECMD = "com.android.music.musicservicecommand";
-    private static final String CMDNAME = "command";
-    private static final String CMDPAUSE = "pause";
-
-    private static final long BLACK_TIMEOUT = 500;
-
-    // If we resume the acitivty with in RESUMEABLE_TIMEOUT, we will keep playing.
-    // Otherwise, we pause the player.
-    private static final long RESUMEABLE_TIMEOUT = 3 * 60 * 1000; // 3 mins
-
-    private Context mContext;
-    private final VideoView mVideoView;
-    private final View mRootView;
-    private final Bookmarker mBookmarker;
-    private final Uri mUri;
-    private final Handler mHandler = new Handler();
-    private final AudioBecomingNoisyReceiver mAudioBecomingNoisyReceiver;
-    private final MovieControllerOverlay mController;
-
-    private long mResumeableTime = Long.MAX_VALUE;
-    private int mVideoPosition = 0;
-    private boolean mHasPaused = false;
-    private int mLastSystemUiVis = 0;
-
-    // If the time bar is being dragged.
-    private boolean mDragging;
-
-    // If the time bar is visible.
-    private boolean mShowing;
-
-    private final Runnable mPlayingChecker = new Runnable() {
-        @Override
-        public void run() {
-            if (mVideoView.isPlaying()) {
-                mController.showPlaying();
-            } else {
-                mHandler.postDelayed(mPlayingChecker, 250);
-            }
-        }
-    };
-
-    private final Runnable mProgressChecker = new Runnable() {
-        @Override
-        public void run() {
-            int pos = setProgress();
-            mHandler.postDelayed(mProgressChecker, 1000 - (pos % 1000));
-        }
-    };
-
-    public MoviePlayer(View rootView, final MovieActivity movieActivity,
-            Uri videoUri, Bundle savedInstance, boolean canReplay) {
-        mContext = movieActivity.getApplicationContext();
-        mRootView = rootView;
-        mVideoView = (VideoView) rootView.findViewById(R.id.surface_view);
-        mBookmarker = new Bookmarker(movieActivity);
-        mUri = videoUri;
-
-        mController = new MovieControllerOverlay(mContext);
-        ((ViewGroup)rootView).addView(mController.getView());
-        mController.setListener(this);
-        mController.setCanReplay(canReplay);
-
-        mVideoView.setOnErrorListener(this);
-        mVideoView.setOnCompletionListener(this);
-        mVideoView.setVideoURI(mUri);
-        mVideoView.setOnTouchListener(new View.OnTouchListener() {
-            @Override
-            public boolean onTouch(View v, MotionEvent event) {
-                mController.show();
-                return true;
-            }
-        });
-        mVideoView.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
-            @Override
-            public void onPrepared(MediaPlayer player) {
-                if (!mVideoView.canSeekForward() || !mVideoView.canSeekBackward()) {
-                    mController.setSeekable(false);
-                } else {
-                    mController.setSeekable(true);
-                }
-                setProgress();
-            }
-        });
-
-        // The SurfaceView is transparent before drawing the first frame.
-        // This makes the UI flashing when open a video. (black -> old screen
-        // -> video) However, we have no way to know the timing of the first
-        // frame. So, we hide the VideoView for a while to make sure the
-        // video has been drawn on it.
-        mVideoView.postDelayed(new Runnable() {
-            @Override
-            public void run() {
-                mVideoView.setVisibility(View.VISIBLE);
-            }
-        }, BLACK_TIMEOUT);
-
-        setOnSystemUiVisibilityChangeListener();
-        // Hide system UI by default
-        showSystemUi(false);
-
-        mAudioBecomingNoisyReceiver = new AudioBecomingNoisyReceiver();
-        mAudioBecomingNoisyReceiver.register();
-
-        Intent i = new Intent(SERVICECMD);
-        i.putExtra(CMDNAME, CMDPAUSE);
-        movieActivity.sendBroadcast(i);
-
-        if (savedInstance != null) { // this is a resumed activity
-            mVideoPosition = savedInstance.getInt(KEY_VIDEO_POSITION, 0);
-            mResumeableTime = savedInstance.getLong(KEY_RESUMEABLE_TIME, Long.MAX_VALUE);
-            mVideoView.start();
-            mVideoView.suspend();
-            mHasPaused = true;
-        } else {
-            final Integer bookmark = mBookmarker.getBookmark(mUri);
-            if (bookmark != null) {
-                showResumeDialog(movieActivity, bookmark);
-            } else {
-                startVideo();
-            }
-        }
-    }
-
-    @TargetApi(Build.VERSION_CODES.JELLY_BEAN)
-    private void setOnSystemUiVisibilityChangeListener() {
-        if (!ApiHelper.HAS_VIEW_SYSTEM_UI_FLAG_HIDE_NAVIGATION) return;
-
-        // When the user touches the screen or uses some hard key, the framework
-        // will change system ui visibility from invisible to visible. We show
-        // the media control and enable system UI (e.g. ActionBar) to be visible at this point
-        mVideoView.setOnSystemUiVisibilityChangeListener(
-                new View.OnSystemUiVisibilityChangeListener() {
-            @Override
-            public void onSystemUiVisibilityChange(int visibility) {
-                int diff = mLastSystemUiVis ^ visibility;
-                mLastSystemUiVis = visibility;
-                if ((diff & View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) != 0
-                        && (visibility & View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) == 0) {
-                    mController.show();
-                }
-            }
-        });
-    }
-
-    @SuppressWarnings("deprecation")
-    @TargetApi(Build.VERSION_CODES.JELLY_BEAN)
-    private void showSystemUi(boolean visible) {
-        if (!ApiHelper.HAS_VIEW_SYSTEM_UI_FLAG_LAYOUT_STABLE) return;
-
-        int flag = View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
-                | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
-                | View.SYSTEM_UI_FLAG_LAYOUT_STABLE;
-        if (!visible) {
-            // We used the deprecated "STATUS_BAR_HIDDEN" for unbundling
-            flag |= View.STATUS_BAR_HIDDEN | View.SYSTEM_UI_FLAG_FULLSCREEN
-                    | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION;
-        }
-        mVideoView.setSystemUiVisibility(flag);
-    }
-
-    public void onSaveInstanceState(Bundle outState) {
-        outState.putInt(KEY_VIDEO_POSITION, mVideoPosition);
-        outState.putLong(KEY_RESUMEABLE_TIME, mResumeableTime);
-    }
-
-    private void showResumeDialog(Context context, final int bookmark) {
-        AlertDialog.Builder builder = new AlertDialog.Builder(context);
-        builder.setTitle(R.string.resume_playing_title);
-        builder.setMessage(String.format(
-                context.getString(R.string.resume_playing_message),
-                GalleryUtils.formatDuration(context, bookmark / 1000)));
-        builder.setOnCancelListener(new OnCancelListener() {
-            @Override
-            public void onCancel(DialogInterface dialog) {
-                onCompletion();
-            }
-        });
-        builder.setPositiveButton(
-                R.string.resume_playing_resume, new OnClickListener() {
-            @Override
-            public void onClick(DialogInterface dialog, int which) {
-                mVideoView.seekTo(bookmark);
-                startVideo();
-            }
-        });
-        builder.setNegativeButton(
-                R.string.resume_playing_restart, new OnClickListener() {
-            @Override
-            public void onClick(DialogInterface dialog, int which) {
-                startVideo();
-            }
-        });
-        builder.show();
-    }
-
-    public void onPause() {
-        mHasPaused = true;
-        mHandler.removeCallbacksAndMessages(null);
-        mVideoPosition = mVideoView.getCurrentPosition();
-        mBookmarker.setBookmark(mUri, mVideoPosition, mVideoView.getDuration());
-        mVideoView.suspend();
-        mResumeableTime = System.currentTimeMillis() + RESUMEABLE_TIMEOUT;
-    }
-
-    public void onResume() {
-        if (mHasPaused) {
-            mVideoView.seekTo(mVideoPosition);
-            mVideoView.resume();
-
-            // If we have slept for too long, pause the play
-            if (System.currentTimeMillis() > mResumeableTime) {
-                pauseVideo();
-            }
-        }
-        mHandler.post(mProgressChecker);
-    }
-
-    public void onDestroy() {
-        mVideoView.stopPlayback();
-        mAudioBecomingNoisyReceiver.unregister();
-    }
-
-    // This updates the time bar display (if necessary). It is called every
-    // second by mProgressChecker and also from places where the time bar needs
-    // to be updated immediately.
-    private int setProgress() {
-        if (mDragging || !mShowing) {
-            return 0;
-        }
-        int position = mVideoView.getCurrentPosition();
-        int duration = mVideoView.getDuration();
-        mController.setTimes(position, duration, 0, 0);
-        return position;
-    }
-
-    private void startVideo() {
-        // For streams that we expect to be slow to start up, show a
-        // progress spinner until playback starts.
-        String scheme = mUri.getScheme();
-        if ("http".equalsIgnoreCase(scheme) || "rtsp".equalsIgnoreCase(scheme)) {
-            mController.showLoading();
-            mHandler.removeCallbacks(mPlayingChecker);
-            mHandler.postDelayed(mPlayingChecker, 250);
-        } else {
-            mController.showPlaying();
-            mController.hide();
-        }
-
-        mVideoView.start();
-        setProgress();
-    }
-
-    private void playVideo() {
-        mVideoView.start();
-        mController.showPlaying();
-        setProgress();
-    }
-
-    private void pauseVideo() {
-        mVideoView.pause();
-        mController.showPaused();
-    }
-
-    // Below are notifications from VideoView
-    @Override
-    public boolean onError(MediaPlayer player, int arg1, int arg2) {
-        mHandler.removeCallbacksAndMessages(null);
-        // VideoView will show an error dialog if we return false, so no need
-        // to show more message.
-        mController.showErrorMessage("");
-        return false;
-    }
-
-    @Override
-    public void onCompletion(MediaPlayer mp) {
-        mController.showEnded();
-        onCompletion();
-    }
-
-    public void onCompletion() {
-    }
-
-    // Below are notifications from ControllerOverlay
-    @Override
-    public void onPlayPause() {
-        if (mVideoView.isPlaying()) {
-            pauseVideo();
-        } else {
-            playVideo();
-        }
-    }
-
-    @Override
-    public void onSeekStart() {
-        mDragging = true;
-    }
-
-    @Override
-    public void onSeekMove(int time) {
-        mVideoView.seekTo(time);
-    }
-
-    @Override
-    public void onSeekEnd(int time, int start, int end) {
-        mDragging = false;
-        mVideoView.seekTo(time);
-        setProgress();
-    }
-
-    @Override
-    public void onShown() {
-        mShowing = true;
-        setProgress();
-        showSystemUi(true);
-    }
-
-    @Override
-    public void onHidden() {
-        mShowing = false;
-        showSystemUi(false);
-    }
-
-    @Override
-    public void onReplay() {
-        startVideo();
-    }
-
-    // Below are key events passed from MovieActivity.
-    public boolean onKeyDown(int keyCode, KeyEvent event) {
-
-        // Some headsets will fire off 7-10 events on a single click
-        if (event.getRepeatCount() > 0) {
-            return isMediaKey(keyCode);
-        }
-
-        switch (keyCode) {
-            case KeyEvent.KEYCODE_HEADSETHOOK:
-            case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE:
-                if (mVideoView.isPlaying()) {
-                    pauseVideo();
-                } else {
-                    playVideo();
-                }
-                return true;
-            case KEYCODE_MEDIA_PAUSE:
-                if (mVideoView.isPlaying()) {
-                    pauseVideo();
-                }
-                return true;
-            case KEYCODE_MEDIA_PLAY:
-                if (!mVideoView.isPlaying()) {
-                    playVideo();
-                }
-                return true;
-            case KeyEvent.KEYCODE_MEDIA_PREVIOUS:
-            case KeyEvent.KEYCODE_MEDIA_NEXT:
-                // TODO: Handle next / previous accordingly, for now we're
-                // just consuming the events.
-                return true;
-        }
-        return false;
-    }
-
-    public boolean onKeyUp(int keyCode, KeyEvent event) {
-        return isMediaKey(keyCode);
-    }
-
-    private static boolean isMediaKey(int keyCode) {
-        return keyCode == KeyEvent.KEYCODE_HEADSETHOOK
-                || keyCode == KeyEvent.KEYCODE_MEDIA_PREVIOUS
-                || keyCode == KeyEvent.KEYCODE_MEDIA_NEXT
-                || keyCode == KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE
-                || keyCode == KeyEvent.KEYCODE_MEDIA_PLAY
-                || keyCode == KeyEvent.KEYCODE_MEDIA_PAUSE;
-    }
-
-    // We want to pause when the headset is unplugged.
-    private class AudioBecomingNoisyReceiver extends BroadcastReceiver {
-
-        public void register() {
-            mContext.registerReceiver(this,
-                    new IntentFilter(AudioManager.ACTION_AUDIO_BECOMING_NOISY));
-        }
-
-        public void unregister() {
-            mContext.unregisterReceiver(this);
-        }
-
-        @Override
-        public void onReceive(Context context, Intent intent) {
-            if (mVideoView.isPlaying()) pauseVideo();
-        }
-    }
-}
-
-class Bookmarker {
-    private static final String TAG = "Bookmarker";
-
-    private static final String BOOKMARK_CACHE_FILE = "bookmark";
-    private static final int BOOKMARK_CACHE_MAX_ENTRIES = 100;
-    private static final int BOOKMARK_CACHE_MAX_BYTES = 10 * 1024;
-    private static final int BOOKMARK_CACHE_VERSION = 1;
-
-    private static final int HALF_MINUTE = 30 * 1000;
-    private static final int TWO_MINUTES = 4 * HALF_MINUTE;
-
-    private final Context mContext;
-
-    public Bookmarker(Context context) {
-        mContext = context;
-    }
-
-    public void setBookmark(Uri uri, int bookmark, int duration) {
-        try {
-            BlobCache cache = CacheManager.getCache(mContext,
-                    BOOKMARK_CACHE_FILE, BOOKMARK_CACHE_MAX_ENTRIES,
-                    BOOKMARK_CACHE_MAX_BYTES, BOOKMARK_CACHE_VERSION);
-
-            ByteArrayOutputStream bos = new ByteArrayOutputStream();
-            DataOutputStream dos = new DataOutputStream(bos);
-            dos.writeUTF(uri.toString());
-            dos.writeInt(bookmark);
-            dos.writeInt(duration);
-            dos.flush();
-            cache.insert(uri.hashCode(), bos.toByteArray());
-        } catch (Throwable t) {
-            Log.w(TAG, "setBookmark failed", t);
-        }
-    }
-
-    public Integer getBookmark(Uri uri) {
-        try {
-            BlobCache cache = CacheManager.getCache(mContext,
-                    BOOKMARK_CACHE_FILE, BOOKMARK_CACHE_MAX_ENTRIES,
-                    BOOKMARK_CACHE_MAX_BYTES, BOOKMARK_CACHE_VERSION);
-
-            byte[] data = cache.lookup(uri.hashCode());
-            if (data == null) return null;
-
-            DataInputStream dis = new DataInputStream(
-                    new ByteArrayInputStream(data));
-
-            String uriString = DataInputStream.readUTF(dis);
-            int bookmark = dis.readInt();
-            int duration = dis.readInt();
-
-            if (!uriString.equals(uri.toString())) {
-                return null;
-            }
-
-            if ((bookmark < HALF_MINUTE) || (duration < TWO_MINUTES)
-                    || (bookmark > (duration - HALF_MINUTE))) {
-                return null;
-            }
-            return Integer.valueOf(bookmark);
-        } catch (Throwable t) {
-            Log.w(TAG, "getBookmark failed", t);
-        }
-        return null;
-    }
-}
diff --git a/src/com/android/gallery3d/app/MuteVideo.java b/src/com/android/gallery3d/app/MuteVideo.java
deleted file mode 100644
index d3f3aa5..0000000
--- a/src/com/android/gallery3d/app/MuteVideo.java
+++ /dev/null
@@ -1,104 +0,0 @@
-/*
- * 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.gallery3d.app;
-
-import android.app.Activity;
-import android.app.ProgressDialog;
-import android.content.Intent;
-import android.net.Uri;
-import android.os.Handler;
-import android.provider.MediaStore;
-import android.widget.Toast;
-
-import com.android.gallery3d.R;
-import com.android.gallery3d.data.MediaItem;
-import com.android.gallery3d.util.SaveVideoFileInfo;
-import com.android.gallery3d.util.SaveVideoFileUtils;
-
-import java.io.IOException;
-
-public class MuteVideo {
-
-    private ProgressDialog mMuteProgress;
-
-    private String mFilePath = null;
-    private Uri mUri = null;
-    private SaveVideoFileInfo mDstFileInfo = null;
-    private Activity mActivity = null;
-    private final Handler mHandler = new Handler();
-
-    final String TIME_STAMP_NAME = "'MUTE'_yyyyMMdd_HHmmss";
-
-    public MuteVideo(String filePath, Uri uri, Activity activity) {
-        mUri = uri;
-        mFilePath = filePath;
-        mActivity = activity;
-    }
-
-    public void muteInBackground() {
-        mDstFileInfo = SaveVideoFileUtils.getDstMp4FileInfo(TIME_STAMP_NAME,
-                mActivity.getContentResolver(), mUri,
-                mActivity.getString(R.string.folder_download));
-
-        showProgressDialog();
-        new Thread(new Runnable() {
-                @Override
-            public void run() {
-                try {
-                    VideoUtils.startMute(mFilePath, mDstFileInfo);
-                    SaveVideoFileUtils.insertContent(
-                            mDstFileInfo, mActivity.getContentResolver(), mUri);
-                } catch (IOException e) {
-                    Toast.makeText(mActivity, mActivity.getString(R.string.video_mute_err),
-                            Toast.LENGTH_SHORT).show();
-                }
-                // After muting is done, trigger the UI changed.
-                mHandler.post(new Runnable() {
-                        @Override
-                    public void run() {
-                        Toast.makeText(mActivity.getApplicationContext(),
-                                mActivity.getString(R.string.save_into,
-                                        mDstFileInfo.mFolderName),
-                                Toast.LENGTH_SHORT)
-                                .show();
-
-                        if (mMuteProgress != null) {
-                            mMuteProgress.dismiss();
-                            mMuteProgress = null;
-
-                            // Show the result only when the activity not
-                            // stopped.
-                            Intent intent = new Intent(android.content.Intent.ACTION_VIEW);
-                            intent.setDataAndType(Uri.fromFile(mDstFileInfo.mFile), "video/*");
-                            intent.putExtra(MediaStore.EXTRA_FINISH_ON_COMPLETION, false);
-                            mActivity.startActivity(intent);
-                        }
-                    }
-                });
-            }
-        }).start();
-    }
-
-    private void showProgressDialog() {
-        mMuteProgress = new ProgressDialog(mActivity);
-        mMuteProgress.setTitle(mActivity.getString(R.string.muting));
-        mMuteProgress.setMessage(mActivity.getString(R.string.please_wait));
-        mMuteProgress.setCancelable(false);
-        mMuteProgress.setCanceledOnTouchOutside(false);
-        mMuteProgress.show();
-    }
-}
diff --git a/src/com/android/gallery3d/app/NotificationIds.java b/src/com/android/gallery3d/app/NotificationIds.java
deleted file mode 100644
index d697d85..0000000
--- a/src/com/android/gallery3d/app/NotificationIds.java
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * Copyright (C) 2013 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.gallery3d.app;
-
-public class NotificationIds {
-    public static final int INGEST_NOTIFICATION_SCANNING = 10;
-    public static final int INGEST_NOTIFICATION_IMPORTING = 11;
-}
diff --git a/src/com/android/gallery3d/app/OrientationManager.java b/src/com/android/gallery3d/app/OrientationManager.java
deleted file mode 100644
index f2f632c..0000000
--- a/src/com/android/gallery3d/app/OrientationManager.java
+++ /dev/null
@@ -1,166 +0,0 @@
-/*
- * 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.gallery3d.app;
-
-import android.app.Activity;
-import android.content.ContentResolver;
-import android.content.Context;
-import android.content.pm.ActivityInfo;
-import android.content.res.Configuration;
-import android.provider.Settings;
-import android.view.OrientationEventListener;
-import android.view.Surface;
-
-import com.android.gallery3d.common.ApiHelper;
-import com.android.gallery3d.ui.OrientationSource;
-
-public class OrientationManager implements OrientationSource {
-    private static final String TAG = "OrientationManager";
-
-    // Orientation hysteresis amount used in rounding, in degrees
-    private static final int ORIENTATION_HYSTERESIS = 5;
-
-    private Activity mActivity;
-    private MyOrientationEventListener mOrientationListener;
-    // If the framework orientation is locked.
-    private boolean mOrientationLocked = false;
-
-    // This is true if "Settings -> Display -> Rotation Lock" is checked. We
-    // don't allow the orientation to be unlocked if the value is true.
-    private boolean mRotationLockedSetting = false;
-
-    public OrientationManager(Activity activity) {
-        mActivity = activity;
-        mOrientationListener = new MyOrientationEventListener(activity);
-    }
-
-    public void resume() {
-        ContentResolver resolver = mActivity.getContentResolver();
-        mRotationLockedSetting = Settings.System.getInt(
-                resolver, Settings.System.ACCELEROMETER_ROTATION, 0) != 1;
-        mOrientationListener.enable();
-    }
-
-    public void pause() {
-        mOrientationListener.disable();
-    }
-
-    ////////////////////////////////////////////////////////////////////////////
-    //  Orientation handling
-    //
-    //  We can choose to lock the framework orientation or not. If we lock the
-    //  framework orientation, we calculate a a compensation value according to
-    //  current device orientation and send it to listeners. If we don't lock
-    //  the framework orientation, we always set the compensation value to 0.
-    ////////////////////////////////////////////////////////////////////////////
-
-    // Lock the framework orientation to the current device orientation
-    public void lockOrientation() {
-        if (mOrientationLocked) return;
-        mOrientationLocked = true;
-        if (ApiHelper.HAS_ORIENTATION_LOCK) {
-            mActivity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LOCKED);
-        } else {
-            mActivity.setRequestedOrientation(calculateCurrentScreenOrientation());
-        }
-    }
-
-    // Unlock the framework orientation, so it can change when the device
-    // rotates.
-    public void unlockOrientation() {
-        if (!mOrientationLocked) return;
-        mOrientationLocked = false;
-        Log.d(TAG, "unlock orientation");
-        mActivity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR);
-    }
-
-    private int calculateCurrentScreenOrientation() {
-        int displayRotation = getDisplayRotation();
-        // Display rotation >= 180 means we need to use the REVERSE landscape/portrait
-        boolean standard = displayRotation < 180;
-        if (mActivity.getResources().getConfiguration().orientation
-                == Configuration.ORIENTATION_LANDSCAPE) {
-            return standard
-                    ? ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE
-                    : ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE;
-        } else {
-            if (displayRotation == 90 || displayRotation == 270) {
-                // If displayRotation = 90 or 270 then we are on a landscape
-                // device. On landscape devices, portrait is a 90 degree
-                // clockwise rotation from landscape, so we need
-                // to flip which portrait we pick as display rotation is counter clockwise
-                standard = !standard;
-            }
-            return standard
-                    ? ActivityInfo.SCREEN_ORIENTATION_PORTRAIT
-                    : ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT;
-        }
-    }
-
-    // This listens to the device orientation, so we can update the compensation.
-    private class MyOrientationEventListener extends OrientationEventListener {
-        public MyOrientationEventListener(Context context) {
-            super(context);
-        }
-
-        @Override
-        public void onOrientationChanged(int orientation) {
-            // We keep the last known orientation. So if the user first orient
-            // the camera then point the camera to floor or sky, we still have
-            // the correct orientation.
-            if (orientation == ORIENTATION_UNKNOWN) return;
-            orientation = roundOrientation(orientation, 0);
-        }
-    }
-
-    @Override
-    public int getDisplayRotation() {
-        return getDisplayRotation(mActivity);
-    }
-
-    @Override
-    public int getCompensation() {
-        return 0;
-    }
-
-    private static int roundOrientation(int orientation, int orientationHistory) {
-        boolean changeOrientation = false;
-        if (orientationHistory == OrientationEventListener.ORIENTATION_UNKNOWN) {
-            changeOrientation = true;
-        } else {
-            int dist = Math.abs(orientation - orientationHistory);
-            dist = Math.min(dist, 360 - dist);
-            changeOrientation = (dist >= 45 + ORIENTATION_HYSTERESIS);
-        }
-        if (changeOrientation) {
-            return ((orientation + 45) / 90 * 90) % 360;
-        }
-        return orientationHistory;
-    }
-
-    private static int getDisplayRotation(Activity activity) {
-        int rotation = activity.getWindowManager().getDefaultDisplay()
-                .getRotation();
-        switch (rotation) {
-            case Surface.ROTATION_0: return 0;
-            case Surface.ROTATION_90: return 90;
-            case Surface.ROTATION_180: return 180;
-            case Surface.ROTATION_270: return 270;
-        }
-        return 0;
-    }
-}
diff --git a/src/com/android/gallery3d/app/PackagesMonitor.java b/src/com/android/gallery3d/app/PackagesMonitor.java
deleted file mode 100644
index 9b2412f..0000000
--- a/src/com/android/gallery3d/app/PackagesMonitor.java
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * Copyright (C) 2010 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.gallery3d.app;
-
-import android.app.IntentService;
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.SharedPreferences;
-import android.preference.PreferenceManager;
-
-import com.android.gallery3d.picasasource.PicasaSource;
-import com.android.gallery3d.util.LightCycleHelper;
-
-public class PackagesMonitor extends BroadcastReceiver {
-    public static final String KEY_PACKAGES_VERSION  = "packages-version";
-
-    public synchronized static int getPackagesVersion(Context context) {
-        SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
-        return prefs.getInt(KEY_PACKAGES_VERSION, 1);
-    }
-
-    @Override
-    public void onReceive(final Context context, final Intent intent) {
-        intent.setClass(context, AsyncService.class);
-        context.startService(intent);
-    }
-
-    public static class AsyncService extends IntentService {
-        public AsyncService() {
-            super("GalleryPackagesMonitorAsync");
-        }
-
-        @Override
-        protected void onHandleIntent(Intent intent) {
-            onReceiveAsync(this, intent);
-        }
-    }
-
-    // Runs in a background thread.
-    private static void onReceiveAsync(Context context, Intent intent) {
-        SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
-
-        int version = prefs.getInt(KEY_PACKAGES_VERSION, 1);
-        prefs.edit().putInt(KEY_PACKAGES_VERSION, version + 1).commit();
-
-        String action = intent.getAction();
-        String packageName = intent.getData().getSchemeSpecificPart();
-        if (Intent.ACTION_PACKAGE_ADDED.equals(action)) {
-            PicasaSource.onPackageAdded(context, packageName);
-        } else if (Intent.ACTION_PACKAGE_REMOVED.equals(action)) {
-            PicasaSource.onPackageRemoved(context, packageName);
-        } else if (Intent.ACTION_PACKAGE_CHANGED.equals(action)) {
-            PicasaSource.onPackageChanged(context, packageName);
-        }
-    }
-}
diff --git a/src/com/android/gallery3d/app/PanoramaMetadataSupport.java b/src/com/android/gallery3d/app/PanoramaMetadataSupport.java
deleted file mode 100644
index ba0c9e7..0000000
--- a/src/com/android/gallery3d/app/PanoramaMetadataSupport.java
+++ /dev/null
@@ -1,93 +0,0 @@
-/*
- * 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.gallery3d.app;
-
-import com.android.gallery3d.data.MediaObject;
-import com.android.gallery3d.data.MediaObject.PanoramaSupportCallback;
-import com.android.gallery3d.data.PanoramaMetadataJob;
-import com.android.gallery3d.util.Future;
-import com.android.gallery3d.util.FutureListener;
-import com.android.gallery3d.util.LightCycleHelper;
-import com.android.gallery3d.util.LightCycleHelper.PanoramaMetadata;
-
-import java.util.ArrayList;
-
-/**
- * This class breaks out the off-thread panorama support checks so that the
- * complexity can be shared between UriImage and LocalImage, which need to
- * support panoramas.
- */
-public class PanoramaMetadataSupport implements FutureListener<PanoramaMetadata> {
-    private Object mLock = new Object();
-    private Future<PanoramaMetadata> mGetPanoMetadataTask;
-    private PanoramaMetadata mPanoramaMetadata;
-    private ArrayList<PanoramaSupportCallback> mCallbacksWaiting;
-    private MediaObject mMediaObject;
-
-    public PanoramaMetadataSupport(MediaObject mediaObject) {
-        mMediaObject = mediaObject;
-    }
-
-    public void getPanoramaSupport(GalleryApp app, PanoramaSupportCallback callback) {
-        synchronized (mLock) {
-            if (mPanoramaMetadata != null) {
-                callback.panoramaInfoAvailable(mMediaObject, mPanoramaMetadata.mUsePanoramaViewer,
-                        mPanoramaMetadata.mIsPanorama360);
-            } else {
-                if (mCallbacksWaiting == null) {
-                    mCallbacksWaiting = new ArrayList<PanoramaSupportCallback>();
-                    mGetPanoMetadataTask = app.getThreadPool().submit(
-                            new PanoramaMetadataJob(app.getAndroidContext(),
-                                    mMediaObject.getContentUri()), this);
-
-                }
-                mCallbacksWaiting.add(callback);
-            }
-        }
-    }
-
-    public void clearCachedValues() {
-        synchronized (mLock) {
-            if (mPanoramaMetadata != null) {
-                mPanoramaMetadata = null;
-            } else if (mGetPanoMetadataTask != null) {
-                mGetPanoMetadataTask.cancel();
-                for (PanoramaSupportCallback cb : mCallbacksWaiting) {
-                    cb.panoramaInfoAvailable(mMediaObject, false, false);
-                }
-                mGetPanoMetadataTask = null;
-                mCallbacksWaiting = null;
-            }
-        }
-    }
-
-    @Override
-    public void onFutureDone(Future<PanoramaMetadata> future) {
-        synchronized (mLock) {
-            mPanoramaMetadata = future.get();
-            if (mPanoramaMetadata == null) {
-                // Error getting panorama data from file. Treat as not panorama.
-                mPanoramaMetadata = LightCycleHelper.NOT_PANORAMA;
-            }
-            for (PanoramaSupportCallback cb : mCallbacksWaiting) {
-                cb.panoramaInfoAvailable(mMediaObject, mPanoramaMetadata.mUsePanoramaViewer,
-                        mPanoramaMetadata.mIsPanorama360);
-            }
-            mGetPanoMetadataTask = null;
-            mCallbacksWaiting = null;
-        }
-    }
-}
diff --git a/src/com/android/gallery3d/app/PhotoDataAdapter.java b/src/com/android/gallery3d/app/PhotoDataAdapter.java
deleted file mode 100644
index fd3a7cf..0000000
--- a/src/com/android/gallery3d/app/PhotoDataAdapter.java
+++ /dev/null
@@ -1,1133 +0,0 @@
-/*
- * Copyright (C) 2010 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.gallery3d.app;
-
-import android.graphics.Bitmap;
-import android.graphics.BitmapRegionDecoder;
-import android.os.Handler;
-import android.os.Message;
-
-import com.android.gallery3d.common.BitmapUtils;
-import com.android.gallery3d.common.Utils;
-import com.android.gallery3d.data.ContentListener;
-import com.android.gallery3d.data.LocalMediaItem;
-import com.android.gallery3d.data.MediaItem;
-import com.android.gallery3d.data.MediaObject;
-import com.android.gallery3d.data.MediaSet;
-import com.android.gallery3d.data.Path;
-import com.android.gallery3d.glrenderer.TiledTexture;
-import com.android.gallery3d.ui.PhotoView;
-import com.android.gallery3d.ui.ScreenNail;
-import com.android.gallery3d.ui.SynchronizedHandler;
-import com.android.gallery3d.ui.TileImageViewAdapter;
-import com.android.gallery3d.ui.TiledScreenNail;
-import com.android.gallery3d.util.Future;
-import com.android.gallery3d.util.FutureListener;
-import com.android.gallery3d.util.MediaSetUtils;
-import com.android.gallery3d.util.ThreadPool;
-import com.android.gallery3d.util.ThreadPool.Job;
-import com.android.gallery3d.util.ThreadPool.JobContext;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.concurrent.Callable;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.FutureTask;
-
-public class PhotoDataAdapter implements PhotoPage.Model {
-    @SuppressWarnings("unused")
-    private static final String TAG = "PhotoDataAdapter";
-
-    private static final int MSG_LOAD_START = 1;
-    private static final int MSG_LOAD_FINISH = 2;
-    private static final int MSG_RUN_OBJECT = 3;
-    private static final int MSG_UPDATE_IMAGE_REQUESTS = 4;
-
-    private static final int MIN_LOAD_COUNT = 16;
-    private static final int DATA_CACHE_SIZE = 256;
-    private static final int SCREEN_NAIL_MAX = PhotoView.SCREEN_NAIL_MAX;
-    private static final int IMAGE_CACHE_SIZE = 2 * SCREEN_NAIL_MAX + 1;
-
-    private static final int BIT_SCREEN_NAIL = 1;
-    private static final int BIT_FULL_IMAGE = 2;
-
-    // sImageFetchSeq is the fetching sequence for images.
-    // We want to fetch the current screennail first (offset = 0), the next
-    // screennail (offset = +1), then the previous screennail (offset = -1) etc.
-    // After all the screennail are fetched, we fetch the full images (only some
-    // of them because of we don't want to use too much memory).
-    private static ImageFetch[] sImageFetchSeq;
-
-    private static class ImageFetch {
-        int indexOffset;
-        int imageBit;
-        public ImageFetch(int offset, int bit) {
-            indexOffset = offset;
-            imageBit = bit;
-        }
-    }
-
-    static {
-        int k = 0;
-        sImageFetchSeq = new ImageFetch[1 + (IMAGE_CACHE_SIZE - 1) * 2 + 3];
-        sImageFetchSeq[k++] = new ImageFetch(0, BIT_SCREEN_NAIL);
-
-        for (int i = 1; i < IMAGE_CACHE_SIZE; ++i) {
-            sImageFetchSeq[k++] = new ImageFetch(i, BIT_SCREEN_NAIL);
-            sImageFetchSeq[k++] = new ImageFetch(-i, BIT_SCREEN_NAIL);
-        }
-
-        sImageFetchSeq[k++] = new ImageFetch(0, BIT_FULL_IMAGE);
-        sImageFetchSeq[k++] = new ImageFetch(1, BIT_FULL_IMAGE);
-        sImageFetchSeq[k++] = new ImageFetch(-1, BIT_FULL_IMAGE);
-    }
-
-    private final TileImageViewAdapter mTileProvider = new TileImageViewAdapter();
-
-    // PhotoDataAdapter caches MediaItems (data) and ImageEntries (image).
-    //
-    // The MediaItems are stored in the mData array, which has DATA_CACHE_SIZE
-    // entries. The valid index range are [mContentStart, mContentEnd). We keep
-    // mContentEnd - mContentStart <= DATA_CACHE_SIZE, so we can use
-    // (i % DATA_CACHE_SIZE) as index to the array.
-    //
-    // The valid MediaItem window size (mContentEnd - mContentStart) may be
-    // smaller than DATA_CACHE_SIZE because we only update the window and reload
-    // the MediaItems when there are significant changes to the window position
-    // (>= MIN_LOAD_COUNT).
-    private final MediaItem mData[] = new MediaItem[DATA_CACHE_SIZE];
-    private int mContentStart = 0;
-    private int mContentEnd = 0;
-
-    // The ImageCache is a Path-to-ImageEntry map. It only holds the
-    // ImageEntries in the range of [mActiveStart, mActiveEnd).  We also keep
-    // mActiveEnd - mActiveStart <= IMAGE_CACHE_SIZE.  Besides, the
-    // [mActiveStart, mActiveEnd) range must be contained within
-    // the [mContentStart, mContentEnd) range.
-    private HashMap<Path, ImageEntry> mImageCache =
-            new HashMap<Path, ImageEntry>();
-    private int mActiveStart = 0;
-    private int mActiveEnd = 0;
-
-    // mCurrentIndex is the "center" image the user is viewing. The change of
-    // mCurrentIndex triggers the data loading and image loading.
-    private int mCurrentIndex;
-
-    // mChanges keeps the version number (of MediaItem) about the images. If any
-    // of the version number changes, we notify the view. This is used after a
-    // database reload or mCurrentIndex changes.
-    private final long mChanges[] = new long[IMAGE_CACHE_SIZE];
-    // mPaths keeps the corresponding Path (of MediaItem) for the images. This
-    // is used to determine the item movement.
-    private final Path mPaths[] = new Path[IMAGE_CACHE_SIZE];
-
-    private final Handler mMainHandler;
-    private final ThreadPool mThreadPool;
-
-    private final PhotoView mPhotoView;
-    private final MediaSet mSource;
-    private ReloadTask mReloadTask;
-
-    private long mSourceVersion = MediaObject.INVALID_DATA_VERSION;
-    private int mSize = 0;
-    private Path mItemPath;
-    private int mCameraIndex;
-    private boolean mIsPanorama;
-    private boolean mIsStaticCamera;
-    private boolean mIsActive;
-    private boolean mNeedFullImage;
-    private int mFocusHintDirection = FOCUS_HINT_NEXT;
-    private Path mFocusHintPath = null;
-
-    public interface DataListener extends LoadingListener {
-        public void onPhotoChanged(int index, Path item);
-    }
-
-    private DataListener mDataListener;
-
-    private final SourceListener mSourceListener = new SourceListener();
-    private final TiledTexture.Uploader mUploader;
-
-    // The path of the current viewing item will be stored in mItemPath.
-    // If mItemPath is not null, mCurrentIndex is only a hint for where we
-    // can find the item. If mItemPath is null, then we use the mCurrentIndex to
-    // find the image being viewed. cameraIndex is the index of the camera
-    // preview. If cameraIndex < 0, there is no camera preview.
-    public PhotoDataAdapter(AbstractGalleryActivity activity, PhotoView view,
-            MediaSet mediaSet, Path itemPath, int indexHint, int cameraIndex,
-            boolean isPanorama, boolean isStaticCamera) {
-        mSource = Utils.checkNotNull(mediaSet);
-        mPhotoView = Utils.checkNotNull(view);
-        mItemPath = Utils.checkNotNull(itemPath);
-        mCurrentIndex = indexHint;
-        mCameraIndex = cameraIndex;
-        mIsPanorama = isPanorama;
-        mIsStaticCamera = isStaticCamera;
-        mThreadPool = activity.getThreadPool();
-        mNeedFullImage = true;
-
-        Arrays.fill(mChanges, MediaObject.INVALID_DATA_VERSION);
-
-        mUploader = new TiledTexture.Uploader(activity.getGLRoot());
-
-        mMainHandler = new SynchronizedHandler(activity.getGLRoot()) {
-            @SuppressWarnings("unchecked")
-            @Override
-            public void handleMessage(Message message) {
-                switch (message.what) {
-                    case MSG_RUN_OBJECT:
-                        ((Runnable) message.obj).run();
-                        return;
-                    case MSG_LOAD_START: {
-                        if (mDataListener != null) {
-                            mDataListener.onLoadingStarted();
-                        }
-                        return;
-                    }
-                    case MSG_LOAD_FINISH: {
-                        if (mDataListener != null) {
-                            mDataListener.onLoadingFinished(false);
-                        }
-                        return;
-                    }
-                    case MSG_UPDATE_IMAGE_REQUESTS: {
-                        updateImageRequests();
-                        return;
-                    }
-                    default: throw new AssertionError();
-                }
-            }
-        };
-
-        updateSlidingWindow();
-    }
-
-    private MediaItem getItemInternal(int index) {
-        if (index < 0 || index >= mSize) return null;
-        if (index >= mContentStart && index < mContentEnd) {
-            return mData[index % DATA_CACHE_SIZE];
-        }
-        return null;
-    }
-
-    private long getVersion(int index) {
-        MediaItem item = getItemInternal(index);
-        if (item == null) return MediaObject.INVALID_DATA_VERSION;
-        return item.getDataVersion();
-    }
-
-    private Path getPath(int index) {
-        MediaItem item = getItemInternal(index);
-        if (item == null) return null;
-        return item.getPath();
-    }
-
-    private void fireDataChange() {
-        // First check if data actually changed.
-        boolean changed = false;
-        for (int i = -SCREEN_NAIL_MAX; i <= SCREEN_NAIL_MAX; ++i) {
-            long newVersion = getVersion(mCurrentIndex + i);
-            if (mChanges[i + SCREEN_NAIL_MAX] != newVersion) {
-                mChanges[i + SCREEN_NAIL_MAX] = newVersion;
-                changed = true;
-            }
-        }
-
-        if (!changed) return;
-
-        // Now calculate the fromIndex array. fromIndex represents the item
-        // movement. It records the index where the picture come from. The
-        // special value Integer.MAX_VALUE means it's a new picture.
-        final int N = IMAGE_CACHE_SIZE;
-        int fromIndex[] = new int[N];
-
-        // Remember the old path array.
-        Path oldPaths[] = new Path[N];
-        System.arraycopy(mPaths, 0, oldPaths, 0, N);
-
-        // Update the mPaths array.
-        for (int i = 0; i < N; ++i) {
-            mPaths[i] = getPath(mCurrentIndex + i - SCREEN_NAIL_MAX);
-        }
-
-        // Calculate the fromIndex array.
-        for (int i = 0; i < N; i++) {
-            Path p = mPaths[i];
-            if (p == null) {
-                fromIndex[i] = Integer.MAX_VALUE;
-                continue;
-            }
-
-            // Try to find the same path in the old array
-            int j;
-            for (j = 0; j < N; j++) {
-                if (oldPaths[j] == p) {
-                    break;
-                }
-            }
-            fromIndex[i] = (j < N) ? j - SCREEN_NAIL_MAX : Integer.MAX_VALUE;
-        }
-
-        mPhotoView.notifyDataChange(fromIndex, -mCurrentIndex,
-                mSize - 1 - mCurrentIndex);
-    }
-
-    public void setDataListener(DataListener listener) {
-        mDataListener = listener;
-    }
-
-    private void updateScreenNail(Path path, Future<ScreenNail> future) {
-        ImageEntry entry = mImageCache.get(path);
-        ScreenNail screenNail = future.get();
-
-        if (entry == null || entry.screenNailTask != future) {
-            if (screenNail != null) screenNail.recycle();
-            return;
-        }
-
-        entry.screenNailTask = null;
-
-        // Combine the ScreenNails if we already have a BitmapScreenNail
-        if (entry.screenNail instanceof TiledScreenNail) {
-            TiledScreenNail original = (TiledScreenNail) entry.screenNail;
-            screenNail = original.combine(screenNail);
-        }
-
-        if (screenNail == null) {
-            entry.failToLoad = true;
-        } else {
-            entry.failToLoad = false;
-            entry.screenNail = screenNail;
-        }
-
-        for (int i = -SCREEN_NAIL_MAX; i <= SCREEN_NAIL_MAX; ++i) {
-            if (path == getPath(mCurrentIndex + i)) {
-                if (i == 0) updateTileProvider(entry);
-                mPhotoView.notifyImageChange(i);
-                break;
-            }
-        }
-        updateImageRequests();
-        updateScreenNailUploadQueue();
-    }
-
-    private void updateFullImage(Path path, Future<BitmapRegionDecoder> future) {
-        ImageEntry entry = mImageCache.get(path);
-        if (entry == null || entry.fullImageTask != future) {
-            BitmapRegionDecoder fullImage = future.get();
-            if (fullImage != null) fullImage.recycle();
-            return;
-        }
-
-        entry.fullImageTask = null;
-        entry.fullImage = future.get();
-        if (entry.fullImage != null) {
-            if (path == getPath(mCurrentIndex)) {
-                updateTileProvider(entry);
-                mPhotoView.notifyImageChange(0);
-            }
-        }
-        updateImageRequests();
-    }
-
-    @Override
-    public void resume() {
-        mIsActive = true;
-        TiledTexture.prepareResources();
-
-        mSource.addContentListener(mSourceListener);
-        updateImageCache();
-        updateImageRequests();
-
-        mReloadTask = new ReloadTask();
-        mReloadTask.start();
-
-        fireDataChange();
-    }
-
-    @Override
-    public void pause() {
-        mIsActive = false;
-
-        mReloadTask.terminate();
-        mReloadTask = null;
-
-        mSource.removeContentListener(mSourceListener);
-
-        for (ImageEntry entry : mImageCache.values()) {
-            if (entry.fullImageTask != null) entry.fullImageTask.cancel();
-            if (entry.screenNailTask != null) entry.screenNailTask.cancel();
-            if (entry.screenNail != null) entry.screenNail.recycle();
-        }
-        mImageCache.clear();
-        mTileProvider.clear();
-
-        mUploader.clear();
-        TiledTexture.freeResources();
-    }
-
-    private MediaItem getItem(int index) {
-        if (index < 0 || index >= mSize || !mIsActive) return null;
-        Utils.assertTrue(index >= mActiveStart && index < mActiveEnd);
-
-        if (index >= mContentStart && index < mContentEnd) {
-            return mData[index % DATA_CACHE_SIZE];
-        }
-        return null;
-    }
-
-    private void updateCurrentIndex(int index) {
-        if (mCurrentIndex == index) return;
-        mCurrentIndex = index;
-        updateSlidingWindow();
-
-        MediaItem item = mData[index % DATA_CACHE_SIZE];
-        mItemPath = item == null ? null : item.getPath();
-
-        updateImageCache();
-        updateImageRequests();
-        updateTileProvider();
-
-        if (mDataListener != null) {
-            mDataListener.onPhotoChanged(index, mItemPath);
-        }
-
-        fireDataChange();
-    }
-
-    private void uploadScreenNail(int offset) {
-        int index = mCurrentIndex + offset;
-        if (index < mActiveStart || index >= mActiveEnd) return;
-
-        MediaItem item = getItem(index);
-        if (item == null) return;
-
-        ImageEntry e = mImageCache.get(item.getPath());
-        if (e == null) return;
-
-        ScreenNail s = e.screenNail;
-        if (s instanceof TiledScreenNail) {
-            TiledTexture t = ((TiledScreenNail) s).getTexture();
-            if (t != null && !t.isReady()) mUploader.addTexture(t);
-        }
-    }
-
-    private void updateScreenNailUploadQueue() {
-        mUploader.clear();
-        uploadScreenNail(0);
-        for (int i = 1; i < IMAGE_CACHE_SIZE; ++i) {
-            uploadScreenNail(i);
-            uploadScreenNail(-i);
-        }
-    }
-
-    @Override
-    public void moveTo(int index) {
-        updateCurrentIndex(index);
-    }
-
-    @Override
-    public ScreenNail getScreenNail(int offset) {
-        int index = mCurrentIndex + offset;
-        if (index < 0 || index >= mSize || !mIsActive) return null;
-        Utils.assertTrue(index >= mActiveStart && index < mActiveEnd);
-
-        MediaItem item = getItem(index);
-        if (item == null) return null;
-
-        ImageEntry entry = mImageCache.get(item.getPath());
-        if (entry == null) return null;
-
-        // Create a default ScreenNail if the real one is not available yet,
-        // except for camera that a black screen is better than a gray tile.
-        if (entry.screenNail == null && !isCamera(offset)) {
-            entry.screenNail = newPlaceholderScreenNail(item);
-            if (offset == 0) updateTileProvider(entry);
-        }
-
-        return entry.screenNail;
-    }
-
-    @Override
-    public void getImageSize(int offset, PhotoView.Size size) {
-        MediaItem item = getItem(mCurrentIndex + offset);
-        if (item == null) {
-            size.width = 0;
-            size.height = 0;
-        } else {
-            size.width = item.getWidth();
-            size.height = item.getHeight();
-        }
-    }
-
-    @Override
-    public int getImageRotation(int offset) {
-        MediaItem item = getItem(mCurrentIndex + offset);
-        return (item == null) ? 0 : item.getFullImageRotation();
-    }
-
-    @Override
-    public void setNeedFullImage(boolean enabled) {
-        mNeedFullImage = enabled;
-        mMainHandler.sendEmptyMessage(MSG_UPDATE_IMAGE_REQUESTS);
-    }
-
-    @Override
-    public boolean isCamera(int offset) {
-        return mCurrentIndex + offset == mCameraIndex;
-    }
-
-    @Override
-    public boolean isPanorama(int offset) {
-        return isCamera(offset) && mIsPanorama;
-    }
-
-    @Override
-    public boolean isStaticCamera(int offset) {
-        return isCamera(offset) && mIsStaticCamera;
-    }
-
-    @Override
-    public boolean isVideo(int offset) {
-        MediaItem item = getItem(mCurrentIndex + offset);
-        return (item == null)
-                ? false
-                : item.getMediaType() == MediaItem.MEDIA_TYPE_VIDEO;
-    }
-
-    @Override
-    public boolean isDeletable(int offset) {
-        MediaItem item = getItem(mCurrentIndex + offset);
-        return (item == null)
-                ? false
-                : (item.getSupportedOperations() & MediaItem.SUPPORT_DELETE) != 0;
-    }
-
-    @Override
-    public int getLoadingState(int offset) {
-        ImageEntry entry = mImageCache.get(getPath(mCurrentIndex + offset));
-        if (entry == null) return LOADING_INIT;
-        if (entry.failToLoad) return LOADING_FAIL;
-        if (entry.screenNail != null) return LOADING_COMPLETE;
-        return LOADING_INIT;
-    }
-
-    @Override
-    public ScreenNail getScreenNail() {
-        return getScreenNail(0);
-    }
-
-    @Override
-    public int getImageHeight() {
-        return mTileProvider.getImageHeight();
-    }
-
-    @Override
-    public int getImageWidth() {
-        return mTileProvider.getImageWidth();
-    }
-
-    @Override
-    public int getLevelCount() {
-        return mTileProvider.getLevelCount();
-    }
-
-    @Override
-    public Bitmap getTile(int level, int x, int y, int tileSize) {
-        return mTileProvider.getTile(level, x, y, tileSize);
-    }
-
-    @Override
-    public boolean isEmpty() {
-        return mSize == 0;
-    }
-
-    @Override
-    public int getCurrentIndex() {
-        return mCurrentIndex;
-    }
-
-    @Override
-    public MediaItem getMediaItem(int offset) {
-        int index = mCurrentIndex + offset;
-        if (index >= mContentStart && index < mContentEnd) {
-            return mData[index % DATA_CACHE_SIZE];
-        }
-        return null;
-    }
-
-    @Override
-    public void setCurrentPhoto(Path path, int indexHint) {
-        if (mItemPath == path) return;
-        mItemPath = path;
-        mCurrentIndex = indexHint;
-        updateSlidingWindow();
-        updateImageCache();
-        fireDataChange();
-
-        // We need to reload content if the path doesn't match.
-        MediaItem item = getMediaItem(0);
-        if (item != null && item.getPath() != path) {
-            if (mReloadTask != null) mReloadTask.notifyDirty();
-        }
-    }
-
-    @Override
-    public void setFocusHintDirection(int direction) {
-        mFocusHintDirection = direction;
-    }
-
-    @Override
-    public void setFocusHintPath(Path path) {
-        mFocusHintPath = path;
-    }
-
-    private void updateTileProvider() {
-        ImageEntry entry = mImageCache.get(getPath(mCurrentIndex));
-        if (entry == null) { // in loading
-            mTileProvider.clear();
-        } else {
-            updateTileProvider(entry);
-        }
-    }
-
-    private void updateTileProvider(ImageEntry entry) {
-        ScreenNail screenNail = entry.screenNail;
-        BitmapRegionDecoder fullImage = entry.fullImage;
-        if (screenNail != null) {
-            if (fullImage != null) {
-                mTileProvider.setScreenNail(screenNail,
-                        fullImage.getWidth(), fullImage.getHeight());
-                mTileProvider.setRegionDecoder(fullImage);
-            } else {
-                int width = screenNail.getWidth();
-                int height = screenNail.getHeight();
-                mTileProvider.setScreenNail(screenNail, width, height);
-            }
-        } else {
-            mTileProvider.clear();
-        }
-    }
-
-    private void updateSlidingWindow() {
-        // 1. Update the image window
-        int start = Utils.clamp(mCurrentIndex - IMAGE_CACHE_SIZE / 2,
-                0, Math.max(0, mSize - IMAGE_CACHE_SIZE));
-        int end = Math.min(mSize, start + IMAGE_CACHE_SIZE);
-
-        if (mActiveStart == start && mActiveEnd == end) return;
-
-        mActiveStart = start;
-        mActiveEnd = end;
-
-        // 2. Update the data window
-        start = Utils.clamp(mCurrentIndex - DATA_CACHE_SIZE / 2,
-                0, Math.max(0, mSize - DATA_CACHE_SIZE));
-        end = Math.min(mSize, start + DATA_CACHE_SIZE);
-        if (mContentStart > mActiveStart || mContentEnd < mActiveEnd
-                || Math.abs(start - mContentStart) > MIN_LOAD_COUNT) {
-            for (int i = mContentStart; i < mContentEnd; ++i) {
-                if (i < start || i >= end) {
-                    mData[i % DATA_CACHE_SIZE] = null;
-                }
-            }
-            mContentStart = start;
-            mContentEnd = end;
-            if (mReloadTask != null) mReloadTask.notifyDirty();
-        }
-    }
-
-    private void updateImageRequests() {
-        if (!mIsActive) return;
-
-        int currentIndex = mCurrentIndex;
-        MediaItem item = mData[currentIndex % DATA_CACHE_SIZE];
-        if (item == null || item.getPath() != mItemPath) {
-            // current item mismatch - don't request image
-            return;
-        }
-
-        // 1. Find the most wanted request and start it (if not already started).
-        Future<?> task = null;
-        for (int i = 0; i < sImageFetchSeq.length; i++) {
-            int offset = sImageFetchSeq[i].indexOffset;
-            int bit = sImageFetchSeq[i].imageBit;
-            if (bit == BIT_FULL_IMAGE && !mNeedFullImage) continue;
-            task = startTaskIfNeeded(currentIndex + offset, bit);
-            if (task != null) break;
-        }
-
-        // 2. Cancel everything else.
-        for (ImageEntry entry : mImageCache.values()) {
-            if (entry.screenNailTask != null && entry.screenNailTask != task) {
-                entry.screenNailTask.cancel();
-                entry.screenNailTask = null;
-                entry.requestedScreenNail = MediaObject.INVALID_DATA_VERSION;
-            }
-            if (entry.fullImageTask != null && entry.fullImageTask != task) {
-                entry.fullImageTask.cancel();
-                entry.fullImageTask = null;
-                entry.requestedFullImage = MediaObject.INVALID_DATA_VERSION;
-            }
-        }
-    }
-
-    private class ScreenNailJob implements Job<ScreenNail> {
-        private MediaItem mItem;
-
-        public ScreenNailJob(MediaItem item) {
-            mItem = item;
-        }
-
-        @Override
-        public ScreenNail run(JobContext jc) {
-            // We try to get a ScreenNail first, if it fails, we fallback to get
-            // a Bitmap and then wrap it in a BitmapScreenNail instead.
-            ScreenNail s = mItem.getScreenNail();
-            if (s != null) return s;
-
-            // If this is a temporary item, don't try to get its bitmap because
-            // it won't be available. We will get its bitmap after a data reload.
-            if (isTemporaryItem(mItem)) {
-                return newPlaceholderScreenNail(mItem);
-            }
-
-            Bitmap bitmap = mItem.requestImage(MediaItem.TYPE_THUMBNAIL).run(jc);
-            if (jc.isCancelled()) return null;
-            if (bitmap != null) {
-                bitmap = BitmapUtils.rotateBitmap(bitmap,
-                    mItem.getRotation() - mItem.getFullImageRotation(), true);
-            }
-            return bitmap == null ? null : new TiledScreenNail(bitmap);
-        }
-    }
-
-    private class FullImageJob implements Job<BitmapRegionDecoder> {
-        private MediaItem mItem;
-
-        public FullImageJob(MediaItem item) {
-            mItem = item;
-        }
-
-        @Override
-        public BitmapRegionDecoder run(JobContext jc) {
-            if (isTemporaryItem(mItem)) {
-                return null;
-            }
-            return mItem.requestLargeImage().run(jc);
-        }
-    }
-
-    // Returns true if we think this is a temporary item created by Camera. A
-    // temporary item is an image or a video whose data is still being
-    // processed, but an incomplete entry is created first in MediaProvider, so
-    // we can display them (in grey tile) even if they are not saved to disk
-    // yet. When the image or video data is actually saved, we will get
-    // notification from MediaProvider, reload data, and show the actual image
-    // or video data.
-    private boolean isTemporaryItem(MediaItem mediaItem) {
-        // Must have camera to create a temporary item.
-        if (mCameraIndex < 0) return false;
-        // Must be an item in camera roll.
-        if (!(mediaItem instanceof LocalMediaItem)) return false;
-        LocalMediaItem item = (LocalMediaItem) mediaItem;
-        if (item.getBucketId() != MediaSetUtils.CAMERA_BUCKET_ID) return false;
-        // Must have no size, but must have width and height information
-        if (item.getSize() != 0) return false;
-        if (item.getWidth() == 0) return false;
-        if (item.getHeight() == 0) return false;
-        // Must be created in the last 10 seconds.
-        if (item.getDateInMs() - System.currentTimeMillis() > 10000) return false;
-        return true;
-    }
-
-    // Create a default ScreenNail when a ScreenNail is needed, but we don't yet
-    // have one available (because the image data is still being saved, or the
-    // Bitmap is still being loaded.
-    private ScreenNail newPlaceholderScreenNail(MediaItem item) {
-        int width = item.getWidth();
-        int height = item.getHeight();
-        return new TiledScreenNail(width, height);
-    }
-
-    // Returns the task if we started the task or the task is already started.
-    private Future<?> startTaskIfNeeded(int index, int which) {
-        if (index < mActiveStart || index >= mActiveEnd) return null;
-
-        ImageEntry entry = mImageCache.get(getPath(index));
-        if (entry == null) return null;
-        MediaItem item = mData[index % DATA_CACHE_SIZE];
-        Utils.assertTrue(item != null);
-        long version = item.getDataVersion();
-
-        if (which == BIT_SCREEN_NAIL && entry.screenNailTask != null
-                && entry.requestedScreenNail == version) {
-            return entry.screenNailTask;
-        } else if (which == BIT_FULL_IMAGE && entry.fullImageTask != null
-                && entry.requestedFullImage == version) {
-            return entry.fullImageTask;
-        }
-
-        if (which == BIT_SCREEN_NAIL && entry.requestedScreenNail != version) {
-            entry.requestedScreenNail = version;
-            entry.screenNailTask = mThreadPool.submit(
-                    new ScreenNailJob(item),
-                    new ScreenNailListener(item));
-            // request screen nail
-            return entry.screenNailTask;
-        }
-        if (which == BIT_FULL_IMAGE && entry.requestedFullImage != version
-                && (item.getSupportedOperations()
-                & MediaItem.SUPPORT_FULL_IMAGE) != 0) {
-            entry.requestedFullImage = version;
-            entry.fullImageTask = mThreadPool.submit(
-                    new FullImageJob(item),
-                    new FullImageListener(item));
-            // request full image
-            return entry.fullImageTask;
-        }
-        return null;
-    }
-
-    private void updateImageCache() {
-        HashSet<Path> toBeRemoved = new HashSet<Path>(mImageCache.keySet());
-        for (int i = mActiveStart; i < mActiveEnd; ++i) {
-            MediaItem item = mData[i % DATA_CACHE_SIZE];
-            if (item == null) continue;
-            Path path = item.getPath();
-            ImageEntry entry = mImageCache.get(path);
-            toBeRemoved.remove(path);
-            if (entry != null) {
-                if (Math.abs(i - mCurrentIndex) > 1) {
-                    if (entry.fullImageTask != null) {
-                        entry.fullImageTask.cancel();
-                        entry.fullImageTask = null;
-                    }
-                    entry.fullImage = null;
-                    entry.requestedFullImage = MediaObject.INVALID_DATA_VERSION;
-                }
-                if (entry.requestedScreenNail != item.getDataVersion()) {
-                    // This ScreenNail is outdated, we want to update it if it's
-                    // still a placeholder.
-                    if (entry.screenNail instanceof TiledScreenNail) {
-                        TiledScreenNail s = (TiledScreenNail) entry.screenNail;
-                        s.updatePlaceholderSize(
-                                item.getWidth(), item.getHeight());
-                    }
-                }
-            } else {
-                entry = new ImageEntry();
-                mImageCache.put(path, entry);
-            }
-        }
-
-        // Clear the data and requests for ImageEntries outside the new window.
-        for (Path path : toBeRemoved) {
-            ImageEntry entry = mImageCache.remove(path);
-            if (entry.fullImageTask != null) entry.fullImageTask.cancel();
-            if (entry.screenNailTask != null) entry.screenNailTask.cancel();
-            if (entry.screenNail != null) entry.screenNail.recycle();
-        }
-
-        updateScreenNailUploadQueue();
-    }
-
-    private class FullImageListener
-            implements Runnable, FutureListener<BitmapRegionDecoder> {
-        private final Path mPath;
-        private Future<BitmapRegionDecoder> mFuture;
-
-        public FullImageListener(MediaItem item) {
-            mPath = item.getPath();
-        }
-
-        @Override
-        public void onFutureDone(Future<BitmapRegionDecoder> future) {
-            mFuture = future;
-            mMainHandler.sendMessage(
-                    mMainHandler.obtainMessage(MSG_RUN_OBJECT, this));
-        }
-
-        @Override
-        public void run() {
-            updateFullImage(mPath, mFuture);
-        }
-    }
-
-    private class ScreenNailListener
-            implements Runnable, FutureListener<ScreenNail> {
-        private final Path mPath;
-        private Future<ScreenNail> mFuture;
-
-        public ScreenNailListener(MediaItem item) {
-            mPath = item.getPath();
-        }
-
-        @Override
-        public void onFutureDone(Future<ScreenNail> future) {
-            mFuture = future;
-            mMainHandler.sendMessage(
-                    mMainHandler.obtainMessage(MSG_RUN_OBJECT, this));
-        }
-
-        @Override
-        public void run() {
-            updateScreenNail(mPath, mFuture);
-        }
-    }
-
-    private static class ImageEntry {
-        public BitmapRegionDecoder fullImage;
-        public ScreenNail screenNail;
-        public Future<ScreenNail> screenNailTask;
-        public Future<BitmapRegionDecoder> fullImageTask;
-        public long requestedScreenNail = MediaObject.INVALID_DATA_VERSION;
-        public long requestedFullImage = MediaObject.INVALID_DATA_VERSION;
-        public boolean failToLoad = false;
-    }
-
-    private class SourceListener implements ContentListener {
-        @Override
-        public void onContentDirty() {
-            if (mReloadTask != null) mReloadTask.notifyDirty();
-        }
-    }
-
-    private <T> T executeAndWait(Callable<T> callable) {
-        FutureTask<T> task = new FutureTask<T>(callable);
-        mMainHandler.sendMessage(
-                mMainHandler.obtainMessage(MSG_RUN_OBJECT, task));
-        try {
-            return task.get();
-        } catch (InterruptedException e) {
-            return null;
-        } catch (ExecutionException e) {
-            throw new RuntimeException(e);
-        }
-    }
-
-    private static class UpdateInfo {
-        public long version;
-        public boolean reloadContent;
-        public Path target;
-        public int indexHint;
-        public int contentStart;
-        public int contentEnd;
-
-        public int size;
-        public ArrayList<MediaItem> items;
-    }
-
-    private class GetUpdateInfo implements Callable<UpdateInfo> {
-
-        private boolean needContentReload() {
-            for (int i = mContentStart, n = mContentEnd; i < n; ++i) {
-                if (mData[i % DATA_CACHE_SIZE] == null) return true;
-            }
-            MediaItem current = mData[mCurrentIndex % DATA_CACHE_SIZE];
-            return current == null || current.getPath() != mItemPath;
-        }
-
-        @Override
-        public UpdateInfo call() throws Exception {
-            // TODO: Try to load some data in first update
-            UpdateInfo info = new UpdateInfo();
-            info.version = mSourceVersion;
-            info.reloadContent = needContentReload();
-            info.target = mItemPath;
-            info.indexHint = mCurrentIndex;
-            info.contentStart = mContentStart;
-            info.contentEnd = mContentEnd;
-            info.size = mSize;
-            return info;
-        }
-    }
-
-    private class UpdateContent implements Callable<Void> {
-        UpdateInfo mUpdateInfo;
-
-        public UpdateContent(UpdateInfo updateInfo) {
-            mUpdateInfo = updateInfo;
-        }
-
-        @Override
-        public Void call() throws Exception {
-            UpdateInfo info = mUpdateInfo;
-            mSourceVersion = info.version;
-
-            if (info.size != mSize) {
-                mSize = info.size;
-                if (mContentEnd > mSize) mContentEnd = mSize;
-                if (mActiveEnd > mSize) mActiveEnd = mSize;
-            }
-
-            mCurrentIndex = info.indexHint;
-            updateSlidingWindow();
-
-            if (info.items != null) {
-                int start = Math.max(info.contentStart, mContentStart);
-                int end = Math.min(info.contentStart + info.items.size(), mContentEnd);
-                int dataIndex = start % DATA_CACHE_SIZE;
-                for (int i = start; i < end; ++i) {
-                    mData[dataIndex] = info.items.get(i - info.contentStart);
-                    if (++dataIndex == DATA_CACHE_SIZE) dataIndex = 0;
-                }
-            }
-
-            // update mItemPath
-            MediaItem current = mData[mCurrentIndex % DATA_CACHE_SIZE];
-            mItemPath = current == null ? null : current.getPath();
-
-            updateImageCache();
-            updateTileProvider();
-            updateImageRequests();
-
-            if (mDataListener != null) {
-                mDataListener.onPhotoChanged(mCurrentIndex, mItemPath);
-            }
-
-            fireDataChange();
-            return null;
-        }
-    }
-
-    private class ReloadTask extends Thread {
-        private volatile boolean mActive = true;
-        private volatile boolean mDirty = true;
-
-        private boolean mIsLoading = false;
-
-        private void updateLoading(boolean loading) {
-            if (mIsLoading == loading) return;
-            mIsLoading = loading;
-            mMainHandler.sendEmptyMessage(loading ? MSG_LOAD_START : MSG_LOAD_FINISH);
-        }
-
-        @Override
-        public void run() {
-            while (mActive) {
-                synchronized (this) {
-                    if (!mDirty && mActive) {
-                        updateLoading(false);
-                        Utils.waitWithoutInterrupt(this);
-                        continue;
-                    }
-                }
-                mDirty = false;
-                UpdateInfo info = executeAndWait(new GetUpdateInfo());
-                updateLoading(true);
-                long version = mSource.reload();
-                if (info.version != version) {
-                    info.reloadContent = true;
-                    info.size = mSource.getMediaItemCount();
-                }
-                if (!info.reloadContent) continue;
-                info.items = mSource.getMediaItem(
-                        info.contentStart, info.contentEnd);
-
-                int index = MediaSet.INDEX_NOT_FOUND;
-
-                // First try to focus on the given hint path if there is one.
-                if (mFocusHintPath != null) {
-                    index = findIndexOfPathInCache(info, mFocusHintPath);
-                    mFocusHintPath = null;
-                }
-
-                // Otherwise try to see if the currently focused item can be found.
-                if (index == MediaSet.INDEX_NOT_FOUND) {
-                    MediaItem item = findCurrentMediaItem(info);
-                    if (item != null && item.getPath() == info.target) {
-                        index = info.indexHint;
-                    } else {
-                        index = findIndexOfTarget(info);
-                    }
-                }
-
-                // The image has been deleted. Focus on the next image (keep
-                // mCurrentIndex unchanged) or the previous image (decrease
-                // mCurrentIndex by 1). In page mode we want to see the next
-                // image, so we focus on the next one. In film mode we want the
-                // later images to shift left to fill the empty space, so we
-                // focus on the previous image (so it will not move). In any
-                // case the index needs to be limited to [0, mSize).
-                if (index == MediaSet.INDEX_NOT_FOUND) {
-                    index = info.indexHint;
-                    int focusHintDirection = mFocusHintDirection;
-                    if (index == (mCameraIndex + 1)) {
-                        focusHintDirection = FOCUS_HINT_NEXT;
-                    }
-                    if (focusHintDirection == FOCUS_HINT_PREVIOUS
-                            && index > 0) {
-                        index--;
-                    }
-                }
-
-                // Don't change index if mSize == 0
-                if (mSize > 0) {
-                    if (index >= mSize) index = mSize - 1;
-                }
-
-                info.indexHint = index;
-
-                executeAndWait(new UpdateContent(info));
-            }
-        }
-
-        public synchronized void notifyDirty() {
-            mDirty = true;
-            notifyAll();
-        }
-
-        public synchronized void terminate() {
-            mActive = false;
-            notifyAll();
-        }
-
-        private MediaItem findCurrentMediaItem(UpdateInfo info) {
-            ArrayList<MediaItem> items = info.items;
-            int index = info.indexHint - info.contentStart;
-            return index < 0 || index >= items.size() ? null : items.get(index);
-        }
-
-        private int findIndexOfTarget(UpdateInfo info) {
-            if (info.target == null) return info.indexHint;
-            ArrayList<MediaItem> items = info.items;
-
-            // First, try to find the item in the data just loaded
-            if (items != null) {
-                int i = findIndexOfPathInCache(info, info.target);
-                if (i != MediaSet.INDEX_NOT_FOUND) return i;
-            }
-
-            // Not found, find it in mSource.
-            return mSource.getIndexOfItem(info.target, info.indexHint);
-        }
-
-        private int findIndexOfPathInCache(UpdateInfo info, Path path) {
-            ArrayList<MediaItem> items = info.items;
-            for (int i = 0, n = items.size(); i < n; ++i) {
-                MediaItem item = items.get(i);
-                if (item != null && item.getPath() == path) {
-                    return i + info.contentStart;
-                }
-            }
-            return MediaSet.INDEX_NOT_FOUND;
-        }
-    }
-}
diff --git a/src/com/android/gallery3d/app/PhotoPage.java b/src/com/android/gallery3d/app/PhotoPage.java
deleted file mode 100644
index 7a71e91..0000000
--- a/src/com/android/gallery3d/app/PhotoPage.java
+++ /dev/null
@@ -1,1571 +0,0 @@
-/*
- * Copyright (C) 2010 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.gallery3d.app;
-
-import android.annotation.TargetApi;
-import android.app.ActionBar.OnMenuVisibilityListener;
-import android.app.Activity;
-import android.content.ActivityNotFoundException;
-import android.content.Context;
-import android.content.Intent;
-import android.content.pm.PackageManager;
-import android.content.res.Configuration;
-import android.graphics.Rect;
-import android.net.Uri;
-import android.nfc.NfcAdapter;
-import android.nfc.NfcAdapter.CreateBeamUrisCallback;
-import android.nfc.NfcEvent;
-import android.os.Bundle;
-import android.os.Handler;
-import android.os.Message;
-import android.os.SystemClock;
-import android.view.Menu;
-import android.view.MenuItem;
-import android.widget.RelativeLayout;
-import android.widget.ShareActionProvider;
-import android.widget.Toast;
-
-import com.android.camera.CameraActivity;
-import com.android.camera.ProxyLauncher;
-import com.android.gallery3d.R;
-import com.android.gallery3d.common.ApiHelper;
-import com.android.gallery3d.data.ComboAlbum;
-import com.android.gallery3d.data.DataManager;
-import com.android.gallery3d.data.FilterDeleteSet;
-import com.android.gallery3d.data.FilterSource;
-import com.android.gallery3d.data.LocalImage;
-import com.android.gallery3d.data.MediaDetails;
-import com.android.gallery3d.data.MediaItem;
-import com.android.gallery3d.data.MediaObject;
-import com.android.gallery3d.data.MediaObject.PanoramaSupportCallback;
-import com.android.gallery3d.data.MediaSet;
-import com.android.gallery3d.data.Path;
-import com.android.gallery3d.data.SecureAlbum;
-import com.android.gallery3d.data.SecureSource;
-import com.android.gallery3d.data.SnailAlbum;
-import com.android.gallery3d.data.SnailItem;
-import com.android.gallery3d.data.SnailSource;
-import com.android.gallery3d.filtershow.FilterShowActivity;
-import com.android.gallery3d.filtershow.crop.CropActivity;
-import com.android.gallery3d.picasasource.PicasaSource;
-import com.android.gallery3d.ui.DetailsHelper;
-import com.android.gallery3d.ui.DetailsHelper.CloseListener;
-import com.android.gallery3d.ui.DetailsHelper.DetailsSource;
-import com.android.gallery3d.ui.GLView;
-import com.android.gallery3d.ui.MenuExecutor;
-import com.android.gallery3d.ui.PhotoView;
-import com.android.gallery3d.ui.SelectionManager;
-import com.android.gallery3d.ui.SynchronizedHandler;
-import com.android.gallery3d.util.GalleryUtils;
-import com.android.gallery3d.util.UsageStatistics;
-
-public abstract class PhotoPage extends ActivityState implements
-        PhotoView.Listener, AppBridge.Server, ShareActionProvider.OnShareTargetSelectedListener,
-        PhotoPageBottomControls.Delegate, GalleryActionBar.OnAlbumModeSelectedListener {
-    private static final String TAG = "PhotoPage";
-
-    private static final int MSG_HIDE_BARS = 1;
-    private static final int MSG_ON_FULL_SCREEN_CHANGED = 4;
-    private static final int MSG_UPDATE_ACTION_BAR = 5;
-    private static final int MSG_UNFREEZE_GLROOT = 6;
-    private static final int MSG_WANT_BARS = 7;
-    private static final int MSG_REFRESH_BOTTOM_CONTROLS = 8;
-    private static final int MSG_ON_CAMERA_CENTER = 9;
-    private static final int MSG_ON_PICTURE_CENTER = 10;
-    private static final int MSG_REFRESH_IMAGE = 11;
-    private static final int MSG_UPDATE_PHOTO_UI = 12;
-    private static final int MSG_UPDATE_PROGRESS = 13;
-    private static final int MSG_UPDATE_DEFERRED = 14;
-    private static final int MSG_UPDATE_SHARE_URI = 15;
-    private static final int MSG_UPDATE_PANORAMA_UI = 16;
-
-    private static final int HIDE_BARS_TIMEOUT = 3500;
-    private static final int UNFREEZE_GLROOT_TIMEOUT = 250;
-
-    private static final int REQUEST_SLIDESHOW = 1;
-    private static final int REQUEST_CROP = 2;
-    private static final int REQUEST_CROP_PICASA = 3;
-    private static final int REQUEST_EDIT = 4;
-    private static final int REQUEST_PLAY_VIDEO = 5;
-    private static final int REQUEST_TRIM = 6;
-
-    public static final String KEY_MEDIA_SET_PATH = "media-set-path";
-    public static final String KEY_MEDIA_ITEM_PATH = "media-item-path";
-    public static final String KEY_INDEX_HINT = "index-hint";
-    public static final String KEY_OPEN_ANIMATION_RECT = "open-animation-rect";
-    public static final String KEY_APP_BRIDGE = "app-bridge";
-    public static final String KEY_TREAT_BACK_AS_UP = "treat-back-as-up";
-    public static final String KEY_START_IN_FILMSTRIP = "start-in-filmstrip";
-    public static final String KEY_RETURN_INDEX_HINT = "return-index-hint";
-    public static final String KEY_SHOW_WHEN_LOCKED = "show_when_locked";
-    public static final String KEY_IN_CAMERA_ROLL = "in_camera_roll";
-
-    public static final String KEY_ALBUMPAGE_TRANSITION = "albumpage-transition";
-    public static final int MSG_ALBUMPAGE_NONE = 0;
-    public static final int MSG_ALBUMPAGE_STARTED = 1;
-    public static final int MSG_ALBUMPAGE_RESUMED = 2;
-    public static final int MSG_ALBUMPAGE_PICKED = 4;
-
-    public static final String ACTION_NEXTGEN_EDIT = "action_nextgen_edit";
-    public static final String ACTION_SIMPLE_EDIT = "action_simple_edit";
-
-    private GalleryApp mApplication;
-    private SelectionManager mSelectionManager;
-
-    private PhotoView mPhotoView;
-    private PhotoPage.Model mModel;
-    private DetailsHelper mDetailsHelper;
-    private boolean mShowDetails;
-
-    // mMediaSet could be null if there is no KEY_MEDIA_SET_PATH supplied.
-    // E.g., viewing a photo in gmail attachment
-    private FilterDeleteSet mMediaSet;
-
-    // The mediaset used by camera launched from secure lock screen.
-    private SecureAlbum mSecureAlbum;
-
-    private int mCurrentIndex = 0;
-    private Handler mHandler;
-    private boolean mShowBars = true;
-    private volatile boolean mActionBarAllowed = true;
-    private GalleryActionBar mActionBar;
-    private boolean mIsMenuVisible;
-    private boolean mHaveImageEditor;
-    private PhotoPageBottomControls mBottomControls;
-    private PhotoPageProgressBar mProgressBar;
-    private MediaItem mCurrentPhoto = null;
-    private MenuExecutor mMenuExecutor;
-    private boolean mIsActive;
-    private boolean mShowSpinner;
-    private String mSetPathString;
-    // This is the original mSetPathString before adding the camera preview item.
-    private String mOriginalSetPathString;
-    private AppBridge mAppBridge;
-    private SnailItem mScreenNailItem;
-    private SnailAlbum mScreenNailSet;
-    private OrientationManager mOrientationManager;
-    private boolean mTreatBackAsUp;
-    private boolean mStartInFilmstrip;
-    private boolean mHasCameraScreennailOrPlaceholder = false;
-    private boolean mRecenterCameraOnResume = true;
-
-    // These are only valid after the panorama callback
-    private boolean mIsPanorama;
-    private boolean mIsPanorama360;
-
-    private long mCameraSwitchCutoff = 0;
-    private boolean mSkipUpdateCurrentPhoto = false;
-    private static final long CAMERA_SWITCH_CUTOFF_THRESHOLD_MS = 300;
-
-    private static final long DEFERRED_UPDATE_MS = 250;
-    private boolean mDeferredUpdateWaiting = false;
-    private long mDeferUpdateUntil = Long.MAX_VALUE;
-
-    // The item that is deleted (but it can still be undeleted before commiting)
-    private Path mDeletePath;
-    private boolean mDeleteIsFocus;  // whether the deleted item was in focus
-
-    private Uri[] mNfcPushUris = new Uri[1];
-
-    private final MyMenuVisibilityListener mMenuVisibilityListener =
-            new MyMenuVisibilityListener();
-    private UpdateProgressListener mProgressListener;
-
-    private final PanoramaSupportCallback mUpdatePanoramaMenuItemsCallback = new PanoramaSupportCallback() {
-        @Override
-        public void panoramaInfoAvailable(MediaObject mediaObject, boolean isPanorama,
-                boolean isPanorama360) {
-            if (mediaObject == mCurrentPhoto) {
-                mHandler.obtainMessage(MSG_UPDATE_PANORAMA_UI, isPanorama360 ? 1 : 0, 0,
-                        mediaObject).sendToTarget();
-            }
-        }
-    };
-
-    private final PanoramaSupportCallback mRefreshBottomControlsCallback = new PanoramaSupportCallback() {
-        @Override
-        public void panoramaInfoAvailable(MediaObject mediaObject, boolean isPanorama,
-                boolean isPanorama360) {
-            if (mediaObject == mCurrentPhoto) {
-                mHandler.obtainMessage(MSG_REFRESH_BOTTOM_CONTROLS, isPanorama ? 1 : 0, isPanorama360 ? 1 : 0,
-                        mediaObject).sendToTarget();
-            }
-        }
-    };
-
-    private final PanoramaSupportCallback mUpdateShareURICallback = new PanoramaSupportCallback() {
-        @Override
-        public void panoramaInfoAvailable(MediaObject mediaObject, boolean isPanorama,
-                boolean isPanorama360) {
-            if (mediaObject == mCurrentPhoto) {
-                mHandler.obtainMessage(MSG_UPDATE_SHARE_URI, isPanorama360 ? 1 : 0, 0, mediaObject)
-                        .sendToTarget();
-            }
-        }
-    };
-
-    public static interface Model extends PhotoView.Model {
-        public void resume();
-        public void pause();
-        public boolean isEmpty();
-        public void setCurrentPhoto(Path path, int indexHint);
-    }
-
-    private class MyMenuVisibilityListener implements OnMenuVisibilityListener {
-        @Override
-        public void onMenuVisibilityChanged(boolean isVisible) {
-            mIsMenuVisible = isVisible;
-            refreshHidingMessage();
-        }
-    }
-
-    private class UpdateProgressListener implements StitchingChangeListener {
-
-        @Override
-        public void onStitchingResult(Uri uri) {
-            sendUpdate(uri, MSG_REFRESH_IMAGE);
-        }
-
-        @Override
-        public void onStitchingQueued(Uri uri) {
-            sendUpdate(uri, MSG_UPDATE_PROGRESS);
-        }
-
-        @Override
-        public void onStitchingProgress(Uri uri, final int progress) {
-            sendUpdate(uri, MSG_UPDATE_PROGRESS);
-        }
-
-        private void sendUpdate(Uri uri, int message) {
-            MediaObject currentPhoto = mCurrentPhoto;
-            boolean isCurrentPhoto = currentPhoto instanceof LocalImage
-                    && currentPhoto.getContentUri().equals(uri);
-            if (isCurrentPhoto) {
-                mHandler.sendEmptyMessage(message);
-            }
-        }
-    };
-
-    @Override
-    protected int getBackgroundColorId() {
-        return R.color.photo_background;
-    }
-
-    private final GLView mRootPane = new GLView() {
-        @Override
-        protected void onLayout(
-                boolean changed, int left, int top, int right, int bottom) {
-            mPhotoView.layout(0, 0, right - left, bottom - top);
-            if (mShowDetails) {
-                mDetailsHelper.layout(left, mActionBar.getHeight(), right, bottom);
-            }
-        }
-    };
-
-    @Override
-    public void onCreate(Bundle data, Bundle restoreState) {
-        super.onCreate(data, restoreState);
-        mActionBar = mActivity.getGalleryActionBar();
-        mSelectionManager = new SelectionManager(mActivity, false);
-        mMenuExecutor = new MenuExecutor(mActivity, mSelectionManager);
-
-        mPhotoView = new PhotoView(mActivity);
-        mPhotoView.setListener(this);
-        mRootPane.addComponent(mPhotoView);
-        mApplication = (GalleryApp) ((Activity) mActivity).getApplication();
-        mOrientationManager = mActivity.getOrientationManager();
-        mActivity.getGLRoot().setOrientationSource(mOrientationManager);
-
-        mHandler = new SynchronizedHandler(mActivity.getGLRoot()) {
-            @Override
-            public void handleMessage(Message message) {
-                switch (message.what) {
-                    case MSG_HIDE_BARS: {
-                        hideBars();
-                        break;
-                    }
-                    case MSG_REFRESH_BOTTOM_CONTROLS: {
-                        if (mCurrentPhoto == message.obj && mBottomControls != null) {
-                            mIsPanorama = message.arg1 == 1;
-                            mIsPanorama360 = message.arg2 == 1;
-                            mBottomControls.refresh();
-                        }
-                        break;
-                    }
-                    case MSG_ON_FULL_SCREEN_CHANGED: {
-                        if (mAppBridge != null) {
-                            mAppBridge.onFullScreenChanged(message.arg1 == 1);
-                        }
-                        break;
-                    }
-                    case MSG_UPDATE_ACTION_BAR: {
-                        updateBars();
-                        break;
-                    }
-                    case MSG_WANT_BARS: {
-                        wantBars();
-                        break;
-                    }
-                    case MSG_UNFREEZE_GLROOT: {
-                        mActivity.getGLRoot().unfreeze();
-                        break;
-                    }
-                    case MSG_UPDATE_DEFERRED: {
-                        long nextUpdate = mDeferUpdateUntil - SystemClock.uptimeMillis();
-                        if (nextUpdate <= 0) {
-                            mDeferredUpdateWaiting = false;
-                            updateUIForCurrentPhoto();
-                        } else {
-                            mHandler.sendEmptyMessageDelayed(MSG_UPDATE_DEFERRED, nextUpdate);
-                        }
-                        break;
-                    }
-                    case MSG_ON_CAMERA_CENTER: {
-                        mSkipUpdateCurrentPhoto = false;
-                        boolean stayedOnCamera = false;
-                        if (!mPhotoView.getFilmMode()) {
-                            stayedOnCamera = true;
-                        } else if (SystemClock.uptimeMillis() < mCameraSwitchCutoff &&
-                                mMediaSet.getMediaItemCount() > 1) {
-                            mPhotoView.switchToImage(1);
-                        } else {
-                            if (mAppBridge != null) mPhotoView.setFilmMode(false);
-                            stayedOnCamera = true;
-                        }
-
-                        if (stayedOnCamera) {
-                            if (mAppBridge == null && mMediaSet.getTotalMediaItemCount() > 1) {
-                                launchCamera();
-                                /* We got here by swiping from photo 1 to the
-                                   placeholder, so make it be the thing that
-                                   is in focus when the user presses back from
-                                   the camera app */
-                                mPhotoView.switchToImage(1);
-                            } else {
-                                updateBars();
-                                updateCurrentPhoto(mModel.getMediaItem(0));
-                            }
-                        }
-                        break;
-                    }
-                    case MSG_ON_PICTURE_CENTER: {
-                        if (!mPhotoView.getFilmMode() && mCurrentPhoto != null
-                                && (mCurrentPhoto.getSupportedOperations() & MediaObject.SUPPORT_ACTION) != 0) {
-                            mPhotoView.setFilmMode(true);
-                        }
-                        break;
-                    }
-                    case MSG_REFRESH_IMAGE: {
-                        final MediaItem photo = mCurrentPhoto;
-                        mCurrentPhoto = null;
-                        updateCurrentPhoto(photo);
-                        break;
-                    }
-                    case MSG_UPDATE_PHOTO_UI: {
-                        updateUIForCurrentPhoto();
-                        break;
-                    }
-                    case MSG_UPDATE_PROGRESS: {
-                        updateProgressBar();
-                        break;
-                    }
-                    case MSG_UPDATE_SHARE_URI: {
-                        if (mCurrentPhoto == message.obj) {
-                            boolean isPanorama360 = message.arg1 != 0;
-                            Uri contentUri = mCurrentPhoto.getContentUri();
-                            Intent panoramaIntent = null;
-                            if (isPanorama360) {
-                                panoramaIntent = createSharePanoramaIntent(contentUri);
-                            }
-                            Intent shareIntent = createShareIntent(mCurrentPhoto);
-
-                            mActionBar.setShareIntents(panoramaIntent, shareIntent, PhotoPage.this);
-                            setNfcBeamPushUri(contentUri);
-                        }
-                        break;
-                    }
-                    case MSG_UPDATE_PANORAMA_UI: {
-                        if (mCurrentPhoto == message.obj) {
-                            boolean isPanorama360 = message.arg1 != 0;
-                            updatePanoramaUI(isPanorama360);
-                        }
-                        break;
-                    }
-                    default: throw new AssertionError(message.what);
-                }
-            }
-        };
-
-        mSetPathString = data.getString(KEY_MEDIA_SET_PATH);
-        mOriginalSetPathString = mSetPathString;
-        setupNfcBeamPush();
-        String itemPathString = data.getString(KEY_MEDIA_ITEM_PATH);
-        Path itemPath = itemPathString != null ?
-                Path.fromString(data.getString(KEY_MEDIA_ITEM_PATH)) :
-                    null;
-        mTreatBackAsUp = data.getBoolean(KEY_TREAT_BACK_AS_UP, false);
-        mStartInFilmstrip = data.getBoolean(KEY_START_IN_FILMSTRIP, false);
-        boolean inCameraRoll = data.getBoolean(KEY_IN_CAMERA_ROLL, false);
-        mCurrentIndex = data.getInt(KEY_INDEX_HINT, 0);
-        if (mSetPathString != null) {
-            mShowSpinner = true;
-            mAppBridge = (AppBridge) data.getParcelable(KEY_APP_BRIDGE);
-            if (mAppBridge != null) {
-                mShowBars = false;
-                mHasCameraScreennailOrPlaceholder = true;
-                mAppBridge.setServer(this);
-
-                // Get the ScreenNail from AppBridge and register it.
-                int id = SnailSource.newId();
-                Path screenNailSetPath = SnailSource.getSetPath(id);
-                Path screenNailItemPath = SnailSource.getItemPath(id);
-                mScreenNailSet = (SnailAlbum) mActivity.getDataManager()
-                        .getMediaObject(screenNailSetPath);
-                mScreenNailItem = (SnailItem) mActivity.getDataManager()
-                        .getMediaObject(screenNailItemPath);
-                mScreenNailItem.setScreenNail(mAppBridge.attachScreenNail());
-
-                if (data.getBoolean(KEY_SHOW_WHEN_LOCKED, false)) {
-                    // Set the flag to be on top of the lock screen.
-                    mFlags |= FLAG_SHOW_WHEN_LOCKED;
-                }
-
-                // Don't display "empty album" action item for capture intents.
-                if (!mSetPathString.equals("/local/all/0")) {
-                    // Check if the path is a secure album.
-                    if (SecureSource.isSecurePath(mSetPathString)) {
-                        mSecureAlbum = (SecureAlbum) mActivity.getDataManager()
-                                .getMediaSet(mSetPathString);
-                        mShowSpinner = false;
-                    }
-                    mSetPathString = "/filter/empty/{"+mSetPathString+"}";
-                }
-
-                // Combine the original MediaSet with the one for ScreenNail
-                // from AppBridge.
-                mSetPathString = "/combo/item/{" + screenNailSetPath +
-                        "," + mSetPathString + "}";
-
-                // Start from the screen nail.
-                itemPath = screenNailItemPath;
-            } else if (inCameraRoll && GalleryUtils.isCameraAvailable(mActivity)) {
-                mSetPathString = "/combo/item/{" + FilterSource.FILTER_CAMERA_SHORTCUT +
-                        "," + mSetPathString + "}";
-                mCurrentIndex++;
-                mHasCameraScreennailOrPlaceholder = true;
-            }
-
-            MediaSet originalSet = mActivity.getDataManager()
-                    .getMediaSet(mSetPathString);
-            if (mHasCameraScreennailOrPlaceholder && originalSet instanceof ComboAlbum) {
-                // Use the name of the camera album rather than the default
-                // ComboAlbum behavior
-                ((ComboAlbum) originalSet).useNameOfChild(1);
-            }
-            mSelectionManager.setSourceMediaSet(originalSet);
-            mSetPathString = "/filter/delete/{" + mSetPathString + "}";
-            mMediaSet = (FilterDeleteSet) mActivity.getDataManager()
-                    .getMediaSet(mSetPathString);
-            if (mMediaSet == null) {
-                Log.w(TAG, "failed to restore " + mSetPathString);
-            }
-            if (itemPath == null) {
-                int mediaItemCount = mMediaSet.getMediaItemCount();
-                if (mediaItemCount > 0) {
-                    if (mCurrentIndex >= mediaItemCount) mCurrentIndex = 0;
-                    itemPath = mMediaSet.getMediaItem(mCurrentIndex, 1)
-                        .get(0).getPath();
-                } else {
-                    // Bail out, PhotoPage can't load on an empty album
-                    return;
-                }
-            }
-            PhotoDataAdapter pda = new PhotoDataAdapter(
-                    mActivity, mPhotoView, mMediaSet, itemPath, mCurrentIndex,
-                    mAppBridge == null ? -1 : 0,
-                    mAppBridge == null ? false : mAppBridge.isPanorama(),
-                    mAppBridge == null ? false : mAppBridge.isStaticCamera());
-            mModel = pda;
-            mPhotoView.setModel(mModel);
-
-            pda.setDataListener(new PhotoDataAdapter.DataListener() {
-
-                @Override
-                public void onPhotoChanged(int index, Path item) {
-                    int oldIndex = mCurrentIndex;
-                    mCurrentIndex = index;
-
-                    if (mHasCameraScreennailOrPlaceholder) {
-                        if (mCurrentIndex > 0) {
-                            mSkipUpdateCurrentPhoto = false;
-                        }
-
-                        if (oldIndex == 0 && mCurrentIndex > 0
-                                && !mPhotoView.getFilmMode()) {
-                            mPhotoView.setFilmMode(true);
-                            if (mAppBridge != null) {
-                                UsageStatistics.onEvent("CameraToFilmstrip",
-                                        UsageStatistics.TRANSITION_SWIPE, null);
-                            }
-                        } else if (oldIndex == 2 && mCurrentIndex == 1) {
-                            mCameraSwitchCutoff = SystemClock.uptimeMillis() +
-                                    CAMERA_SWITCH_CUTOFF_THRESHOLD_MS;
-                            mPhotoView.stopScrolling();
-                        } else if (oldIndex >= 1 && mCurrentIndex == 0) {
-                            mPhotoView.setWantPictureCenterCallbacks(true);
-                            mSkipUpdateCurrentPhoto = true;
-                        }
-                    }
-                    if (!mSkipUpdateCurrentPhoto) {
-                        if (item != null) {
-                            MediaItem photo = mModel.getMediaItem(0);
-                            if (photo != null) updateCurrentPhoto(photo);
-                        }
-                        updateBars();
-                    }
-                    // Reset the timeout for the bars after a swipe
-                    refreshHidingMessage();
-                }
-
-                @Override
-                public void onLoadingFinished(boolean loadingFailed) {
-                    if (!mModel.isEmpty()) {
-                        MediaItem photo = mModel.getMediaItem(0);
-                        if (photo != null) updateCurrentPhoto(photo);
-                    } else if (mIsActive) {
-                        // We only want to finish the PhotoPage if there is no
-                        // deletion that the user can undo.
-                        if (mMediaSet.getNumberOfDeletions() == 0) {
-                            mActivity.getStateManager().finishState(
-                                    PhotoPage.this);
-                        }
-                    }
-                }
-
-                @Override
-                public void onLoadingStarted() {
-                }
-            });
-        } else {
-            // Get default media set by the URI
-            MediaItem mediaItem = (MediaItem)
-                    mActivity.getDataManager().getMediaObject(itemPath);
-            mModel = new SinglePhotoDataAdapter(mActivity, mPhotoView, mediaItem);
-            mPhotoView.setModel(mModel);
-            updateCurrentPhoto(mediaItem);
-            mShowSpinner = false;
-        }
-
-        mPhotoView.setFilmMode(mStartInFilmstrip && mMediaSet.getMediaItemCount() > 1);
-        RelativeLayout galleryRoot = (RelativeLayout) ((Activity) mActivity)
-                .findViewById(mAppBridge != null ? R.id.content : R.id.gallery_root);
-        if (galleryRoot != null) {
-            if (mSecureAlbum == null) {
-                mBottomControls = new PhotoPageBottomControls(this, mActivity, galleryRoot);
-            }
-            StitchingProgressManager progressManager = mApplication.getStitchingProgressManager();
-            if (progressManager != null) {
-                mProgressBar = new PhotoPageProgressBar(mActivity, galleryRoot);
-                mProgressListener = new UpdateProgressListener();
-                progressManager.addChangeListener(mProgressListener);
-                if (mSecureAlbum != null) {
-                    progressManager.addChangeListener(mSecureAlbum);
-                }
-            }
-        }
-    }
-
-    @Override
-    public void onPictureCenter(boolean isCamera) {
-        isCamera = isCamera || (mHasCameraScreennailOrPlaceholder && mAppBridge == null);
-        mPhotoView.setWantPictureCenterCallbacks(false);
-        mHandler.removeMessages(MSG_ON_CAMERA_CENTER);
-        mHandler.removeMessages(MSG_ON_PICTURE_CENTER);
-        mHandler.sendEmptyMessage(isCamera ? MSG_ON_CAMERA_CENTER : MSG_ON_PICTURE_CENTER);
-    }
-
-    @Override
-    public boolean canDisplayBottomControls() {
-        return mIsActive && !mPhotoView.canUndo();
-    }
-
-    @Override
-    public boolean canDisplayBottomControl(int control) {
-        if (mCurrentPhoto == null) {
-            return false;
-        }
-        switch(control) {
-            case R.id.photopage_bottom_control_edit:
-                return mHaveImageEditor && mShowBars
-                        && !mPhotoView.getFilmMode()
-                        && (mCurrentPhoto.getSupportedOperations() & MediaItem.SUPPORT_EDIT) != 0
-                        && mCurrentPhoto.getMediaType() == MediaObject.MEDIA_TYPE_IMAGE;
-            case R.id.photopage_bottom_control_panorama:
-                return mIsPanorama;
-            case R.id.photopage_bottom_control_tiny_planet:
-                return mHaveImageEditor && mShowBars
-                        && mIsPanorama360 && !mPhotoView.getFilmMode();
-            default:
-                return false;
-        }
-    }
-
-    @Override
-    public void onBottomControlClicked(int control) {
-        switch(control) {
-            case R.id.photopage_bottom_control_edit:
-                launchPhotoEditor();
-                return;
-            case R.id.photopage_bottom_control_panorama:
-                mActivity.getPanoramaViewHelper()
-                        .showPanorama(mCurrentPhoto.getContentUri());
-                return;
-            case R.id.photopage_bottom_control_tiny_planet:
-                launchTinyPlanet();
-                return;
-            default:
-                return;
-        }
-    }
-
-    @TargetApi(ApiHelper.VERSION_CODES.JELLY_BEAN)
-    private void setupNfcBeamPush() {
-        if (!ApiHelper.HAS_SET_BEAM_PUSH_URIS) return;
-
-        NfcAdapter adapter = NfcAdapter.getDefaultAdapter(mActivity);
-        if (adapter != null) {
-            adapter.setBeamPushUris(null, mActivity);
-            adapter.setBeamPushUrisCallback(new CreateBeamUrisCallback() {
-                @Override
-                public Uri[] createBeamUris(NfcEvent event) {
-                    return mNfcPushUris;
-                }
-            }, mActivity);
-        }
-    }
-
-    private void setNfcBeamPushUri(Uri uri) {
-        mNfcPushUris[0] = uri;
-    }
-
-    private static Intent createShareIntent(MediaObject mediaObject) {
-        int type = mediaObject.getMediaType();
-        return new Intent(Intent.ACTION_SEND)
-                .setType(MenuExecutor.getMimeType(type))
-                .putExtra(Intent.EXTRA_STREAM, mediaObject.getContentUri())
-                .addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
-    }
-
-    private static Intent createSharePanoramaIntent(Uri contentUri) {
-        return new Intent(Intent.ACTION_SEND)
-                .setType(GalleryUtils.MIME_TYPE_PANORAMA360)
-                .putExtra(Intent.EXTRA_STREAM, contentUri)
-                .addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
-    }
-
-    private void overrideTransitionToEditor() {
-        ((Activity) mActivity).overridePendingTransition(android.R.anim.fade_in,
-                android.R.anim.fade_out);
-    }
-
-    private void launchTinyPlanet() {
-        // Deep link into tiny planet
-        MediaItem current = mModel.getMediaItem(0);
-        Intent intent = new Intent(FilterShowActivity.TINY_PLANET_ACTION);
-        intent.setClass(mActivity, FilterShowActivity.class);
-        intent.setDataAndType(current.getContentUri(), current.getMimeType())
-            .setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
-        intent.putExtra(FilterShowActivity.LAUNCH_FULLSCREEN,
-                mActivity.isFullscreen());
-        mActivity.startActivityForResult(intent, REQUEST_EDIT);
-        overrideTransitionToEditor();
-    }
-
-    private void launchCamera() {
-        Intent intent = new Intent(mActivity, CameraActivity.class)
-            .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
-        mRecenterCameraOnResume = false;
-        mActivity.startActivity(intent);
-    }
-
-    private void launchPhotoEditor() {
-        MediaItem current = mModel.getMediaItem(0);
-        if (current == null || (current.getSupportedOperations()
-                & MediaObject.SUPPORT_EDIT) == 0) {
-            return;
-        }
-
-        Intent intent = new Intent(ACTION_NEXTGEN_EDIT);
-
-        intent.setDataAndType(current.getContentUri(), current.getMimeType())
-                .setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
-        if (mActivity.getPackageManager()
-                .queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY).size() == 0) {
-            intent.setAction(Intent.ACTION_EDIT);
-        }
-        intent.putExtra(FilterShowActivity.LAUNCH_FULLSCREEN,
-                mActivity.isFullscreen());
-        ((Activity) mActivity).startActivityForResult(Intent.createChooser(intent, null),
-                REQUEST_EDIT);
-        overrideTransitionToEditor();
-    }
-
-    private void launchSimpleEditor() {
-        MediaItem current = mModel.getMediaItem(0);
-        if (current == null || (current.getSupportedOperations()
-                & MediaObject.SUPPORT_EDIT) == 0) {
-            return;
-        }
-
-        Intent intent = new Intent(ACTION_SIMPLE_EDIT);
-
-        intent.setDataAndType(current.getContentUri(), current.getMimeType())
-                .setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
-        if (mActivity.getPackageManager()
-                .queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY).size() == 0) {
-            intent.setAction(Intent.ACTION_EDIT);
-        }
-        intent.putExtra(FilterShowActivity.LAUNCH_FULLSCREEN,
-                mActivity.isFullscreen());
-        ((Activity) mActivity).startActivityForResult(Intent.createChooser(intent, null),
-                REQUEST_EDIT);
-        overrideTransitionToEditor();
-    }
-
-    private void requestDeferredUpdate() {
-        mDeferUpdateUntil = SystemClock.uptimeMillis() + DEFERRED_UPDATE_MS;
-        if (!mDeferredUpdateWaiting) {
-            mDeferredUpdateWaiting = true;
-            mHandler.sendEmptyMessageDelayed(MSG_UPDATE_DEFERRED, DEFERRED_UPDATE_MS);
-        }
-    }
-
-    private void updateUIForCurrentPhoto() {
-        if (mCurrentPhoto == null) return;
-
-        // If by swiping or deletion the user ends up on an action item
-        // and zoomed in, zoom out so that the context of the action is
-        // more clear
-        if ((mCurrentPhoto.getSupportedOperations() & MediaObject.SUPPORT_ACTION) != 0
-                && !mPhotoView.getFilmMode()) {
-            mPhotoView.setWantPictureCenterCallbacks(true);
-        }
-
-        updateMenuOperations();
-        refreshBottomControlsWhenReady();
-        if (mShowDetails) {
-            mDetailsHelper.reloadDetails();
-        }
-        if ((mSecureAlbum == null)
-                && (mCurrentPhoto.getSupportedOperations() & MediaItem.SUPPORT_SHARE) != 0) {
-            mCurrentPhoto.getPanoramaSupport(mUpdateShareURICallback);
-        }
-        updateProgressBar();
-    }
-
-    private void updateCurrentPhoto(MediaItem photo) {
-        if (mCurrentPhoto == photo) return;
-        mCurrentPhoto = photo;
-        if (mPhotoView.getFilmMode()) {
-            requestDeferredUpdate();
-        } else {
-            updateUIForCurrentPhoto();
-        }
-    }
-
-    private void updateProgressBar() {
-        if (mProgressBar != null) {
-            mProgressBar.hideProgress();
-            StitchingProgressManager progressManager = mApplication.getStitchingProgressManager();
-            if (progressManager != null && mCurrentPhoto instanceof LocalImage) {
-                Integer progress = progressManager.getProgress(mCurrentPhoto.getContentUri());
-                if (progress != null) {
-                    mProgressBar.setProgress(progress);
-                }
-            }
-        }
-    }
-
-    private void updateMenuOperations() {
-        Menu menu = mActionBar.getMenu();
-
-        // it could be null if onCreateActionBar has not been called yet
-        if (menu == null) return;
-
-        MenuItem item = menu.findItem(R.id.action_slideshow);
-        if (item != null) {
-            item.setVisible((mSecureAlbum == null) && canDoSlideShow());
-        }
-        if (mCurrentPhoto == null) return;
-
-        int supportedOperations = mCurrentPhoto.getSupportedOperations();
-        if (mSecureAlbum != null) {
-            supportedOperations &= MediaObject.SUPPORT_DELETE;
-        } else {
-            mCurrentPhoto.getPanoramaSupport(mUpdatePanoramaMenuItemsCallback);
-            if (!mHaveImageEditor) {
-                supportedOperations &= ~MediaObject.SUPPORT_EDIT;
-            }
-        }
-        MenuExecutor.updateMenuOperation(menu, supportedOperations);
-    }
-
-    private boolean canDoSlideShow() {
-        if (mMediaSet == null || mCurrentPhoto == null) {
-            return false;
-        }
-        if (mCurrentPhoto.getMediaType() != MediaObject.MEDIA_TYPE_IMAGE) {
-            return false;
-        }
-        return true;
-    }
-
-    //////////////////////////////////////////////////////////////////////////
-    //  Action Bar show/hide management
-    //////////////////////////////////////////////////////////////////////////
-
-    private void showBars() {
-        if (mShowBars) return;
-        mShowBars = true;
-        mOrientationManager.unlockOrientation();
-        mActionBar.show();
-        mActivity.getGLRoot().setLightsOutMode(false);
-        refreshHidingMessage();
-        refreshBottomControlsWhenReady();
-    }
-
-    private void hideBars() {
-        if (!mShowBars) return;
-        mShowBars = false;
-        mActionBar.hide();
-        mActivity.getGLRoot().setLightsOutMode(true);
-        mHandler.removeMessages(MSG_HIDE_BARS);
-        refreshBottomControlsWhenReady();
-    }
-
-    private void refreshHidingMessage() {
-        mHandler.removeMessages(MSG_HIDE_BARS);
-        if (!mIsMenuVisible && !mPhotoView.getFilmMode()) {
-            mHandler.sendEmptyMessageDelayed(MSG_HIDE_BARS, HIDE_BARS_TIMEOUT);
-        }
-    }
-
-    private boolean canShowBars() {
-        // No bars if we are showing camera preview.
-        if (mAppBridge != null && mCurrentIndex == 0
-                && !mPhotoView.getFilmMode()) return false;
-
-        // No bars if it's not allowed.
-        if (!mActionBarAllowed) return false;
-
-        Configuration config = mActivity.getResources().getConfiguration();
-        if (config.touchscreen == Configuration.TOUCHSCREEN_NOTOUCH) {
-            return false;
-        }
-
-        return true;
-    }
-
-    private void wantBars() {
-        if (canShowBars()) showBars();
-    }
-
-    private void toggleBars() {
-        if (mShowBars) {
-            hideBars();
-        } else {
-            if (canShowBars()) showBars();
-        }
-    }
-
-    private void updateBars() {
-        if (!canShowBars()) {
-            hideBars();
-        }
-    }
-
-    @Override
-    protected void onBackPressed() {
-        if (mShowDetails) {
-            hideDetails();
-        } else if (mAppBridge == null || !switchWithCaptureAnimation(-1)) {
-            // We are leaving this page. Set the result now.
-            setResult();
-            if (mStartInFilmstrip && !mPhotoView.getFilmMode()) {
-                mPhotoView.setFilmMode(true);
-            } else if (mTreatBackAsUp) {
-                onUpPressed();
-            } else {
-                super.onBackPressed();
-            }
-        }
-    }
-
-    private void onUpPressed() {
-        if ((mStartInFilmstrip || mAppBridge != null)
-                && !mPhotoView.getFilmMode()) {
-            mPhotoView.setFilmMode(true);
-            return;
-        }
-
-        if (mActivity.getStateManager().getStateCount() > 1) {
-            setResult();
-            super.onBackPressed();
-            return;
-        }
-
-        if (mOriginalSetPathString == null) return;
-
-        if (mAppBridge == null) {
-            // We're in view mode so set up the stacks on our own.
-            Bundle data = new Bundle(getData());
-            data.putString(AlbumPage.KEY_MEDIA_PATH, mOriginalSetPathString);
-            data.putString(AlbumPage.KEY_PARENT_MEDIA_PATH,
-                    mActivity.getDataManager().getTopSetPath(
-                            DataManager.INCLUDE_ALL));
-            mActivity.getStateManager().switchState(this, AlbumPage.class, data);
-        } else {
-            GalleryUtils.startGalleryActivity(mActivity);
-        }
-    }
-
-    private void setResult() {
-        Intent result = null;
-        result = new Intent();
-        result.putExtra(KEY_RETURN_INDEX_HINT, mCurrentIndex);
-        setStateResult(Activity.RESULT_OK, result);
-    }
-
-    //////////////////////////////////////////////////////////////////////////
-    //  AppBridge.Server interface
-    //////////////////////////////////////////////////////////////////////////
-
-    @Override
-    public void setCameraRelativeFrame(Rect frame) {
-        mPhotoView.setCameraRelativeFrame(frame);
-    }
-
-    @Override
-    public boolean switchWithCaptureAnimation(int offset) {
-        return mPhotoView.switchWithCaptureAnimation(offset);
-    }
-
-    @Override
-    public void setSwipingEnabled(boolean enabled) {
-        mPhotoView.setSwipingEnabled(enabled);
-    }
-
-    @Override
-    public void notifyScreenNailChanged() {
-        mScreenNailItem.setScreenNail(mAppBridge.attachScreenNail());
-        mScreenNailSet.notifyChange();
-    }
-
-    @Override
-    public void addSecureAlbumItem(boolean isVideo, int id) {
-        mSecureAlbum.addMediaItem(isVideo, id);
-    }
-
-    @Override
-    protected boolean onCreateActionBar(Menu menu) {
-        mActionBar.createActionBarMenu(R.menu.photo, menu);
-        mHaveImageEditor = GalleryUtils.isEditorAvailable(mActivity, "image/*");
-        updateMenuOperations();
-        mActionBar.setTitle(mMediaSet != null ? mMediaSet.getName() : "");
-        return true;
-    }
-
-    private MenuExecutor.ProgressListener mConfirmDialogListener =
-            new MenuExecutor.ProgressListener() {
-        @Override
-        public void onProgressUpdate(int index) {}
-
-        @Override
-        public void onProgressComplete(int result) {}
-
-        @Override
-        public void onConfirmDialogShown() {
-            mHandler.removeMessages(MSG_HIDE_BARS);
-        }
-
-        @Override
-        public void onConfirmDialogDismissed(boolean confirmed) {
-            refreshHidingMessage();
-        }
-
-        @Override
-        public void onProgressStart() {}
-    };
-
-    private void switchToGrid() {
-        if (mActivity.getStateManager().hasStateClass(AlbumPage.class)) {
-            onUpPressed();
-        } else {
-            if (mOriginalSetPathString == null) return;
-            if (mProgressBar != null) {
-                updateCurrentPhoto(null);
-                mProgressBar.hideProgress();
-            }
-            Bundle data = new Bundle(getData());
-            data.putString(AlbumPage.KEY_MEDIA_PATH, mOriginalSetPathString);
-            data.putString(AlbumPage.KEY_PARENT_MEDIA_PATH,
-                    mActivity.getDataManager().getTopSetPath(
-                            DataManager.INCLUDE_ALL));
-
-            // We only show cluster menu in the first AlbumPage in stack
-            // TODO: Enable this when running from the camera app
-            boolean inAlbum = mActivity.getStateManager().hasStateClass(AlbumPage.class);
-            data.putBoolean(AlbumPage.KEY_SHOW_CLUSTER_MENU, !inAlbum
-                    && mAppBridge == null);
-
-            data.putBoolean(PhotoPage.KEY_APP_BRIDGE, mAppBridge != null);
-
-            // Account for live preview being first item
-            mActivity.getTransitionStore().put(KEY_RETURN_INDEX_HINT,
-                    mAppBridge != null ? mCurrentIndex - 1 : mCurrentIndex);
-
-            if (mHasCameraScreennailOrPlaceholder && mAppBridge != null) {
-                mActivity.getStateManager().startState(AlbumPage.class, data);
-            } else {
-                mActivity.getStateManager().switchState(this, AlbumPage.class, data);
-            }
-        }
-    }
-
-    @Override
-    protected boolean onItemSelected(MenuItem item) {
-        if (mModel == null) return true;
-        refreshHidingMessage();
-        MediaItem current = mModel.getMediaItem(0);
-
-        // This is a shield for monkey when it clicks the action bar
-        // menu when transitioning from filmstrip to camera
-        if (current instanceof SnailItem) return true;
-        // TODO: We should check the current photo against the MediaItem
-        // that the menu was initially created for. We need to fix this
-        // after PhotoPage being refactored.
-        if (current == null) {
-            // item is not ready, ignore
-            return true;
-        }
-        int currentIndex = mModel.getCurrentIndex();
-        Path path = current.getPath();
-
-        DataManager manager = mActivity.getDataManager();
-        int action = item.getItemId();
-        String confirmMsg = null;
-        switch (action) {
-            case android.R.id.home: {
-                onUpPressed();
-                return true;
-            }
-            case R.id.action_slideshow: {
-                Bundle data = new Bundle();
-                data.putString(SlideshowPage.KEY_SET_PATH, mMediaSet.getPath().toString());
-                data.putString(SlideshowPage.KEY_ITEM_PATH, path.toString());
-                data.putInt(SlideshowPage.KEY_PHOTO_INDEX, currentIndex);
-                data.putBoolean(SlideshowPage.KEY_REPEAT, true);
-                mActivity.getStateManager().startStateForResult(
-                        SlideshowPage.class, REQUEST_SLIDESHOW, data);
-                return true;
-            }
-            case R.id.action_crop: {
-                Activity activity = mActivity;
-                Intent intent = new Intent(CropActivity.CROP_ACTION);
-                intent.setClass(activity, CropActivity.class);
-                intent.setDataAndType(manager.getContentUri(path), current.getMimeType())
-                    .setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
-                activity.startActivityForResult(intent, PicasaSource.isPicasaImage(current)
-                        ? REQUEST_CROP_PICASA
-                        : REQUEST_CROP);
-                return true;
-            }
-            case R.id.action_trim: {
-                Intent intent = new Intent(mActivity, TrimVideo.class);
-                intent.setData(manager.getContentUri(path));
-                // We need the file path to wrap this into a RandomAccessFile.
-                intent.putExtra(KEY_MEDIA_ITEM_PATH, current.getFilePath());
-                mActivity.startActivityForResult(intent, REQUEST_TRIM);
-                return true;
-            }
-            case R.id.action_mute: {
-                MuteVideo muteVideo = new MuteVideo(current.getFilePath(),
-                        manager.getContentUri(path), mActivity);
-                muteVideo.muteInBackground();
-                return true;
-            }
-            case R.id.action_edit: {
-                launchPhotoEditor();
-                return true;
-            }
-            case R.id.action_simple_edit: {
-                launchSimpleEditor();
-                return true;
-            }
-            case R.id.action_details: {
-                if (mShowDetails) {
-                    hideDetails();
-                } else {
-                    showDetails();
-                }
-                return true;
-            }
-            case R.id.action_delete:
-                confirmMsg = mActivity.getResources().getQuantityString(
-                        R.plurals.delete_selection, 1);
-            case R.id.action_setas:
-            case R.id.action_rotate_ccw:
-            case R.id.action_rotate_cw:
-            case R.id.action_show_on_map:
-                mSelectionManager.deSelectAll();
-                mSelectionManager.toggle(path);
-                mMenuExecutor.onMenuClicked(item, confirmMsg, mConfirmDialogListener);
-                return true;
-            default :
-                return false;
-        }
-    }
-
-    private void hideDetails() {
-        mShowDetails = false;
-        mDetailsHelper.hide();
-    }
-
-    private void showDetails() {
-        mShowDetails = true;
-        if (mDetailsHelper == null) {
-            mDetailsHelper = new DetailsHelper(mActivity, mRootPane, new MyDetailsSource());
-            mDetailsHelper.setCloseListener(new CloseListener() {
-                @Override
-                public void onClose() {
-                    hideDetails();
-                }
-            });
-        }
-        mDetailsHelper.show();
-    }
-
-    ////////////////////////////////////////////////////////////////////////////
-    //  Callbacks from PhotoView
-    ////////////////////////////////////////////////////////////////////////////
-    @Override
-    public void onSingleTapUp(int x, int y) {
-        if (mAppBridge != null) {
-            if (mAppBridge.onSingleTapUp(x, y)) return;
-        }
-
-        MediaItem item = mModel.getMediaItem(0);
-        if (item == null || item == mScreenNailItem) {
-            // item is not ready or it is camera preview, ignore
-            return;
-        }
-
-        int supported = item.getSupportedOperations();
-        boolean playVideo = ((supported & MediaItem.SUPPORT_PLAY) != 0);
-        boolean unlock = ((supported & MediaItem.SUPPORT_UNLOCK) != 0);
-        boolean goBack = ((supported & MediaItem.SUPPORT_BACK) != 0);
-        boolean launchCamera = ((supported & MediaItem.SUPPORT_CAMERA_SHORTCUT) != 0);
-
-        if (playVideo) {
-            // determine if the point is at center (1/6) of the photo view.
-            // (The position of the "play" icon is at center (1/6) of the photo)
-            int w = mPhotoView.getWidth();
-            int h = mPhotoView.getHeight();
-            playVideo = (Math.abs(x - w / 2) * 12 <= w)
-                && (Math.abs(y - h / 2) * 12 <= h);
-        }
-
-        if (playVideo) {
-            if (mSecureAlbum == null) {
-                playVideo(mActivity, item.getPlayUri(), item.getName());
-            } else {
-                mActivity.getStateManager().finishState(this);
-            }
-        } else if (goBack) {
-            onBackPressed();
-        } else if (unlock) {
-            Intent intent = new Intent(mActivity, Gallery.class);
-            intent.putExtra(Gallery.KEY_DISMISS_KEYGUARD, true);
-            mActivity.startActivity(intent);
-        } else if (launchCamera) {
-            launchCamera();
-        } else {
-            toggleBars();
-        }
-    }
-
-    @Override
-    public void onActionBarAllowed(boolean allowed) {
-        mActionBarAllowed = allowed;
-        mHandler.sendEmptyMessage(MSG_UPDATE_ACTION_BAR);
-    }
-
-    @Override
-    public void onActionBarWanted() {
-        mHandler.sendEmptyMessage(MSG_WANT_BARS);
-    }
-
-    @Override
-    public void onFullScreenChanged(boolean full) {
-        Message m = mHandler.obtainMessage(
-                MSG_ON_FULL_SCREEN_CHANGED, full ? 1 : 0, 0);
-        m.sendToTarget();
-    }
-
-    // How we do delete/undo:
-    //
-    // When the user choose to delete a media item, we just tell the
-    // FilterDeleteSet to hide that item. If the user choose to undo it, we
-    // again tell FilterDeleteSet not to hide it. If the user choose to commit
-    // the deletion, we then actually delete the media item.
-    @Override
-    public void onDeleteImage(Path path, int offset) {
-        onCommitDeleteImage();  // commit the previous deletion
-        mDeletePath = path;
-        mDeleteIsFocus = (offset == 0);
-        mMediaSet.addDeletion(path, mCurrentIndex + offset);
-    }
-
-    @Override
-    public void onUndoDeleteImage() {
-        if (mDeletePath == null) return;
-        // If the deletion was done on the focused item, we want the model to
-        // focus on it when it is undeleted.
-        if (mDeleteIsFocus) mModel.setFocusHintPath(mDeletePath);
-        mMediaSet.removeDeletion(mDeletePath);
-        mDeletePath = null;
-    }
-
-    @Override
-    public void onCommitDeleteImage() {
-        if (mDeletePath == null) return;
-        mMenuExecutor.startSingleItemAction(R.id.action_delete, mDeletePath);
-        mDeletePath = null;
-    }
-
-    public void playVideo(Activity activity, Uri uri, String title) {
-        try {
-            Intent intent = new Intent(Intent.ACTION_VIEW)
-                    .setDataAndType(uri, "video/*")
-                    .putExtra(Intent.EXTRA_TITLE, title)
-                    .putExtra(MovieActivity.KEY_TREAT_UP_AS_BACK, true);
-            activity.startActivityForResult(intent, REQUEST_PLAY_VIDEO);
-        } catch (ActivityNotFoundException e) {
-            Toast.makeText(activity, activity.getString(R.string.video_err),
-                    Toast.LENGTH_SHORT).show();
-        }
-    }
-
-    private void setCurrentPhotoByIntent(Intent intent) {
-        if (intent == null) return;
-        Path path = mApplication.getDataManager()
-                .findPathByUri(intent.getData(), intent.getType());
-        if (path != null) {
-            Path albumPath = mApplication.getDataManager().getDefaultSetOf(path);
-            if (!albumPath.equalsIgnoreCase(mOriginalSetPathString)) {
-                // If the edited image is stored in a different album, we need
-                // to start a new activity state to show the new image
-                Bundle data = new Bundle(getData());
-                data.putString(KEY_MEDIA_SET_PATH, albumPath.toString());
-                data.putString(PhotoPage.KEY_MEDIA_ITEM_PATH, path.toString());
-                mActivity.getStateManager().startState(SinglePhotoPage.class, data);
-                return;
-            }
-            mModel.setCurrentPhoto(path, mCurrentIndex);
-        }
-    }
-
-    @Override
-    protected void onStateResult(int requestCode, int resultCode, Intent data) {
-        if (resultCode == Activity.RESULT_CANCELED) {
-            // This is a reset, not a canceled
-            return;
-        }
-        if (resultCode == ProxyLauncher.RESULT_USER_CANCELED) {
-            // Unmap reset vs. canceled
-            resultCode = Activity.RESULT_CANCELED;
-        }
-        mRecenterCameraOnResume = false;
-        switch (requestCode) {
-            case REQUEST_EDIT:
-                setCurrentPhotoByIntent(data);
-                break;
-            case REQUEST_CROP:
-                if (resultCode == Activity.RESULT_OK) {
-                    setCurrentPhotoByIntent(data);
-                }
-                break;
-            case REQUEST_CROP_PICASA: {
-                if (resultCode == Activity.RESULT_OK) {
-                    Context context = mActivity.getAndroidContext();
-                    String message = context.getString(R.string.crop_saved,
-                            context.getString(R.string.folder_edited_online_photos));
-                    Toast.makeText(context, message, Toast.LENGTH_SHORT).show();
-                }
-                break;
-            }
-            case REQUEST_SLIDESHOW: {
-                if (data == null) break;
-                String path = data.getStringExtra(SlideshowPage.KEY_ITEM_PATH);
-                int index = data.getIntExtra(SlideshowPage.KEY_PHOTO_INDEX, 0);
-                if (path != null) {
-                    mModel.setCurrentPhoto(Path.fromString(path), index);
-                }
-            }
-        }
-    }
-
-    @Override
-    public void onPause() {
-        super.onPause();
-        mIsActive = false;
-
-        mActivity.getGLRoot().unfreeze();
-        mHandler.removeMessages(MSG_UNFREEZE_GLROOT);
-
-        DetailsHelper.pause();
-        // Hide the detail dialog on exit
-        if (mShowDetails) hideDetails();
-        if (mModel != null) {
-            mModel.pause();
-        }
-        mPhotoView.pause();
-        mHandler.removeMessages(MSG_HIDE_BARS);
-        mHandler.removeMessages(MSG_REFRESH_BOTTOM_CONTROLS);
-        refreshBottomControlsWhenReady();
-        mActionBar.removeOnMenuVisibilityListener(mMenuVisibilityListener);
-        if (mShowSpinner) {
-            mActionBar.disableAlbumModeMenu(true);
-        }
-        onCommitDeleteImage();
-        mMenuExecutor.pause();
-        if (mMediaSet != null) mMediaSet.clearDeletion();
-    }
-
-    @Override
-    public void onCurrentImageUpdated() {
-        mActivity.getGLRoot().unfreeze();
-    }
-
-    @Override
-    public void onFilmModeChanged(boolean enabled) {
-        refreshBottomControlsWhenReady();
-        if (mShowSpinner) {
-            if (enabled) {
-                mActionBar.enableAlbumModeMenu(
-                        GalleryActionBar.ALBUM_FILMSTRIP_MODE_SELECTED, this);
-            } else {
-                mActionBar.disableAlbumModeMenu(true);
-            }
-        }
-        if (enabled) {
-            mHandler.removeMessages(MSG_HIDE_BARS);
-            UsageStatistics.onContentViewChanged(
-                    UsageStatistics.COMPONENT_GALLERY, "FilmstripPage");
-        } else {
-            refreshHidingMessage();
-            if (mAppBridge == null || mCurrentIndex > 0) {
-                UsageStatistics.onContentViewChanged(
-                        UsageStatistics.COMPONENT_GALLERY, "SinglePhotoPage");
-            } else {
-                UsageStatistics.onContentViewChanged(
-                        UsageStatistics.COMPONENT_CAMERA, "Unknown"); // TODO
-            }
-        }
-    }
-
-    private void transitionFromAlbumPageIfNeeded() {
-        TransitionStore transitions = mActivity.getTransitionStore();
-
-        int albumPageTransition = transitions.get(
-                KEY_ALBUMPAGE_TRANSITION, MSG_ALBUMPAGE_NONE);
-
-        if (albumPageTransition == MSG_ALBUMPAGE_NONE && mAppBridge != null
-                && mRecenterCameraOnResume) {
-            // Generally, resuming the PhotoPage when in Camera should
-            // reset to the capture mode to allow quick photo taking
-            mCurrentIndex = 0;
-            mPhotoView.resetToFirstPicture();
-        } else {
-            int resumeIndex = transitions.get(KEY_INDEX_HINT, -1);
-            if (resumeIndex >= 0) {
-                if (mHasCameraScreennailOrPlaceholder) {
-                    // Account for preview/placeholder being the first item
-                    resumeIndex++;
-                }
-                if (resumeIndex < mMediaSet.getMediaItemCount()) {
-                    mCurrentIndex = resumeIndex;
-                    mModel.moveTo(mCurrentIndex);
-                }
-            }
-        }
-
-        if (albumPageTransition == MSG_ALBUMPAGE_RESUMED) {
-            mPhotoView.setFilmMode(mStartInFilmstrip || mAppBridge != null);
-        } else if (albumPageTransition == MSG_ALBUMPAGE_PICKED) {
-            mPhotoView.setFilmMode(false);
-        }
-    }
-
-    @Override
-    protected void onResume() {
-        super.onResume();
-
-        if (mModel == null) {
-            mActivity.getStateManager().finishState(this);
-            return;
-        }
-        transitionFromAlbumPageIfNeeded();
-
-        mActivity.getGLRoot().freeze();
-        mIsActive = true;
-        setContentPane(mRootPane);
-
-        mModel.resume();
-        mPhotoView.resume();
-        mActionBar.setDisplayOptions(
-                ((mSecureAlbum == null) && (mSetPathString != null)), false);
-        mActionBar.addOnMenuVisibilityListener(mMenuVisibilityListener);
-        refreshBottomControlsWhenReady();
-        if (mShowSpinner && mPhotoView.getFilmMode()) {
-            mActionBar.enableAlbumModeMenu(
-                    GalleryActionBar.ALBUM_FILMSTRIP_MODE_SELECTED, this);
-        }
-        if (!mShowBars) {
-            mActionBar.hide();
-            mActivity.getGLRoot().setLightsOutMode(true);
-        }
-        boolean haveImageEditor = GalleryUtils.isEditorAvailable(mActivity, "image/*");
-        if (haveImageEditor != mHaveImageEditor) {
-            mHaveImageEditor = haveImageEditor;
-            updateMenuOperations();
-        }
-
-        mRecenterCameraOnResume = true;
-        mHandler.sendEmptyMessageDelayed(MSG_UNFREEZE_GLROOT, UNFREEZE_GLROOT_TIMEOUT);
-    }
-
-    @Override
-    protected void onDestroy() {
-        if (mAppBridge != null) {
-            mAppBridge.setServer(null);
-            mScreenNailItem.setScreenNail(null);
-            mAppBridge.detachScreenNail();
-            mAppBridge = null;
-            mScreenNailSet = null;
-            mScreenNailItem = null;
-        }
-        mActivity.getGLRoot().setOrientationSource(null);
-        if (mBottomControls != null) mBottomControls.cleanup();
-
-        // Remove all pending messages.
-        mHandler.removeCallbacksAndMessages(null);
-        super.onDestroy();
-    }
-
-    private class MyDetailsSource implements DetailsSource {
-
-        @Override
-        public MediaDetails getDetails() {
-            return mModel.getMediaItem(0).getDetails();
-        }
-
-        @Override
-        public int size() {
-            return mMediaSet != null ? mMediaSet.getMediaItemCount() : 1;
-        }
-
-        @Override
-        public int setIndex() {
-            return mModel.getCurrentIndex();
-        }
-    }
-
-    @Override
-    public void onAlbumModeSelected(int mode) {
-        if (mode == GalleryActionBar.ALBUM_GRID_MODE_SELECTED) {
-            switchToGrid();
-        }
-    }
-
-    @Override
-    public void refreshBottomControlsWhenReady() {
-        if (mBottomControls == null) {
-            return;
-        }
-        MediaObject currentPhoto = mCurrentPhoto;
-        if (currentPhoto == null) {
-            mHandler.obtainMessage(MSG_REFRESH_BOTTOM_CONTROLS, 0, 0, currentPhoto).sendToTarget();
-        } else {
-            currentPhoto.getPanoramaSupport(mRefreshBottomControlsCallback);
-        }
-    }
-
-    private void updatePanoramaUI(boolean isPanorama360) {
-        Menu menu = mActionBar.getMenu();
-
-        // it could be null if onCreateActionBar has not been called yet
-        if (menu == null) {
-            return;
-        }
-
-        MenuExecutor.updateMenuForPanorama(menu, isPanorama360, isPanorama360);
-
-        if (isPanorama360) {
-            MenuItem item = menu.findItem(R.id.action_share);
-            if (item != null) {
-                item.setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER);
-                item.setTitle(mActivity.getResources().getString(R.string.share_as_photo));
-            }
-        } else if ((mCurrentPhoto.getSupportedOperations() & MediaObject.SUPPORT_SHARE) != 0) {
-            MenuItem item = menu.findItem(R.id.action_share);
-            if (item != null) {
-                item.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
-                item.setTitle(mActivity.getResources().getString(R.string.share));
-            }
-        }
-    }
-
-    @Override
-    public void onUndoBarVisibilityChanged(boolean visible) {
-        refreshBottomControlsWhenReady();
-    }
-
-    @Override
-    public boolean onShareTargetSelected(ShareActionProvider source, Intent intent) {
-        final long timestampMillis = mCurrentPhoto.getDateInMs();
-        final String mediaType = getMediaTypeString(mCurrentPhoto);
-        UsageStatistics.onEvent(UsageStatistics.COMPONENT_GALLERY,
-                UsageStatistics.ACTION_SHARE,
-                mediaType,
-                        timestampMillis > 0
-                        ? System.currentTimeMillis() - timestampMillis
-                        : -1);
-        return false;
-    }
-
-    private static String getMediaTypeString(MediaItem item) {
-        if (item.getMediaType() == MediaObject.MEDIA_TYPE_VIDEO) {
-            return "Video";
-        } else if (item.getMediaType() == MediaObject.MEDIA_TYPE_IMAGE) {
-            return "Photo";
-        } else {
-            return "Unknown:" + item.getMediaType();
-        }
-    }
-
-}
diff --git a/src/com/android/gallery3d/app/PhotoPageBottomControls.java b/src/com/android/gallery3d/app/PhotoPageBottomControls.java
deleted file mode 100644
index 24b8ceb..0000000
--- a/src/com/android/gallery3d/app/PhotoPageBottomControls.java
+++ /dev/null
@@ -1,137 +0,0 @@
-/*
- * 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.gallery3d.app;
-
-import android.content.Context;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.View.OnClickListener;
-import android.view.ViewGroup;
-import android.view.animation.AlphaAnimation;
-import android.view.animation.Animation;
-import android.widget.RelativeLayout;
-
-import com.android.gallery3d.R;
-
-import java.util.HashMap;
-import java.util.Map;
-
-public class PhotoPageBottomControls implements OnClickListener {
-    public interface Delegate {
-        public boolean canDisplayBottomControls();
-        public boolean canDisplayBottomControl(int control);
-        public void onBottomControlClicked(int control);
-        public void refreshBottomControlsWhenReady();
-    }
-
-    private Delegate mDelegate;
-    private ViewGroup mParentLayout;
-    private ViewGroup mContainer;
-
-    private boolean mContainerVisible = false;
-    private Map<View, Boolean> mControlsVisible = new HashMap<View, Boolean>();
-
-    private Animation mContainerAnimIn = new AlphaAnimation(0f, 1f);
-    private Animation mContainerAnimOut = new AlphaAnimation(1f, 0f);
-    private static final int CONTAINER_ANIM_DURATION_MS = 200;
-
-    private static final int CONTROL_ANIM_DURATION_MS = 150;
-    private static Animation getControlAnimForVisibility(boolean visible) {
-        Animation anim = visible ? new AlphaAnimation(0f, 1f)
-                : new AlphaAnimation(1f, 0f);
-        anim.setDuration(CONTROL_ANIM_DURATION_MS);
-        return anim;
-    }
-
-    public PhotoPageBottomControls(Delegate delegate, Context context, RelativeLayout layout) {
-        mDelegate = delegate;
-        mParentLayout = layout;
-
-        LayoutInflater inflater = (LayoutInflater) context
-                .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
-        mContainer = (ViewGroup) inflater
-                .inflate(R.layout.photopage_bottom_controls, mParentLayout, false);
-        mParentLayout.addView(mContainer);
-
-        for (int i = mContainer.getChildCount() - 1; i >= 0; i--) {
-            View child = mContainer.getChildAt(i);
-            child.setOnClickListener(this);
-            mControlsVisible.put(child, false);
-        }
-
-        mContainerAnimIn.setDuration(CONTAINER_ANIM_DURATION_MS);
-        mContainerAnimOut.setDuration(CONTAINER_ANIM_DURATION_MS);
-
-        mDelegate.refreshBottomControlsWhenReady();
-    }
-
-    private void hide() {
-        mContainer.clearAnimation();
-        mContainerAnimOut.reset();
-        mContainer.startAnimation(mContainerAnimOut);
-        mContainer.setVisibility(View.INVISIBLE);
-    }
-
-    private void show() {
-        mContainer.clearAnimation();
-        mContainerAnimIn.reset();
-        mContainer.startAnimation(mContainerAnimIn);
-        mContainer.setVisibility(View.VISIBLE);
-    }
-
-    public void refresh() {
-        boolean visible = mDelegate.canDisplayBottomControls();
-        boolean containerVisibilityChanged = (visible != mContainerVisible);
-        if (containerVisibilityChanged) {
-            if (visible) {
-                show();
-            } else {
-                hide();
-            }
-            mContainerVisible = visible;
-        }
-        if (!mContainerVisible) {
-            return;
-        }
-        for (View control : mControlsVisible.keySet()) {
-            Boolean prevVisibility = mControlsVisible.get(control);
-            boolean curVisibility = mDelegate.canDisplayBottomControl(control.getId());
-            if (prevVisibility.booleanValue() != curVisibility) {
-                if (!containerVisibilityChanged) {
-                    control.clearAnimation();
-                    control.startAnimation(getControlAnimForVisibility(curVisibility));
-                }
-                control.setVisibility(curVisibility ? View.VISIBLE : View.INVISIBLE);
-                mControlsVisible.put(control, curVisibility);
-            }
-        }
-        // Force a layout change
-        mContainer.requestLayout(); // Kick framework to draw the control.
-    }
-
-    public void cleanup() {
-        mParentLayout.removeView(mContainer);
-        mControlsVisible.clear();
-    }
-
-    @Override
-    public void onClick(View view) {
-        if (mContainerVisible && mControlsVisible.get(view).booleanValue()) {
-            mDelegate.onBottomControlClicked(view.getId());
-        }
-    }
-}
diff --git a/src/com/android/gallery3d/app/PhotoPageProgressBar.java b/src/com/android/gallery3d/app/PhotoPageProgressBar.java
deleted file mode 100644
index 141fea6..0000000
--- a/src/com/android/gallery3d/app/PhotoPageProgressBar.java
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * 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.gallery3d.app;
-
-import android.content.Context;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.view.ViewGroup.LayoutParams;
-import android.widget.RelativeLayout;
-
-import com.android.gallery3d.R;
-
-public class PhotoPageProgressBar {
-    private ViewGroup mContainer;
-    private View mProgress;
-
-    public PhotoPageProgressBar(Context context, RelativeLayout parentLayout) {
-        LayoutInflater inflater = (LayoutInflater) context
-                .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
-        mContainer = (ViewGroup) inflater.inflate(R.layout.photopage_progress_bar, parentLayout,
-                false);
-        parentLayout.addView(mContainer);
-        mProgress = mContainer.findViewById(R.id.photopage_progress_foreground);
-    }
-
-    public void setProgress(int progressPercent) {
-        mContainer.setVisibility(View.VISIBLE);
-        LayoutParams layoutParams = mProgress.getLayoutParams();
-        layoutParams.width = mContainer.getWidth() * progressPercent / 100;
-        mProgress.setLayoutParams(layoutParams);
-    }
-
-    public void hideProgress() {
-        mContainer.setVisibility(View.INVISIBLE);
-    }
-}
diff --git a/src/com/android/gallery3d/app/PickerActivity.java b/src/com/android/gallery3d/app/PickerActivity.java
deleted file mode 100644
index d5bb218..0000000
--- a/src/com/android/gallery3d/app/PickerActivity.java
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * Copyright (C) 2011 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.gallery3d.app;
-
-import android.os.Bundle;
-import android.view.Menu;
-import android.view.MenuInflater;
-import android.view.MenuItem;
-import android.view.View;
-import android.view.View.OnClickListener;
-import android.view.Window;
-
-import com.android.gallery3d.R;
-import com.android.gallery3d.ui.GLRootView;
-
-public class PickerActivity extends AbstractGalleryActivity
-        implements OnClickListener {
-
-    public static final String KEY_ALBUM_PATH = "album-path";
-
-    @Override
-    public void onCreate(Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-
-        // We show the picker in two ways. One smaller screen we use a full
-        // screen window with an action bar. On larger screen we use a dialog.
-        boolean isDialog = getResources().getBoolean(R.bool.picker_is_dialog);
-
-        if (!isDialog) {
-            requestWindowFeature(Window.FEATURE_ACTION_BAR);
-            requestWindowFeature(Window.FEATURE_ACTION_BAR_OVERLAY);
-        }
-
-        setContentView(R.layout.dialog_picker);
-
-        if (isDialog) {
-            // In dialog mode, we don't have the action bar to show the
-            // "cancel" action, so we show an additional "cancel" button.
-            View view = findViewById(R.id.cancel);
-            view.setOnClickListener(this);
-            view.setVisibility(View.VISIBLE);
-
-            // We need this, otherwise the view will be dimmed because it
-            // is "behind" the dialog.
-            ((GLRootView) findViewById(R.id.gl_root_view)).setZOrderOnTop(true);
-        }
-    }
-
-    @Override
-    public boolean onCreateOptionsMenu(Menu menu) {
-        MenuInflater inflater = getMenuInflater();
-        inflater.inflate(R.menu.pickup, menu);
-        return true;
-    }
-
-    @Override
-    public boolean onOptionsItemSelected(MenuItem item) {
-        if (item.getItemId() == R.id.action_cancel) {
-            finish();
-            return true;
-        }
-        return super.onOptionsItemSelected(item);
-    }
-
-    @Override
-    public void onClick(View v) {
-        if (v.getId() == R.id.cancel) finish();
-    }
-}
diff --git a/src/com/android/gallery3d/app/SinglePhotoDataAdapter.java b/src/com/android/gallery3d/app/SinglePhotoDataAdapter.java
deleted file mode 100644
index 00f2fe7..0000000
--- a/src/com/android/gallery3d/app/SinglePhotoDataAdapter.java
+++ /dev/null
@@ -1,263 +0,0 @@
-/*
- * Copyright (C) 2010 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.gallery3d.app;
-
-import android.graphics.Bitmap;
-import android.graphics.BitmapFactory;
-import android.graphics.BitmapRegionDecoder;
-import android.graphics.Rect;
-import android.os.Handler;
-import android.os.Message;
-
-import com.android.gallery3d.common.BitmapUtils;
-import com.android.gallery3d.common.Utils;
-import com.android.gallery3d.data.MediaItem;
-import com.android.gallery3d.data.Path;
-import com.android.gallery3d.ui.BitmapScreenNail;
-import com.android.gallery3d.ui.PhotoView;
-import com.android.gallery3d.ui.ScreenNail;
-import com.android.gallery3d.ui.SynchronizedHandler;
-import com.android.gallery3d.ui.TileImageViewAdapter;
-import com.android.gallery3d.util.Future;
-import com.android.gallery3d.util.FutureListener;
-import com.android.gallery3d.util.ThreadPool;
-
-public class SinglePhotoDataAdapter extends TileImageViewAdapter
-        implements PhotoPage.Model {
-
-    private static final String TAG = "SinglePhotoDataAdapter";
-    private static final int SIZE_BACKUP = 1024;
-    private static final int MSG_UPDATE_IMAGE = 1;
-
-    private MediaItem mItem;
-    private boolean mHasFullImage;
-    private Future<?> mTask;
-    private Handler mHandler;
-
-    private PhotoView mPhotoView;
-    private ThreadPool mThreadPool;
-    private int mLoadingState = LOADING_INIT;
-    private BitmapScreenNail mBitmapScreenNail;
-
-    public SinglePhotoDataAdapter(
-            AbstractGalleryActivity activity, PhotoView view, MediaItem item) {
-        mItem = Utils.checkNotNull(item);
-        mHasFullImage = (item.getSupportedOperations() &
-                MediaItem.SUPPORT_FULL_IMAGE) != 0;
-        mPhotoView = Utils.checkNotNull(view);
-        mHandler = new SynchronizedHandler(activity.getGLRoot()) {
-            @Override
-            @SuppressWarnings("unchecked")
-            public void handleMessage(Message message) {
-                Utils.assertTrue(message.what == MSG_UPDATE_IMAGE);
-                if (mHasFullImage) {
-                    onDecodeLargeComplete((ImageBundle) message.obj);
-                } else {
-                    onDecodeThumbComplete((Future<Bitmap>) message.obj);
-                }
-            }
-        };
-        mThreadPool = activity.getThreadPool();
-    }
-
-    private static class ImageBundle {
-        public final BitmapRegionDecoder decoder;
-        public final Bitmap backupImage;
-
-        public ImageBundle(BitmapRegionDecoder decoder, Bitmap backupImage) {
-            this.decoder = decoder;
-            this.backupImage = backupImage;
-        }
-    }
-
-    private FutureListener<BitmapRegionDecoder> mLargeListener =
-            new FutureListener<BitmapRegionDecoder>() {
-        @Override
-        public void onFutureDone(Future<BitmapRegionDecoder> future) {
-            BitmapRegionDecoder decoder = future.get();
-            if (decoder == null) return;
-            int width = decoder.getWidth();
-            int height = decoder.getHeight();
-            BitmapFactory.Options options = new BitmapFactory.Options();
-            options.inSampleSize = BitmapUtils.computeSampleSize(
-                    (float) SIZE_BACKUP / Math.max(width, height));
-            Bitmap bitmap = decoder.decodeRegion(new Rect(0, 0, width, height), options);
-            mHandler.sendMessage(mHandler.obtainMessage(
-                    MSG_UPDATE_IMAGE, new ImageBundle(decoder, bitmap)));
-        }
-    };
-
-    private FutureListener<Bitmap> mThumbListener =
-            new FutureListener<Bitmap>() {
-        @Override
-        public void onFutureDone(Future<Bitmap> future) {
-            mHandler.sendMessage(
-                    mHandler.obtainMessage(MSG_UPDATE_IMAGE, future));
-        }
-    };
-
-    @Override
-    public boolean isEmpty() {
-        return false;
-    }
-
-    private void setScreenNail(Bitmap bitmap, int width, int height) {
-        mBitmapScreenNail = new BitmapScreenNail(bitmap);
-        setScreenNail(mBitmapScreenNail, width, height);
-    }
-
-    private void onDecodeLargeComplete(ImageBundle bundle) {
-        try {
-            setScreenNail(bundle.backupImage,
-                    bundle.decoder.getWidth(), bundle.decoder.getHeight());
-            setRegionDecoder(bundle.decoder);
-            mPhotoView.notifyImageChange(0);
-        } catch (Throwable t) {
-            Log.w(TAG, "fail to decode large", t);
-        }
-    }
-
-    private void onDecodeThumbComplete(Future<Bitmap> future) {
-        try {
-            Bitmap backup = future.get();
-            if (backup == null) {
-                mLoadingState = LOADING_FAIL;
-                return;
-            } else {
-                mLoadingState = LOADING_COMPLETE;
-            }
-            setScreenNail(backup, backup.getWidth(), backup.getHeight());
-            mPhotoView.notifyImageChange(0);
-        } catch (Throwable t) {
-            Log.w(TAG, "fail to decode thumb", t);
-        }
-    }
-
-    @Override
-    public void resume() {
-        if (mTask == null) {
-            if (mHasFullImage) {
-                mTask = mThreadPool.submit(
-                        mItem.requestLargeImage(), mLargeListener);
-            } else {
-                mTask = mThreadPool.submit(
-                        mItem.requestImage(MediaItem.TYPE_THUMBNAIL),
-                        mThumbListener);
-            }
-        }
-    }
-
-    @Override
-    public void pause() {
-        Future<?> task = mTask;
-        task.cancel();
-        task.waitDone();
-        if (task.get() == null) {
-            mTask = null;
-        }
-        if (mBitmapScreenNail != null) {
-            mBitmapScreenNail.recycle();
-            mBitmapScreenNail = null;
-        }
-    }
-
-    @Override
-    public void moveTo(int index) {
-        throw new UnsupportedOperationException();
-    }
-
-    @Override
-    public void getImageSize(int offset, PhotoView.Size size) {
-        if (offset == 0) {
-            size.width = mItem.getWidth();
-            size.height = mItem.getHeight();
-        } else {
-            size.width = 0;
-            size.height = 0;
-        }
-    }
-
-    @Override
-    public int getImageRotation(int offset) {
-        return (offset == 0) ? mItem.getFullImageRotation() : 0;
-    }
-
-    @Override
-    public ScreenNail getScreenNail(int offset) {
-        return (offset == 0) ? getScreenNail() : null;
-    }
-
-    @Override
-    public void setNeedFullImage(boolean enabled) {
-        // currently not necessary.
-    }
-
-    @Override
-    public boolean isCamera(int offset) {
-        return false;
-    }
-
-    @Override
-    public boolean isPanorama(int offset) {
-        return false;
-    }
-
-    @Override
-    public boolean isStaticCamera(int offset) {
-        return false;
-    }
-
-    @Override
-    public boolean isVideo(int offset) {
-        return mItem.getMediaType() == MediaItem.MEDIA_TYPE_VIDEO;
-    }
-
-    @Override
-    public boolean isDeletable(int offset) {
-        return (mItem.getSupportedOperations() & MediaItem.SUPPORT_DELETE) != 0;
-    }
-
-    @Override
-    public MediaItem getMediaItem(int offset) {
-        return offset == 0 ? mItem : null;
-    }
-
-    @Override
-    public int getCurrentIndex() {
-        return 0;
-    }
-
-    @Override
-    public void setCurrentPhoto(Path path, int indexHint) {
-        // ignore
-    }
-
-    @Override
-    public void setFocusHintDirection(int direction) {
-        // ignore
-    }
-
-    @Override
-    public void setFocusHintPath(Path path) {
-        // ignore
-    }
-
-    @Override
-    public int getLoadingState(int offset) {
-        return mLoadingState;
-    }
-}
diff --git a/src/com/android/gallery3d/app/SinglePhotoPage.java b/src/com/android/gallery3d/app/SinglePhotoPage.java
deleted file mode 100644
index beb87d3..0000000
--- a/src/com/android/gallery3d/app/SinglePhotoPage.java
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- * 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.gallery3d.app;
-
-public class SinglePhotoPage extends PhotoPage {
-
-}
diff --git a/src/com/android/gallery3d/app/SlideshowDataAdapter.java b/src/com/android/gallery3d/app/SlideshowDataAdapter.java
deleted file mode 100644
index 7a0fba5..0000000
--- a/src/com/android/gallery3d/app/SlideshowDataAdapter.java
+++ /dev/null
@@ -1,204 +0,0 @@
-/*
- * Copyright (C) 2010 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.gallery3d.app;
-
-import android.graphics.Bitmap;
-
-import com.android.gallery3d.app.SlideshowPage.Slide;
-import com.android.gallery3d.data.ContentListener;
-import com.android.gallery3d.data.MediaItem;
-import com.android.gallery3d.data.MediaObject;
-import com.android.gallery3d.data.Path;
-import com.android.gallery3d.util.Future;
-import com.android.gallery3d.util.FutureListener;
-import com.android.gallery3d.util.ThreadPool;
-import com.android.gallery3d.util.ThreadPool.Job;
-import com.android.gallery3d.util.ThreadPool.JobContext;
-
-import java.util.LinkedList;
-import java.util.concurrent.atomic.AtomicBoolean;
-
-public class SlideshowDataAdapter implements SlideshowPage.Model {
-    @SuppressWarnings("unused")
-    private static final String TAG = "SlideshowDataAdapter";
-
-    private static final int IMAGE_QUEUE_CAPACITY = 3;
-
-    public interface SlideshowSource {
-        public void addContentListener(ContentListener listener);
-        public void removeContentListener(ContentListener listener);
-        public long reload();
-        public MediaItem getMediaItem(int index);
-        public int findItemIndex(Path path, int hint);
-    }
-
-    private final SlideshowSource mSource;
-
-    private int mLoadIndex = 0;
-    private int mNextOutput = 0;
-    private boolean mIsActive = false;
-    private boolean mNeedReset;
-    private boolean mDataReady;
-    private Path mInitialPath;
-
-    private final LinkedList<Slide> mImageQueue = new LinkedList<Slide>();
-
-    private Future<Void> mReloadTask;
-    private final ThreadPool mThreadPool;
-
-    private long mDataVersion = MediaObject.INVALID_DATA_VERSION;
-    private final AtomicBoolean mNeedReload = new AtomicBoolean(false);
-    private final SourceListener mSourceListener = new SourceListener();
-
-    // The index is just a hint if initialPath is set
-    public SlideshowDataAdapter(GalleryContext context, SlideshowSource source, int index,
-            Path initialPath) {
-        mSource = source;
-        mInitialPath = initialPath;
-        mLoadIndex = index;
-        mNextOutput = index;
-        mThreadPool = context.getThreadPool();
-    }
-
-    private MediaItem loadItem() {
-        if (mNeedReload.compareAndSet(true, false)) {
-            long v = mSource.reload();
-            if (v != mDataVersion) {
-                mDataVersion = v;
-                mNeedReset = true;
-                return null;
-            }
-        }
-        int index = mLoadIndex;
-        if (mInitialPath != null) {
-            index = mSource.findItemIndex(mInitialPath, index);
-            mInitialPath = null;
-        }
-        return mSource.getMediaItem(index);
-    }
-
-    private class ReloadTask implements Job<Void> {
-        @Override
-        public Void run(JobContext jc) {
-            while (true) {
-                synchronized (SlideshowDataAdapter.this) {
-                    while (mIsActive && (!mDataReady
-                            || mImageQueue.size() >= IMAGE_QUEUE_CAPACITY)) {
-                        try {
-                            SlideshowDataAdapter.this.wait();
-                        } catch (InterruptedException ex) {
-                            // ignored.
-                        }
-                        continue;
-                    }
-                }
-                if (!mIsActive) return null;
-                mNeedReset = false;
-
-                MediaItem item = loadItem();
-
-                if (mNeedReset) {
-                    synchronized (SlideshowDataAdapter.this) {
-                        mImageQueue.clear();
-                        mLoadIndex = mNextOutput;
-                    }
-                    continue;
-                }
-
-                if (item == null) {
-                    synchronized (SlideshowDataAdapter.this) {
-                        if (!mNeedReload.get()) mDataReady = false;
-                        SlideshowDataAdapter.this.notifyAll();
-                    }
-                    continue;
-                }
-
-                Bitmap bitmap = item
-                        .requestImage(MediaItem.TYPE_THUMBNAIL)
-                        .run(jc);
-
-                if (bitmap != null) {
-                    synchronized (SlideshowDataAdapter.this) {
-                        mImageQueue.addLast(
-                                new Slide(item, mLoadIndex, bitmap));
-                        if (mImageQueue.size() == 1) {
-                            SlideshowDataAdapter.this.notifyAll();
-                        }
-                    }
-                }
-                ++mLoadIndex;
-            }
-        }
-    }
-
-    private class SourceListener implements ContentListener {
-        @Override
-        public void onContentDirty() {
-            synchronized (SlideshowDataAdapter.this) {
-                mNeedReload.set(true);
-                mDataReady = true;
-                SlideshowDataAdapter.this.notifyAll();
-            }
-        }
-    }
-
-    private synchronized Slide innerNextBitmap() {
-        while (mIsActive && mDataReady && mImageQueue.isEmpty()) {
-            try {
-                wait();
-            } catch (InterruptedException t) {
-                throw new AssertionError();
-            }
-        }
-        if (mImageQueue.isEmpty()) return null;
-        mNextOutput++;
-        this.notifyAll();
-        return mImageQueue.removeFirst();
-    }
-
-    @Override
-    public Future<Slide> nextSlide(FutureListener<Slide> listener) {
-        return mThreadPool.submit(new Job<Slide>() {
-            @Override
-            public Slide run(JobContext jc) {
-                jc.setMode(ThreadPool.MODE_NONE);
-                return innerNextBitmap();
-            }
-        }, listener);
-    }
-
-    @Override
-    public void pause() {
-        synchronized (this) {
-            mIsActive = false;
-            notifyAll();
-        }
-        mSource.removeContentListener(mSourceListener);
-        mReloadTask.cancel();
-        mReloadTask.waitDone();
-        mReloadTask = null;
-    }
-
-    @Override
-    public synchronized void resume() {
-        mIsActive = true;
-        mSource.addContentListener(mSourceListener);
-        mNeedReload.set(true);
-        mDataReady = true;
-        mReloadTask = mThreadPool.submit(new ReloadTask());
-    }
-}
diff --git a/src/com/android/gallery3d/app/SlideshowPage.java b/src/com/android/gallery3d/app/SlideshowPage.java
deleted file mode 100644
index 174058d..0000000
--- a/src/com/android/gallery3d/app/SlideshowPage.java
+++ /dev/null
@@ -1,366 +0,0 @@
-/*
- * Copyright (C) 2010 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.gallery3d.app;
-
-import android.app.Activity;
-import android.content.Intent;
-import android.graphics.Bitmap;
-import android.os.Bundle;
-import android.os.Handler;
-import android.os.Message;
-import android.view.MotionEvent;
-
-import com.android.gallery3d.R;
-import com.android.gallery3d.common.Utils;
-import com.android.gallery3d.data.ContentListener;
-import com.android.gallery3d.data.MediaItem;
-import com.android.gallery3d.data.MediaObject;
-import com.android.gallery3d.data.MediaSet;
-import com.android.gallery3d.data.Path;
-import com.android.gallery3d.glrenderer.GLCanvas;
-import com.android.gallery3d.ui.GLView;
-import com.android.gallery3d.ui.SlideshowView;
-import com.android.gallery3d.ui.SynchronizedHandler;
-import com.android.gallery3d.util.Future;
-import com.android.gallery3d.util.FutureListener;
-
-import java.util.ArrayList;
-import java.util.Random;
-
-public class SlideshowPage extends ActivityState {
-    private static final String TAG = "SlideshowPage";
-
-    public static final String KEY_SET_PATH = "media-set-path";
-    public static final String KEY_ITEM_PATH = "media-item-path";
-    public static final String KEY_PHOTO_INDEX = "photo-index";
-    public static final String KEY_RANDOM_ORDER = "random-order";
-    public static final String KEY_REPEAT = "repeat";
-    public static final String KEY_DREAM = "dream";
-
-    private static final long SLIDESHOW_DELAY = 3000; // 3 seconds
-
-    private static final int MSG_LOAD_NEXT_BITMAP = 1;
-    private static final int MSG_SHOW_PENDING_BITMAP = 2;
-
-    public static interface Model {
-        public void pause();
-
-        public void resume();
-
-        public Future<Slide> nextSlide(FutureListener<Slide> listener);
-    }
-
-    public static class Slide {
-        public Bitmap bitmap;
-        public MediaItem item;
-        public int index;
-
-        public Slide(MediaItem item, int index, Bitmap bitmap) {
-            this.bitmap = bitmap;
-            this.item = item;
-            this.index = index;
-        }
-    }
-
-    private Handler mHandler;
-    private Model mModel;
-    private SlideshowView mSlideshowView;
-
-    private Slide mPendingSlide = null;
-    private boolean mIsActive = false;
-    private final Intent mResultIntent = new Intent();
-
-    @Override
-    protected int getBackgroundColorId() {
-        return R.color.slideshow_background;
-    }
-
-    private final GLView mRootPane = new GLView() {
-        @Override
-        protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
-            mSlideshowView.layout(0, 0, right - left, bottom - top);
-        }
-
-        @Override
-        protected boolean onTouch(MotionEvent event) {
-            if (event.getAction() == MotionEvent.ACTION_UP) {
-                onBackPressed();
-            }
-            return true;
-        }
-
-        @Override
-        protected void renderBackground(GLCanvas canvas) {
-            canvas.clearBuffer(getBackgroundColor());
-        }
-    };
-
-    @Override
-    public void onCreate(Bundle data, Bundle restoreState) {
-        super.onCreate(data, restoreState);
-        mFlags |= (FLAG_HIDE_ACTION_BAR | FLAG_HIDE_STATUS_BAR);
-        if (data.getBoolean(KEY_DREAM)) {
-            // Dream screensaver only keeps screen on for plugged devices.
-            mFlags |= FLAG_SCREEN_ON_WHEN_PLUGGED | FLAG_SHOW_WHEN_LOCKED;
-        } else {
-            // User-initiated slideshow would always keep screen on.
-            mFlags |= FLAG_SCREEN_ON_ALWAYS;
-        }
-
-        mHandler = new SynchronizedHandler(mActivity.getGLRoot()) {
-            @Override
-            public void handleMessage(Message message) {
-                switch (message.what) {
-                    case MSG_SHOW_PENDING_BITMAP:
-                        showPendingBitmap();
-                        break;
-                    case MSG_LOAD_NEXT_BITMAP:
-                        loadNextBitmap();
-                        break;
-                    default: throw new AssertionError();
-                }
-            }
-        };
-        initializeViews();
-        initializeData(data);
-    }
-
-    private void loadNextBitmap() {
-        mModel.nextSlide(new FutureListener<Slide>() {
-            @Override
-            public void onFutureDone(Future<Slide> future) {
-                mPendingSlide = future.get();
-                mHandler.sendEmptyMessage(MSG_SHOW_PENDING_BITMAP);
-            }
-        });
-    }
-
-    private void showPendingBitmap() {
-        // mPendingBitmap could be null, if
-        // 1.) there is no more items
-        // 2.) mModel is paused
-        Slide slide = mPendingSlide;
-        if (slide == null) {
-            if (mIsActive) {
-                mActivity.getStateManager().finishState(SlideshowPage.this);
-            }
-            return;
-        }
-
-        mSlideshowView.next(slide.bitmap, slide.item.getRotation());
-
-        setStateResult(Activity.RESULT_OK, mResultIntent
-                .putExtra(KEY_ITEM_PATH, slide.item.getPath().toString())
-                .putExtra(KEY_PHOTO_INDEX, slide.index));
-        mHandler.sendEmptyMessageDelayed(MSG_LOAD_NEXT_BITMAP, SLIDESHOW_DELAY);
-    }
-
-    @Override
-    public void onPause() {
-        super.onPause();
-        mIsActive = false;
-        mModel.pause();
-        mSlideshowView.release();
-
-        mHandler.removeMessages(MSG_LOAD_NEXT_BITMAP);
-        mHandler.removeMessages(MSG_SHOW_PENDING_BITMAP);
-    }
-
-    @Override
-    public void onResume() {
-        super.onResume();
-        mIsActive = true;
-        mModel.resume();
-
-        if (mPendingSlide != null) {
-            showPendingBitmap();
-        } else {
-            loadNextBitmap();
-        }
-    }
-
-    private void initializeData(Bundle data) {
-        boolean random = data.getBoolean(KEY_RANDOM_ORDER, false);
-
-        // We only want to show slideshow for images only, not videos.
-        String mediaPath = data.getString(KEY_SET_PATH);
-        mediaPath = FilterUtils.newFilterPath(mediaPath, FilterUtils.FILTER_IMAGE_ONLY);
-        MediaSet mediaSet = mActivity.getDataManager().getMediaSet(mediaPath);
-
-        if (random) {
-            boolean repeat = data.getBoolean(KEY_REPEAT);
-            mModel = new SlideshowDataAdapter(mActivity,
-                    new ShuffleSource(mediaSet, repeat), 0, null);
-            setStateResult(Activity.RESULT_OK, mResultIntent.putExtra(KEY_PHOTO_INDEX, 0));
-        } else {
-            int index = data.getInt(KEY_PHOTO_INDEX);
-            String itemPath = data.getString(KEY_ITEM_PATH);
-            Path path = itemPath != null ? Path.fromString(itemPath) : null;
-            boolean repeat = data.getBoolean(KEY_REPEAT);
-            mModel = new SlideshowDataAdapter(mActivity, new SequentialSource(mediaSet, repeat),
-                    index, path);
-            setStateResult(Activity.RESULT_OK, mResultIntent.putExtra(KEY_PHOTO_INDEX, index));
-        }
-    }
-
-    private void initializeViews() {
-        mSlideshowView = new SlideshowView();
-        mRootPane.addComponent(mSlideshowView);
-        setContentPane(mRootPane);
-    }
-
-    private static MediaItem findMediaItem(MediaSet mediaSet, int index) {
-        for (int i = 0, n = mediaSet.getSubMediaSetCount(); i < n; ++i) {
-            MediaSet subset = mediaSet.getSubMediaSet(i);
-            int count = subset.getTotalMediaItemCount();
-            if (index < count) {
-                return findMediaItem(subset, index);
-            }
-            index -= count;
-        }
-        ArrayList<MediaItem> list = mediaSet.getMediaItem(index, 1);
-        return list.isEmpty() ? null : list.get(0);
-    }
-
-    private static class ShuffleSource implements SlideshowDataAdapter.SlideshowSource {
-        private static final int RETRY_COUNT = 5;
-        private final MediaSet mMediaSet;
-        private final Random mRandom = new Random();
-        private int mOrder[] = new int[0];
-        private final boolean mRepeat;
-        private long mSourceVersion = MediaSet.INVALID_DATA_VERSION;
-        private int mLastIndex = -1;
-
-        public ShuffleSource(MediaSet mediaSet, boolean repeat) {
-            mMediaSet = Utils.checkNotNull(mediaSet);
-            mRepeat = repeat;
-        }
-
-        @Override
-        public int findItemIndex(Path path, int hint) {
-            return hint;
-        }
-
-        @Override
-        public MediaItem getMediaItem(int index) {
-            if (!mRepeat && index >= mOrder.length) return null;
-            if (mOrder.length == 0) return null;
-            mLastIndex = mOrder[index % mOrder.length];
-            MediaItem item = findMediaItem(mMediaSet, mLastIndex);
-            for (int i = 0; i < RETRY_COUNT && item == null; ++i) {
-                Log.w(TAG, "fail to find image: " + mLastIndex);
-                mLastIndex = mRandom.nextInt(mOrder.length);
-                item = findMediaItem(mMediaSet, mLastIndex);
-            }
-            return item;
-        }
-
-        @Override
-        public long reload() {
-            long version = mMediaSet.reload();
-            if (version != mSourceVersion) {
-                mSourceVersion = version;
-                int count = mMediaSet.getTotalMediaItemCount();
-                if (count != mOrder.length) generateOrderArray(count);
-            }
-            return version;
-        }
-
-        private void generateOrderArray(int totalCount) {
-            if (mOrder.length != totalCount) {
-                mOrder = new int[totalCount];
-                for (int i = 0; i < totalCount; ++i) {
-                    mOrder[i] = i;
-                }
-            }
-            for (int i = totalCount - 1; i > 0; --i) {
-                Utils.swap(mOrder, i, mRandom.nextInt(i + 1));
-            }
-            if (mOrder[0] == mLastIndex && totalCount > 1) {
-                Utils.swap(mOrder, 0, mRandom.nextInt(totalCount - 1) + 1);
-            }
-        }
-
-        @Override
-        public void addContentListener(ContentListener listener) {
-            mMediaSet.addContentListener(listener);
-        }
-
-        @Override
-        public void removeContentListener(ContentListener listener) {
-            mMediaSet.removeContentListener(listener);
-        }
-    }
-
-    private static class SequentialSource implements SlideshowDataAdapter.SlideshowSource {
-        private static final int DATA_SIZE = 32;
-
-        private ArrayList<MediaItem> mData = new ArrayList<MediaItem>();
-        private int mDataStart = 0;
-        private long mDataVersion = MediaObject.INVALID_DATA_VERSION;
-        private final MediaSet mMediaSet;
-        private final boolean mRepeat;
-
-        public SequentialSource(MediaSet mediaSet, boolean repeat) {
-            mMediaSet = mediaSet;
-            mRepeat = repeat;
-        }
-
-        @Override
-        public int findItemIndex(Path path, int hint) {
-            return mMediaSet.getIndexOfItem(path, hint);
-        }
-
-        @Override
-        public MediaItem getMediaItem(int index) {
-            int dataEnd = mDataStart + mData.size();
-
-            if (mRepeat) {
-                int count = mMediaSet.getMediaItemCount();
-                if (count == 0) return null;
-                index = index % count;
-            }
-            if (index < mDataStart || index >= dataEnd) {
-                mData = mMediaSet.getMediaItem(index, DATA_SIZE);
-                mDataStart = index;
-                dataEnd = index + mData.size();
-            }
-
-            return (index < mDataStart || index >= dataEnd) ? null : mData.get(index - mDataStart);
-        }
-
-        @Override
-        public long reload() {
-            long version = mMediaSet.reload();
-            if (version != mDataVersion) {
-                mDataVersion = version;
-                mData.clear();
-            }
-            return mDataVersion;
-        }
-
-        @Override
-        public void addContentListener(ContentListener listener) {
-            mMediaSet.addContentListener(listener);
-        }
-
-        @Override
-        public void removeContentListener(ContentListener listener) {
-            mMediaSet.removeContentListener(listener);
-        }
-    }
-}
diff --git a/src/com/android/gallery3d/app/StateManager.java b/src/com/android/gallery3d/app/StateManager.java
deleted file mode 100644
index 53c3fc2..0000000
--- a/src/com/android/gallery3d/app/StateManager.java
+++ /dev/null
@@ -1,339 +0,0 @@
-/*
- * Copyright (C) 2010 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.gallery3d.app;
-
-import android.app.Activity;
-import android.content.Intent;
-import android.content.res.Configuration;
-import android.os.Bundle;
-import android.os.Parcelable;
-import android.view.Menu;
-import android.view.MenuItem;
-
-import com.android.camera.CameraActivity;
-import com.android.gallery3d.anim.StateTransitionAnimation;
-import com.android.gallery3d.common.Utils;
-import com.android.gallery3d.util.UsageStatistics;
-
-import java.util.Stack;
-
-public class StateManager {
-    @SuppressWarnings("unused")
-    private static final String TAG = "StateManager";
-    private boolean mIsResumed = false;
-
-    private static final String KEY_MAIN = "activity-state";
-    private static final String KEY_DATA = "data";
-    private static final String KEY_STATE = "bundle";
-    private static final String KEY_CLASS = "class";
-
-    private AbstractGalleryActivity mActivity;
-    private Stack<StateEntry> mStack = new Stack<StateEntry>();
-    private ActivityState.ResultEntry mResult;
-
-    public StateManager(AbstractGalleryActivity activity) {
-        mActivity = activity;
-    }
-
-    public void startState(Class<? extends ActivityState> klass,
-            Bundle data) {
-        Log.v(TAG, "startState " + klass);
-        ActivityState state = null;
-        try {
-            state = klass.newInstance();
-        } catch (Exception e) {
-            throw new AssertionError(e);
-        }
-        if (!mStack.isEmpty()) {
-            ActivityState top = getTopState();
-            top.transitionOnNextPause(top.getClass(), klass,
-                    StateTransitionAnimation.Transition.Incoming);
-            if (mIsResumed) top.onPause();
-        }
-
-        UsageStatistics.onContentViewChanged(
-                UsageStatistics.COMPONENT_GALLERY,
-                klass.getSimpleName());
-        state.initialize(mActivity, data);
-
-        mStack.push(new StateEntry(data, state));
-        state.onCreate(data, null);
-        if (mIsResumed) state.resume();
-    }
-
-    public void startStateForResult(Class<? extends ActivityState> klass,
-            int requestCode, Bundle data) {
-        Log.v(TAG, "startStateForResult " + klass + ", " + requestCode);
-        ActivityState state = null;
-        try {
-            state = klass.newInstance();
-        } catch (Exception e) {
-            throw new AssertionError(e);
-        }
-        state.initialize(mActivity, data);
-        state.mResult = new ActivityState.ResultEntry();
-        state.mResult.requestCode = requestCode;
-
-        if (!mStack.isEmpty()) {
-            ActivityState as = getTopState();
-            as.transitionOnNextPause(as.getClass(), klass,
-                    StateTransitionAnimation.Transition.Incoming);
-            as.mReceivedResults = state.mResult;
-            if (mIsResumed) as.onPause();
-        } else {
-            mResult = state.mResult;
-        }
-        UsageStatistics.onContentViewChanged(UsageStatistics.COMPONENT_GALLERY,
-                klass.getSimpleName());
-        mStack.push(new StateEntry(data, state));
-        state.onCreate(data, null);
-        if (mIsResumed) state.resume();
-    }
-
-    public boolean createOptionsMenu(Menu menu) {
-        if (mStack.isEmpty()) {
-            return false;
-        } else {
-            return getTopState().onCreateActionBar(menu);
-        }
-    }
-
-    public void onConfigurationChange(Configuration config) {
-        for (StateEntry entry : mStack) {
-            entry.activityState.onConfigurationChanged(config);
-        }
-    }
-
-    public void resume() {
-        if (mIsResumed) return;
-        mIsResumed = true;
-        if (!mStack.isEmpty()) getTopState().resume();
-    }
-
-    public void pause() {
-        if (!mIsResumed) return;
-        mIsResumed = false;
-        if (!mStack.isEmpty()) getTopState().onPause();
-    }
-
-    public void notifyActivityResult(int requestCode, int resultCode, Intent data) {
-        getTopState().onStateResult(requestCode, resultCode, data);
-    }
-
-    public void clearActivityResult() {
-        if (!mStack.isEmpty()) {
-            getTopState().clearStateResult();
-        }
-    }
-
-    public int getStateCount() {
-        return mStack.size();
-    }
-
-    public boolean itemSelected(MenuItem item) {
-        if (!mStack.isEmpty()) {
-            if (getTopState().onItemSelected(item)) return true;
-            if (item.getItemId() == android.R.id.home) {
-                if (mStack.size() > 1) {
-                    getTopState().onBackPressed();
-                }
-                return true;
-            }
-        }
-        return false;
-    }
-
-    public void onBackPressed() {
-        if (!mStack.isEmpty()) {
-            getTopState().onBackPressed();
-        }
-    }
-
-    void finishState(ActivityState state) {
-        finishState(state, true);
-    }
-
-    public void clearTasks() {
-        // Remove all the states that are on top of the bottom PhotoPage state
-        while (mStack.size() > 1) {
-            mStack.pop().activityState.onDestroy();
-        }
-    }
-
-    void finishState(ActivityState state, boolean fireOnPause) {
-        // The finish() request could be rejected (only happens under Monkey),
-        // If it is rejected, we won't close the last page.
-        if (mStack.size() == 1) {
-            Activity activity = (Activity) mActivity.getAndroidContext();
-            if (mResult != null) {
-                activity.setResult(mResult.resultCode, mResult.resultData);
-            }
-            activity.finish();
-            if (!activity.isFinishing()) {
-                Log.w(TAG, "finish is rejected, keep the last state");
-                return;
-            }
-            Log.v(TAG, "no more state, finish activity");
-        }
-
-        Log.v(TAG, "finishState " + state);
-        if (state != mStack.peek().activityState) {
-            if (state.isDestroyed()) {
-                Log.d(TAG, "The state is already destroyed");
-                return;
-            } else {
-                throw new IllegalArgumentException("The stateview to be finished"
-                        + " is not at the top of the stack: " + state + ", "
-                        + mStack.peek().activityState);
-            }
-        }
-
-        // Remove the top state.
-        mStack.pop();
-        state.mIsFinishing = true;
-        ActivityState top = !mStack.isEmpty() ? mStack.peek().activityState : null;
-        if (mIsResumed && fireOnPause) {
-            if (top != null) {
-                state.transitionOnNextPause(state.getClass(), top.getClass(),
-                        StateTransitionAnimation.Transition.Outgoing);
-            }
-            state.onPause();
-        }
-        mActivity.getGLRoot().setContentPane(null);
-        state.onDestroy();
-
-        if (top != null && mIsResumed) top.resume();
-        if (top != null) {
-            UsageStatistics.onContentViewChanged(UsageStatistics.COMPONENT_GALLERY,
-                    top.getClass().getSimpleName());
-        }
-    }
-
-    public void switchState(ActivityState oldState,
-            Class<? extends ActivityState> klass, Bundle data) {
-        Log.v(TAG, "switchState " + oldState + ", " + klass);
-        if (oldState != mStack.peek().activityState) {
-            throw new IllegalArgumentException("The stateview to be finished"
-                    + " is not at the top of the stack: " + oldState + ", "
-                    + mStack.peek().activityState);
-        }
-        // Remove the top state.
-        mStack.pop();
-        if (!data.containsKey(PhotoPage.KEY_APP_BRIDGE)) {
-            // Do not do the fade out stuff when we are switching camera modes
-            oldState.transitionOnNextPause(oldState.getClass(), klass,
-                    StateTransitionAnimation.Transition.Incoming);
-        }
-        if (mIsResumed) oldState.onPause();
-        oldState.onDestroy();
-
-        // Create new state.
-        ActivityState state = null;
-        try {
-            state = klass.newInstance();
-        } catch (Exception e) {
-            throw new AssertionError(e);
-        }
-        state.initialize(mActivity, data);
-        mStack.push(new StateEntry(data, state));
-        state.onCreate(data, null);
-        if (mIsResumed) state.resume();
-        UsageStatistics.onContentViewChanged(UsageStatistics.COMPONENT_GALLERY,
-                klass.getSimpleName());
-    }
-
-    public void destroy() {
-        Log.v(TAG, "destroy");
-        while (!mStack.isEmpty()) {
-            mStack.pop().activityState.onDestroy();
-        }
-        mStack.clear();
-    }
-
-    @SuppressWarnings("unchecked")
-    public void restoreFromState(Bundle inState) {
-        Log.v(TAG, "restoreFromState");
-        Parcelable list[] = inState.getParcelableArray(KEY_MAIN);
-        ActivityState topState = null;
-        for (Parcelable parcelable : list) {
-            Bundle bundle = (Bundle) parcelable;
-            Class<? extends ActivityState> klass =
-                    (Class<? extends ActivityState>) bundle.getSerializable(KEY_CLASS);
-
-            Bundle data = bundle.getBundle(KEY_DATA);
-            Bundle state = bundle.getBundle(KEY_STATE);
-
-            ActivityState activityState;
-            try {
-                Log.v(TAG, "restoreFromState " + klass);
-                activityState = klass.newInstance();
-            } catch (Exception e) {
-                throw new AssertionError(e);
-            }
-            activityState.initialize(mActivity, data);
-            activityState.onCreate(data, state);
-            mStack.push(new StateEntry(data, activityState));
-            topState = activityState;
-        }
-        if (topState != null) {
-            UsageStatistics.onContentViewChanged(UsageStatistics.COMPONENT_GALLERY,
-                    topState.getClass().getSimpleName());
-        }
-    }
-
-    public void saveState(Bundle outState) {
-        Log.v(TAG, "saveState");
-
-        Parcelable list[] = new Parcelable[mStack.size()];
-        int i = 0;
-        for (StateEntry entry : mStack) {
-            Bundle bundle = new Bundle();
-            bundle.putSerializable(KEY_CLASS, entry.activityState.getClass());
-            bundle.putBundle(KEY_DATA, entry.data);
-            Bundle state = new Bundle();
-            entry.activityState.onSaveState(state);
-            bundle.putBundle(KEY_STATE, state);
-            Log.v(TAG, "saveState " + entry.activityState.getClass());
-            list[i++] = bundle;
-        }
-        outState.putParcelableArray(KEY_MAIN, list);
-    }
-
-    public boolean hasStateClass(Class<? extends ActivityState> klass) {
-        for (StateEntry entry : mStack) {
-            if (klass.isInstance(entry.activityState)) {
-                return true;
-            }
-        }
-        return false;
-    }
-
-    public ActivityState getTopState() {
-        Utils.assertTrue(!mStack.isEmpty());
-        return mStack.peek().activityState;
-    }
-
-    private static class StateEntry {
-        public Bundle data;
-        public ActivityState activityState;
-
-        public StateEntry(Bundle data, ActivityState state) {
-            this.data = data;
-            this.activityState = state;
-        }
-    }
-}
diff --git a/src/com/android/gallery3d/app/StitchingChangeListener.java b/src/com/android/gallery3d/app/StitchingChangeListener.java
deleted file mode 100644
index 0b8c2d6..0000000
--- a/src/com/android/gallery3d/app/StitchingChangeListener.java
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * 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.gallery3d.app;
-
-import android.net.Uri;
-
-public interface StitchingChangeListener {
-    public void onStitchingQueued(Uri uri);
-
-    public void onStitchingResult(Uri uri);
-
-    public void onStitchingProgress(Uri uri, int progress);
-}
diff --git a/src/com/android/gallery3d/app/TimeBar.java b/src/com/android/gallery3d/app/TimeBar.java
deleted file mode 100644
index 246346a..0000000
--- a/src/com/android/gallery3d/app/TimeBar.java
+++ /dev/null
@@ -1,266 +0,0 @@
-/*
- * Copyright (C) 2011 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.gallery3d.app;
-
-import android.content.Context;
-import android.graphics.Bitmap;
-import android.graphics.BitmapFactory;
-import android.graphics.Canvas;
-import android.graphics.Paint;
-import android.graphics.Rect;
-import android.util.DisplayMetrics;
-import android.view.MotionEvent;
-import android.view.View;
-
-import com.android.gallery3d.R;
-import com.android.gallery3d.common.Utils;
-
-/**
- * The time bar view, which includes the current and total time, the progress
- * bar, and the scrubber.
- */
-public class TimeBar extends View {
-
-    public interface Listener {
-        void onScrubbingStart();
-
-        void onScrubbingMove(int time);
-
-        void onScrubbingEnd(int time, int start, int end);
-    }
-
-    // Padding around the scrubber to increase its touch target
-    private static final int SCRUBBER_PADDING_IN_DP = 10;
-
-    // The total padding, top plus bottom
-    private static final int V_PADDING_IN_DP = 30;
-
-    private static final int TEXT_SIZE_IN_DP = 14;
-
-    protected final Listener mListener;
-
-    // the bars we use for displaying the progress
-    protected final Rect mProgressBar;
-    protected final Rect mPlayedBar;
-
-    protected final Paint mProgressPaint;
-    protected final Paint mPlayedPaint;
-    protected final Paint mTimeTextPaint;
-
-    protected final Bitmap mScrubber;
-    protected int mScrubberPadding; // adds some touch tolerance around the
-                                    // scrubber
-
-    protected int mScrubberLeft;
-    protected int mScrubberTop;
-    protected int mScrubberCorrection;
-    protected boolean mScrubbing;
-    protected boolean mShowTimes;
-    protected boolean mShowScrubber;
-
-    protected int mTotalTime;
-    protected int mCurrentTime;
-
-    protected final Rect mTimeBounds;
-
-    protected int mVPaddingInPx;
-
-    public TimeBar(Context context, Listener listener) {
-        super(context);
-        mListener = Utils.checkNotNull(listener);
-
-        mShowTimes = true;
-        mShowScrubber = true;
-
-        mProgressBar = new Rect();
-        mPlayedBar = new Rect();
-
-        mProgressPaint = new Paint();
-        mProgressPaint.setColor(0xFF808080);
-        mPlayedPaint = new Paint();
-        mPlayedPaint.setColor(0xFFFFFFFF);
-
-        DisplayMetrics metrics = context.getResources().getDisplayMetrics();
-        float textSizeInPx = metrics.density * TEXT_SIZE_IN_DP;
-        mTimeTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
-        mTimeTextPaint.setColor(0xFFCECECE);
-        mTimeTextPaint.setTextSize(textSizeInPx);
-        mTimeTextPaint.setTextAlign(Paint.Align.CENTER);
-
-        mTimeBounds = new Rect();
-        mTimeTextPaint.getTextBounds("0:00:00", 0, 7, mTimeBounds);
-
-        mScrubber = BitmapFactory.decodeResource(getResources(), R.drawable.scrubber_knob);
-        mScrubberPadding = (int) (metrics.density * SCRUBBER_PADDING_IN_DP);
-
-        mVPaddingInPx = (int) (metrics.density * V_PADDING_IN_DP);
-    }
-
-    private void update() {
-        mPlayedBar.set(mProgressBar);
-
-        if (mTotalTime > 0) {
-            mPlayedBar.right =
-                    mPlayedBar.left + (int) ((mProgressBar.width() * (long) mCurrentTime) / mTotalTime);
-        } else {
-            mPlayedBar.right = mProgressBar.left;
-        }
-
-        if (!mScrubbing) {
-            mScrubberLeft = mPlayedBar.right - mScrubber.getWidth() / 2;
-        }
-        invalidate();
-    }
-
-    /**
-     * @return the preferred height of this view, including invisible padding
-     */
-    public int getPreferredHeight() {
-        return mTimeBounds.height() + mVPaddingInPx + mScrubberPadding;
-    }
-
-    /**
-     * @return the height of the time bar, excluding invisible padding
-     */
-    public int getBarHeight() {
-        return mTimeBounds.height() + mVPaddingInPx;
-    }
-
-    public void setTime(int currentTime, int totalTime,
-            int trimStartTime, int trimEndTime) {
-        if (mCurrentTime == currentTime && mTotalTime == totalTime) {
-            return;
-        }
-        mCurrentTime = currentTime;
-        mTotalTime = totalTime;
-        update();
-    }
-
-    private boolean inScrubber(float x, float y) {
-        int scrubberRight = mScrubberLeft + mScrubber.getWidth();
-        int scrubberBottom = mScrubberTop + mScrubber.getHeight();
-        return mScrubberLeft - mScrubberPadding < x && x < scrubberRight + mScrubberPadding
-                && mScrubberTop - mScrubberPadding < y && y < scrubberBottom + mScrubberPadding;
-    }
-
-    private void clampScrubber() {
-        int half = mScrubber.getWidth() / 2;
-        int max = mProgressBar.right - half;
-        int min = mProgressBar.left - half;
-        mScrubberLeft = Math.min(max, Math.max(min, mScrubberLeft));
-    }
-
-    private int getScrubberTime() {
-        return (int) ((long) (mScrubberLeft + mScrubber.getWidth() / 2 - mProgressBar.left)
-                * mTotalTime / mProgressBar.width());
-    }
-
-    @Override
-    protected void onLayout(boolean changed, int l, int t, int r, int b) {
-        int w = r - l;
-        int h = b - t;
-        if (!mShowTimes && !mShowScrubber) {
-            mProgressBar.set(0, 0, w, h);
-        } else {
-            int margin = mScrubber.getWidth() / 3;
-            if (mShowTimes) {
-                margin += mTimeBounds.width();
-            }
-            int progressY = (h + mScrubberPadding) / 2;
-            mScrubberTop = progressY - mScrubber.getHeight() / 2 + 1;
-            mProgressBar.set(
-                    getPaddingLeft() + margin, progressY,
-                    w - getPaddingRight() - margin, progressY + 4);
-        }
-        update();
-    }
-
-    @Override
-    protected void onDraw(Canvas canvas) {
-        // draw progress bars
-        canvas.drawRect(mProgressBar, mProgressPaint);
-        canvas.drawRect(mPlayedBar, mPlayedPaint);
-
-        // draw scrubber and timers
-        if (mShowScrubber) {
-            canvas.drawBitmap(mScrubber, mScrubberLeft, mScrubberTop, null);
-        }
-        if (mShowTimes) {
-            canvas.drawText(
-                    stringForTime(mCurrentTime),
-                            mTimeBounds.width() / 2 + getPaddingLeft(),
-                            mTimeBounds.height() + mVPaddingInPx / 2 + mScrubberPadding + 1,
-                    mTimeTextPaint);
-            canvas.drawText(
-                    stringForTime(mTotalTime),
-                            getWidth() - getPaddingRight() - mTimeBounds.width() / 2,
-                            mTimeBounds.height() + mVPaddingInPx / 2 + mScrubberPadding + 1,
-                    mTimeTextPaint);
-        }
-    }
-
-    @Override
-    public boolean onTouchEvent(MotionEvent event) {
-        if (mShowScrubber) {
-            int x = (int) event.getX();
-            int y = (int) event.getY();
-
-            switch (event.getAction()) {
-                case MotionEvent.ACTION_DOWN: {
-                    mScrubberCorrection = inScrubber(x, y)
-                            ? x - mScrubberLeft
-                            : mScrubber.getWidth() / 2;
-                    mScrubbing = true;
-                    mListener.onScrubbingStart();
-                }
-                // fall-through
-                case MotionEvent.ACTION_MOVE: {
-                    mScrubberLeft = x - mScrubberCorrection;
-                    clampScrubber();
-                    mCurrentTime = getScrubberTime();
-                    mListener.onScrubbingMove(mCurrentTime);
-                    invalidate();
-                    return true;
-                }
-                case MotionEvent.ACTION_CANCEL:
-                case MotionEvent.ACTION_UP: {
-                    mListener.onScrubbingEnd(getScrubberTime(), 0, 0);
-                    mScrubbing = false;
-                    return true;
-                }
-            }
-        }
-        return false;
-    }
-
-    protected String stringForTime(long millis) {
-        int totalSeconds = (int) millis / 1000;
-        int seconds = totalSeconds % 60;
-        int minutes = (totalSeconds / 60) % 60;
-        int hours = totalSeconds / 3600;
-        if (hours > 0) {
-            return String.format("%d:%02d:%02d", hours, minutes, seconds).toString();
-        } else {
-            return String.format("%02d:%02d", minutes, seconds).toString();
-        }
-    }
-
-    public void setSeekable(boolean canSeek) {
-        mShowScrubber = canSeek;
-    }
-
-}
diff --git a/src/com/android/gallery3d/app/TransitionStore.java b/src/com/android/gallery3d/app/TransitionStore.java
deleted file mode 100644
index aa38ed7..0000000
--- a/src/com/android/gallery3d/app/TransitionStore.java
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * 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.gallery3d.app;
-
-import java.util.HashMap;
-
-public class TransitionStore {
-    private HashMap<Object, Object> mStorage = new HashMap<Object, Object>();
-
-    public void put(Object key, Object value) {
-        mStorage.put(key, value);
-    }
-
-    public <T> void putIfNotPresent(Object key, T valueIfNull) {
-        mStorage.put(key, get(key, valueIfNull));
-    }
-
-    @SuppressWarnings("unchecked")
-    public <T> T get(Object key) {
-        return (T) mStorage.get(key);
-    }
-
-    @SuppressWarnings("unchecked")
-    public <T> T get(Object key, T valueIfNull) {
-        T value = (T) mStorage.get(key);
-        return value == null ? valueIfNull : value;
-    }
-
-    public void clear() {
-        mStorage.clear();
-    }
-}
diff --git a/src/com/android/gallery3d/app/TrimControllerOverlay.java b/src/com/android/gallery3d/app/TrimControllerOverlay.java
deleted file mode 100644
index cae0166..0000000
--- a/src/com/android/gallery3d/app/TrimControllerOverlay.java
+++ /dev/null
@@ -1,111 +0,0 @@
-/*
- * 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.gallery3d.app;
-
-import android.animation.Animator;
-import android.animation.Animator.AnimatorListener;
-import android.animation.ObjectAnimator;
-import android.content.Context;
-import android.view.MotionEvent;
-import android.view.View;
-
-import com.android.gallery3d.common.ApiHelper;
-
-/**
- * The controller for the Trimming Video.
- */
-public class TrimControllerOverlay extends CommonControllerOverlay  {
-
-    public TrimControllerOverlay(Context context) {
-        super(context);
-    }
-
-    @Override
-    protected void createTimeBar(Context context) {
-        mTimeBar = new TrimTimeBar(context, this);
-    }
-
-    private void hidePlayButtonIfPlaying() {
-        if (mState == State.PLAYING) {
-            mPlayPauseReplayView.setVisibility(View.INVISIBLE);
-        }
-        if (ApiHelper.HAS_OBJECT_ANIMATION) {
-            mPlayPauseReplayView.setAlpha(1f);
-        }
-    }
-
-    @Override
-    public void showPlaying() {
-        super.showPlaying();
-        if (ApiHelper.HAS_OBJECT_ANIMATION) {
-            // Add animation to hide the play button while playing.
-            ObjectAnimator anim = ObjectAnimator.ofFloat(mPlayPauseReplayView, "alpha", 1f, 0f);
-            anim.setDuration(200);
-            anim.start();
-            anim.addListener(new AnimatorListener() {
-                @Override
-                public void onAnimationStart(Animator animation) {
-                }
-
-                @Override
-                public void onAnimationEnd(Animator animation) {
-                    hidePlayButtonIfPlaying();
-                }
-
-                @Override
-                public void onAnimationCancel(Animator animation) {
-                    hidePlayButtonIfPlaying();
-                }
-
-                @Override
-                public void onAnimationRepeat(Animator animation) {
-                }
-            });
-        } else {
-            hidePlayButtonIfPlaying();
-        }
-    }
-
-    @Override
-    public void setTimes(int currentTime, int totalTime, int trimStartTime, int trimEndTime) {
-        mTimeBar.setTime(currentTime, totalTime, trimStartTime, trimEndTime);
-    }
-
-    @Override
-    public boolean onTouchEvent(MotionEvent event) {
-        if (super.onTouchEvent(event)) {
-            return true;
-        }
-
-        // The special thing here is that the State.ENDED include both cases of
-        // the video completed and current == trimEnd. Both request a replay.
-        switch (event.getAction()) {
-            case MotionEvent.ACTION_DOWN:
-                if (mState == State.PLAYING || mState == State.PAUSED) {
-                    mListener.onPlayPause();
-                } else if (mState == State.ENDED) {
-                    if (mCanReplay) {
-                        mListener.onReplay();
-                    }
-                }
-                break;
-            case MotionEvent.ACTION_UP:
-                break;
-        }
-        return true;
-    }
-}
diff --git a/src/com/android/gallery3d/app/TrimTimeBar.java b/src/com/android/gallery3d/app/TrimTimeBar.java
deleted file mode 100644
index f8dbc74..0000000
--- a/src/com/android/gallery3d/app/TrimTimeBar.java
+++ /dev/null
@@ -1,339 +0,0 @@
-/*
- * 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.gallery3d.app;
-
-import android.content.Context;
-import android.graphics.Bitmap;
-import android.graphics.BitmapFactory;
-import android.graphics.Canvas;
-import android.view.MotionEvent;
-
-import com.android.gallery3d.R;
-
-/**
- * The trim time bar view, which includes the current and total time, the progress
- * bar, and the scrubbers for current time, start and end time for trimming.
- */
-public class TrimTimeBar extends TimeBar {
-
-    public static final int SCRUBBER_NONE = 0;
-    public static final int SCRUBBER_START = 1;
-    public static final int SCRUBBER_CURRENT = 2;
-    public static final int SCRUBBER_END = 3;
-
-    private int mPressedThumb = SCRUBBER_NONE;
-
-    // On touch event, the setting order is Scrubber Position -> Time ->
-    // PlayedBar. At the setTimes(), activity can update the Time directly, then
-    // PlayedBar will be updated too.
-    private int mTrimStartScrubberLeft;
-    private int mTrimEndScrubberLeft;
-
-    private int mTrimStartScrubberTop;
-    private int mTrimEndScrubberTop;
-
-    private int mTrimStartTime;
-    private int mTrimEndTime;
-
-    private final Bitmap mTrimStartScrubber;
-    private final Bitmap mTrimEndScrubber;
-    public TrimTimeBar(Context context, Listener listener) {
-        super(context, listener);
-
-        mTrimStartTime = 0;
-        mTrimEndTime = 0;
-        mTrimStartScrubberLeft = 0;
-        mTrimEndScrubberLeft = 0;
-        mTrimStartScrubberTop = 0;
-        mTrimEndScrubberTop = 0;
-
-        mTrimStartScrubber = BitmapFactory.decodeResource(getResources(),
-                R.drawable.text_select_handle_left);
-        mTrimEndScrubber = BitmapFactory.decodeResource(getResources(),
-                R.drawable.text_select_handle_right);
-        // Increase the size of this trimTimeBar, but minimize the scrubber
-        // touch padding since we have 3 scrubbers now.
-        mScrubberPadding = 0;
-        mVPaddingInPx = mVPaddingInPx * 3 / 2;
-    }
-
-    private int getBarPosFromTime(int time) {
-        return mProgressBar.left +
-                (int) ((mProgressBar.width() * (long) time) / mTotalTime);
-    }
-
-    private int trimStartScrubberTipOffset() {
-        return mTrimStartScrubber.getWidth() * 3 / 4;
-    }
-
-    private int trimEndScrubberTipOffset() {
-        return mTrimEndScrubber.getWidth() / 4;
-    }
-
-    // Based on all the time info (current, total, trimStart, trimEnd), we
-    // decide the playedBar size.
-    private void updatePlayedBarAndScrubberFromTime() {
-        // According to the Time, update the Played Bar
-        mPlayedBar.set(mProgressBar);
-        if (mTotalTime > 0) {
-            // set playedBar according to the trim time.
-            mPlayedBar.left = getBarPosFromTime(mTrimStartTime);
-            mPlayedBar.right = getBarPosFromTime(mCurrentTime);
-            if (!mScrubbing) {
-                mScrubberLeft = mPlayedBar.right - mScrubber.getWidth() / 2;
-                mTrimStartScrubberLeft = mPlayedBar.left - trimStartScrubberTipOffset();
-                mTrimEndScrubberLeft = getBarPosFromTime(mTrimEndTime)
-                        - trimEndScrubberTipOffset();
-            }
-        } else {
-            // If the video is not prepared, just show the scrubber at the end
-            // of progressBar
-            mPlayedBar.right = mProgressBar.left;
-            mScrubberLeft = mProgressBar.left - mScrubber.getWidth() / 2;
-            mTrimStartScrubberLeft = mProgressBar.left - trimStartScrubberTipOffset();
-            mTrimEndScrubberLeft = mProgressBar.right - trimEndScrubberTipOffset();
-        }
-    }
-
-    private void initTrimTimeIfNeeded() {
-        if (mTotalTime > 0 && mTrimEndTime == 0) {
-            mTrimEndTime = mTotalTime;
-        }
-    }
-
-    private void update() {
-        initTrimTimeIfNeeded();
-        updatePlayedBarAndScrubberFromTime();
-        invalidate();
-    }
-
-    @Override
-    public void setTime(int currentTime, int totalTime,
-            int trimStartTime, int trimEndTime) {
-        if (mCurrentTime == currentTime && mTotalTime == totalTime
-                && mTrimStartTime == trimStartTime && mTrimEndTime == trimEndTime) {
-            return;
-        }
-        mCurrentTime = currentTime;
-        mTotalTime = totalTime;
-        mTrimStartTime = trimStartTime;
-        mTrimEndTime = trimEndTime;
-        update();
-    }
-
-    private int whichScrubber(float x, float y) {
-        if (inScrubber(x, y, mTrimStartScrubberLeft, mTrimStartScrubberTop, mTrimStartScrubber)) {
-            return SCRUBBER_START;
-        } else if (inScrubber(x, y, mTrimEndScrubberLeft, mTrimEndScrubberTop, mTrimEndScrubber)) {
-            return SCRUBBER_END;
-        } else if (inScrubber(x, y, mScrubberLeft, mScrubberTop, mScrubber)) {
-            return SCRUBBER_CURRENT;
-        }
-        return SCRUBBER_NONE;
-    }
-
-    private boolean inScrubber(float x, float y, int startX, int startY, Bitmap scrubber) {
-        int scrubberRight = startX + scrubber.getWidth();
-        int scrubberBottom = startY + scrubber.getHeight();
-        return startX < x && x < scrubberRight && startY < y && y < scrubberBottom;
-    }
-
-    private int clampScrubber(int scrubberLeft, int offset, int lowerBound, int upperBound) {
-        int max = upperBound - offset;
-        int min = lowerBound - offset;
-        return Math.min(max, Math.max(min, scrubberLeft));
-    }
-
-    private int getScrubberTime(int scrubberLeft, int offset) {
-        return (int) ((long) (scrubberLeft + offset - mProgressBar.left)
-                * mTotalTime / mProgressBar.width());
-    }
-
-    @Override
-    protected void onLayout(boolean changed, int l, int t, int r, int b) {
-        int w = r - l;
-        int h = b - t;
-        if (!mShowTimes && !mShowScrubber) {
-            mProgressBar.set(0, 0, w, h);
-        } else {
-            int margin = mScrubber.getWidth() / 3;
-            if (mShowTimes) {
-                margin += mTimeBounds.width();
-            }
-            int progressY = h / 4;
-            int scrubberY = progressY - mScrubber.getHeight() / 2 + 1;
-            mScrubberTop = scrubberY;
-            mTrimStartScrubberTop = progressY;
-            mTrimEndScrubberTop = progressY;
-            mProgressBar.set(
-                    getPaddingLeft() + margin, progressY,
-                    w - getPaddingRight() - margin, progressY + 4);
-        }
-        update();
-    }
-
-    @Override
-    protected void onDraw(Canvas canvas) {
-        // draw progress bars
-        canvas.drawRect(mProgressBar, mProgressPaint);
-        canvas.drawRect(mPlayedBar, mPlayedPaint);
-
-        if (mShowTimes) {
-            canvas.drawText(
-                    stringForTime(mCurrentTime),
-                            mTimeBounds.width() / 2 + getPaddingLeft(),
-                            mTimeBounds.height() / 2 +  mTrimStartScrubberTop,
-                    mTimeTextPaint);
-            canvas.drawText(
-                    stringForTime(mTotalTime),
-                            getWidth() - getPaddingRight() - mTimeBounds.width() / 2,
-                            mTimeBounds.height() / 2 +  mTrimStartScrubberTop,
-                    mTimeTextPaint);
-        }
-
-        // draw extra scrubbers
-        if (mShowScrubber) {
-            canvas.drawBitmap(mScrubber, mScrubberLeft, mScrubberTop, null);
-            canvas.drawBitmap(mTrimStartScrubber, mTrimStartScrubberLeft,
-                    mTrimStartScrubberTop, null);
-            canvas.drawBitmap(mTrimEndScrubber, mTrimEndScrubberLeft,
-                    mTrimEndScrubberTop, null);
-        }
-    }
-
-    private void updateTimeFromPos() {
-        mCurrentTime = getScrubberTime(mScrubberLeft, mScrubber.getWidth() / 2);
-        mTrimStartTime = getScrubberTime(mTrimStartScrubberLeft, trimStartScrubberTipOffset());
-        mTrimEndTime = getScrubberTime(mTrimEndScrubberLeft, trimEndScrubberTipOffset());
-    }
-
-    @Override
-    public boolean onTouchEvent(MotionEvent event) {
-        if (mShowScrubber) {
-            int x = (int) event.getX();
-            int y = (int) event.getY();
-
-            switch (event.getAction()) {
-                case MotionEvent.ACTION_DOWN:
-                    mPressedThumb = whichScrubber(x, y);
-                    switch (mPressedThumb) {
-                        case SCRUBBER_NONE:
-                            break;
-                        case SCRUBBER_CURRENT:
-                            mScrubbing = true;
-                            mScrubberCorrection = x - mScrubberLeft;
-                            break;
-                        case SCRUBBER_START:
-                            mScrubbing = true;
-                            mScrubberCorrection = x - mTrimStartScrubberLeft;
-                            break;
-                        case SCRUBBER_END:
-                            mScrubbing = true;
-                            mScrubberCorrection = x - mTrimEndScrubberLeft;
-                            break;
-                    }
-                    if (mScrubbing == true) {
-                        mListener.onScrubbingStart();
-                        return true;
-                    }
-                    break;
-                case MotionEvent.ACTION_MOVE:
-                    if (mScrubbing) {
-                        int seekToTime = -1;
-                        int lowerBound = mTrimStartScrubberLeft + trimStartScrubberTipOffset();
-                        int upperBound = mTrimEndScrubberLeft + trimEndScrubberTipOffset();
-                        switch (mPressedThumb) {
-                            case SCRUBBER_CURRENT:
-                                mScrubberLeft = x - mScrubberCorrection;
-                                mScrubberLeft =
-                                        clampScrubber(mScrubberLeft,
-                                                mScrubber.getWidth() / 2,
-                                                lowerBound, upperBound);
-                                seekToTime = getScrubberTime(mScrubberLeft,
-                                        mScrubber.getWidth() / 2);
-                                break;
-                            case SCRUBBER_START:
-                                mTrimStartScrubberLeft = x - mScrubberCorrection;
-                                // Limit start <= end
-                                if (mTrimStartScrubberLeft > mTrimEndScrubberLeft) {
-                                    mTrimStartScrubberLeft = mTrimEndScrubberLeft;
-                                }
-                                lowerBound = mProgressBar.left;
-                                mTrimStartScrubberLeft =
-                                        clampScrubber(mTrimStartScrubberLeft,
-                                                trimStartScrubberTipOffset(),
-                                                lowerBound, upperBound);
-                                seekToTime = getScrubberTime(mTrimStartScrubberLeft,
-                                        trimStartScrubberTipOffset());
-                                break;
-                            case SCRUBBER_END:
-                                mTrimEndScrubberLeft = x - mScrubberCorrection;
-                                upperBound = mProgressBar.right;
-                                mTrimEndScrubberLeft =
-                                        clampScrubber(mTrimEndScrubberLeft,
-                                                trimEndScrubberTipOffset(),
-                                                lowerBound, upperBound);
-                                seekToTime = getScrubberTime(mTrimEndScrubberLeft,
-                                        trimEndScrubberTipOffset());
-                                break;
-                        }
-                        updateTimeFromPos();
-                        updatePlayedBarAndScrubberFromTime();
-                        if (seekToTime != -1) {
-                            mListener.onScrubbingMove(seekToTime);
-                        }
-                        invalidate();
-                        return true;
-                    }
-                    break;
-                case MotionEvent.ACTION_CANCEL:
-                case MotionEvent.ACTION_UP:
-                    if (mScrubbing) {
-                        int seekToTime = 0;
-                        switch (mPressedThumb) {
-                            case SCRUBBER_CURRENT:
-                                seekToTime = getScrubberTime(mScrubberLeft,
-                                        mScrubber.getWidth() / 2);
-                                break;
-                            case SCRUBBER_START:
-                                seekToTime = getScrubberTime(mTrimStartScrubberLeft,
-                                        trimStartScrubberTipOffset());
-                                mScrubberLeft = mTrimStartScrubberLeft +
-                                        trimStartScrubberTipOffset() - mScrubber.getWidth() / 2;
-                                break;
-                            case SCRUBBER_END:
-                                seekToTime = getScrubberTime(mTrimEndScrubberLeft,
-                                        trimEndScrubberTipOffset());
-                                mScrubberLeft = mTrimEndScrubberLeft +
-                                        trimEndScrubberTipOffset() - mScrubber.getWidth() / 2;
-                                break;
-                        }
-                        updateTimeFromPos();
-                        mListener.onScrubbingEnd(seekToTime,
-                                getScrubberTime(mTrimStartScrubberLeft,
-                                        trimStartScrubberTipOffset()),
-                                getScrubberTime(mTrimEndScrubberLeft, trimEndScrubberTipOffset()));
-                        mScrubbing = false;
-                        mPressedThumb = SCRUBBER_NONE;
-                        return true;
-                    }
-                    break;
-            }
-        }
-        return false;
-    }
-}
diff --git a/src/com/android/gallery3d/app/TrimVideo.java b/src/com/android/gallery3d/app/TrimVideo.java
deleted file mode 100644
index 1e77281..0000000
--- a/src/com/android/gallery3d/app/TrimVideo.java
+++ /dev/null
@@ -1,337 +0,0 @@
-/*
- * 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.gallery3d.app;
-
-import android.app.ActionBar;
-import android.app.Activity;
-import android.app.ProgressDialog;
-import android.content.Context;
-import android.content.Intent;
-import android.media.MediaPlayer;
-import android.net.Uri;
-import android.os.Bundle;
-import android.os.Handler;
-import android.provider.MediaStore;
-import android.view.View;
-import android.view.ViewGroup;
-import android.view.Window;
-import android.widget.TextView;
-import android.widget.Toast;
-import android.widget.VideoView;
-
-import com.android.gallery3d.R;
-import com.android.gallery3d.util.SaveVideoFileInfo;
-import com.android.gallery3d.util.SaveVideoFileUtils;
-
-import java.io.File;
-import java.io.IOException;
-
-public class TrimVideo extends Activity implements
-        MediaPlayer.OnErrorListener,
-        MediaPlayer.OnCompletionListener,
-        ControllerOverlay.Listener {
-
-    private VideoView mVideoView;
-    private TextView mSaveVideoTextView;
-    private TrimControllerOverlay mController;
-    private Context mContext;
-    private Uri mUri;
-    private final Handler mHandler = new Handler();
-    public static final String TRIM_ACTION = "com.android.camera.action.TRIM";
-
-    public ProgressDialog mProgress;
-
-    private int mTrimStartTime = 0;
-    private int mTrimEndTime = 0;
-    private int mVideoPosition = 0;
-    public static final String KEY_TRIM_START = "trim_start";
-    public static final String KEY_TRIM_END = "trim_end";
-    public static final String KEY_VIDEO_POSITION = "video_pos";
-    private boolean mHasPaused = false;
-
-    private String mSrcVideoPath = null;
-    private static final String TIME_STAMP_NAME = "'TRIM'_yyyyMMdd_HHmmss";
-    private SaveVideoFileInfo mDstFileInfo = null;
-
-    @Override
-    public void onCreate(Bundle savedInstanceState) {
-        mContext = getApplicationContext();
-        super.onCreate(savedInstanceState);
-
-        requestWindowFeature(Window.FEATURE_ACTION_BAR);
-        requestWindowFeature(Window.FEATURE_ACTION_BAR_OVERLAY);
-
-        ActionBar actionBar = getActionBar();
-        int displayOptions = ActionBar.DISPLAY_SHOW_HOME;
-        actionBar.setDisplayOptions(0, displayOptions);
-        displayOptions = ActionBar.DISPLAY_SHOW_CUSTOM;
-        actionBar.setDisplayOptions(displayOptions, displayOptions);
-        actionBar.setCustomView(R.layout.trim_menu);
-
-        mSaveVideoTextView = (TextView) findViewById(R.id.start_trim);
-        mSaveVideoTextView.setOnClickListener(new View.OnClickListener() {
-            @Override
-            public void onClick(View arg0) {
-                trimVideo();
-            }
-        });
-        mSaveVideoTextView.setEnabled(false);
-
-        Intent intent = getIntent();
-        mUri = intent.getData();
-        mSrcVideoPath = intent.getStringExtra(PhotoPage.KEY_MEDIA_ITEM_PATH);
-        setContentView(R.layout.trim_view);
-        View rootView = findViewById(R.id.trim_view_root);
-
-        mVideoView = (VideoView) rootView.findViewById(R.id.surface_view);
-
-        mController = new TrimControllerOverlay(mContext);
-        ((ViewGroup) rootView).addView(mController.getView());
-        mController.setListener(this);
-        mController.setCanReplay(true);
-
-        mVideoView.setOnErrorListener(this);
-        mVideoView.setOnCompletionListener(this);
-        mVideoView.setVideoURI(mUri);
-
-        playVideo();
-    }
-
-    @Override
-    public void onResume() {
-        super.onResume();
-        if (mHasPaused) {
-            mVideoView.seekTo(mVideoPosition);
-            mVideoView.resume();
-            mHasPaused = false;
-        }
-        mHandler.post(mProgressChecker);
-    }
-
-    @Override
-    public void onPause() {
-        mHasPaused = true;
-        mHandler.removeCallbacksAndMessages(null);
-        mVideoPosition = mVideoView.getCurrentPosition();
-        mVideoView.suspend();
-        super.onPause();
-    }
-
-    @Override
-    public void onStop() {
-        if (mProgress != null) {
-            mProgress.dismiss();
-            mProgress = null;
-        }
-        super.onStop();
-    }
-
-    @Override
-    public void onDestroy() {
-        mVideoView.stopPlayback();
-        super.onDestroy();
-    }
-
-    private final Runnable mProgressChecker = new Runnable() {
-        @Override
-        public void run() {
-            int pos = setProgress();
-            mHandler.postDelayed(mProgressChecker, 200 - (pos % 200));
-        }
-    };
-
-    @Override
-    public void onSaveInstanceState(Bundle savedInstanceState) {
-        savedInstanceState.putInt(KEY_TRIM_START, mTrimStartTime);
-        savedInstanceState.putInt(KEY_TRIM_END, mTrimEndTime);
-        savedInstanceState.putInt(KEY_VIDEO_POSITION, mVideoPosition);
-        super.onSaveInstanceState(savedInstanceState);
-    }
-
-    @Override
-    public void onRestoreInstanceState(Bundle savedInstanceState) {
-        super.onRestoreInstanceState(savedInstanceState);
-        mTrimStartTime = savedInstanceState.getInt(KEY_TRIM_START, 0);
-        mTrimEndTime = savedInstanceState.getInt(KEY_TRIM_END, 0);
-        mVideoPosition = savedInstanceState.getInt(KEY_VIDEO_POSITION, 0);
-    }
-
-    // This updates the time bar display (if necessary). It is called by
-    // mProgressChecker and also from places where the time bar needs
-    // to be updated immediately.
-    private int setProgress() {
-        mVideoPosition = mVideoView.getCurrentPosition();
-        // If the video position is smaller than the starting point of trimming,
-        // correct it.
-        if (mVideoPosition < mTrimStartTime) {
-            mVideoView.seekTo(mTrimStartTime);
-            mVideoPosition = mTrimStartTime;
-        }
-        // If the position is bigger than the end point of trimming, show the
-        // replay button and pause.
-        if (mVideoPosition >= mTrimEndTime && mTrimEndTime > 0) {
-            if (mVideoPosition > mTrimEndTime) {
-                mVideoView.seekTo(mTrimEndTime);
-                mVideoPosition = mTrimEndTime;
-            }
-            mController.showEnded();
-            mVideoView.pause();
-        }
-
-        int duration = mVideoView.getDuration();
-        if (duration > 0 && mTrimEndTime == 0) {
-            mTrimEndTime = duration;
-        }
-        mController.setTimes(mVideoPosition, duration, mTrimStartTime, mTrimEndTime);
-        return mVideoPosition;
-    }
-
-    private void playVideo() {
-        mVideoView.start();
-        mController.showPlaying();
-        setProgress();
-    }
-
-    private void pauseVideo() {
-        mVideoView.pause();
-        mController.showPaused();
-    }
-
-
-    private boolean isModified() {
-        int delta = mTrimEndTime - mTrimStartTime;
-
-        // Considering that we only trim at sync frame, we don't want to trim
-        // when the time interval is too short or too close to the origin.
-        if (delta < 100 || Math.abs(mVideoView.getDuration() - delta) < 100) {
-            return false;
-        } else {
-            return true;
-        }
-    }
-
-    private void trimVideo() {
-
-        mDstFileInfo = SaveVideoFileUtils.getDstMp4FileInfo(TIME_STAMP_NAME,
-                getContentResolver(), mUri, getString(R.string.folder_download));
-        final File mSrcFile = new File(mSrcVideoPath);
-
-        showProgressDialog();
-
-        new Thread(new Runnable() {
-            @Override
-            public void run() {
-                try {
-                    VideoUtils.startTrim(mSrcFile, mDstFileInfo.mFile,
-                            mTrimStartTime, mTrimEndTime);
-                    // Update the database for adding a new video file.
-                    SaveVideoFileUtils.insertContent(mDstFileInfo,
-                            getContentResolver(), mUri);
-                } catch (IOException e) {
-                    e.printStackTrace();
-                }
-                // After trimming is done, trigger the UI changed.
-                mHandler.post(new Runnable() {
-                    @Override
-                    public void run() {
-                        Toast.makeText(getApplicationContext(),
-                            getString(R.string.save_into, mDstFileInfo.mFolderName),
-                            Toast.LENGTH_SHORT)
-                            .show();
-                        // TODO: change trimming into a service to avoid
-                        // this progressDialog and add notification properly.
-                        if (mProgress != null) {
-                            mProgress.dismiss();
-                            mProgress = null;
-                            // Show the result only when the activity not stopped.
-                            Intent intent = new Intent(android.content.Intent.ACTION_VIEW);
-                            intent.setDataAndType(Uri.fromFile(mDstFileInfo.mFile), "video/*");
-                            intent.putExtra(MediaStore.EXTRA_FINISH_ON_COMPLETION, false);
-                            startActivity(intent);
-                            finish();
-                        }
-                    }
-                });
-            }
-        }).start();
-    }
-
-    private void showProgressDialog() {
-        // create a background thread to trim the video.
-        // and show the progress.
-        mProgress = new ProgressDialog(this);
-        mProgress.setTitle(getString(R.string.trimming));
-        mProgress.setMessage(getString(R.string.please_wait));
-        // TODO: make this cancelable.
-        mProgress.setCancelable(false);
-        mProgress.setCanceledOnTouchOutside(false);
-        mProgress.show();
-    }
-
-    @Override
-    public void onPlayPause() {
-        if (mVideoView.isPlaying()) {
-            pauseVideo();
-        } else {
-            playVideo();
-        }
-    }
-
-    @Override
-    public void onSeekStart() {
-        pauseVideo();
-    }
-
-    @Override
-    public void onSeekMove(int time) {
-        mVideoView.seekTo(time);
-    }
-
-    @Override
-    public void onSeekEnd(int time, int start, int end) {
-        mVideoView.seekTo(time);
-        mTrimStartTime = start;
-        mTrimEndTime = end;
-        setProgress();
-        // Enable save if there's modifications
-        mSaveVideoTextView.setEnabled(isModified());
-    }
-
-    @Override
-    public void onShown() {
-    }
-
-    @Override
-    public void onHidden() {
-    }
-
-    @Override
-    public void onReplay() {
-        mVideoView.seekTo(mTrimStartTime);
-        playVideo();
-    }
-
-    @Override
-    public void onCompletion(MediaPlayer mp) {
-        mController.showEnded();
-    }
-
-    @Override
-    public boolean onError(MediaPlayer mp, int what, int extra) {
-        return false;
-    }
-}
diff --git a/src/com/android/gallery3d/app/VideoUtils.java b/src/com/android/gallery3d/app/VideoUtils.java
deleted file mode 100644
index a3c3ef2..0000000
--- a/src/com/android/gallery3d/app/VideoUtils.java
+++ /dev/null
@@ -1,328 +0,0 @@
-/*
- * 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.
- */
-
-// Modified example based on mp4parser google code open source project.
-// http://code.google.com/p/mp4parser/source/browse/trunk/examples/src/main/java/com/googlecode/mp4parser/ShortenExample.java
-
-package com.android.gallery3d.app;
-
-import android.media.MediaCodec.BufferInfo;
-import android.media.MediaExtractor;
-import android.media.MediaFormat;
-import android.media.MediaMetadataRetriever;
-import android.media.MediaMuxer;
-import android.util.Log;
-
-import com.android.gallery3d.common.ApiHelper;
-import com.android.gallery3d.util.SaveVideoFileInfo;
-import com.coremedia.iso.IsoFile;
-import com.coremedia.iso.boxes.TimeToSampleBox;
-import com.googlecode.mp4parser.authoring.Movie;
-import com.googlecode.mp4parser.authoring.Track;
-import com.googlecode.mp4parser.authoring.builder.DefaultMp4Builder;
-import com.googlecode.mp4parser.authoring.container.mp4.MovieCreator;
-import com.googlecode.mp4parser.authoring.tracks.CroppedTrack;
-
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.RandomAccessFile;
-import java.nio.ByteBuffer;
-import java.nio.channels.FileChannel;
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.LinkedList;
-import java.util.List;
-
-public class VideoUtils {
-    private static final String LOGTAG = "VideoUtils";
-    private static final int DEFAULT_BUFFER_SIZE = 1 * 1024 * 1024;
-
-    /**
-     * Remove the sound track.
-     */
-    public static void startMute(String filePath, SaveVideoFileInfo dstFileInfo)
-            throws IOException {
-        if (ApiHelper.HAS_MEDIA_MUXER) {
-            genVideoUsingMuxer(filePath, dstFileInfo.mFile.getPath(), -1, -1,
-                    false, true);
-        } else {
-            startMuteUsingMp4Parser(filePath, dstFileInfo);
-        }
-    }
-
-    /**
-     * Shortens/Crops tracks
-     */
-    public static void startTrim(File src, File dst, int startMs, int endMs)
-            throws IOException {
-        if (ApiHelper.HAS_MEDIA_MUXER) {
-            genVideoUsingMuxer(src.getPath(), dst.getPath(), startMs, endMs,
-                    true, true);
-        } else {
-            trimUsingMp4Parser(src, dst, startMs, endMs);
-        }
-    }
-
-    private static void startMuteUsingMp4Parser(String filePath,
-            SaveVideoFileInfo dstFileInfo) throws FileNotFoundException, IOException {
-        File dst = dstFileInfo.mFile;
-        File src = new File(filePath);
-        RandomAccessFile randomAccessFile = new RandomAccessFile(src, "r");
-        Movie movie = MovieCreator.build(randomAccessFile.getChannel());
-
-        // remove all tracks we will create new tracks from the old
-        List<Track> tracks = movie.getTracks();
-        movie.setTracks(new LinkedList<Track>());
-
-        for (Track track : tracks) {
-            if (track.getHandler().equals("vide")) {
-                movie.addTrack(track);
-            }
-        }
-        writeMovieIntoFile(dst, movie);
-        randomAccessFile.close();
-    }
-
-    private static void writeMovieIntoFile(File dst, Movie movie)
-            throws IOException {
-        if (!dst.exists()) {
-            dst.createNewFile();
-        }
-
-        IsoFile out = new DefaultMp4Builder().build(movie);
-        FileOutputStream fos = new FileOutputStream(dst);
-        FileChannel fc = fos.getChannel();
-        out.getBox(fc); // This one build up the memory.
-
-        fc.close();
-        fos.close();
-    }
-
-    /**
-     * @param srcPath the path of source video file.
-     * @param dstPath the path of destination video file.
-     * @param startMs starting time in milliseconds for trimming. Set to
-     *            negative if starting from beginning.
-     * @param endMs end time for trimming in milliseconds. Set to negative if
-     *            no trimming at the end.
-     * @param useAudio true if keep the audio track from the source.
-     * @param useVideo true if keep the video track from the source.
-     * @throws IOException
-     */
-    private static void genVideoUsingMuxer(String srcPath, String dstPath,
-            int startMs, int endMs, boolean useAudio, boolean useVideo)
-            throws IOException {
-        // Set up MediaExtractor to read from the source.
-        MediaExtractor extractor = new MediaExtractor();
-        extractor.setDataSource(srcPath);
-
-        int trackCount = extractor.getTrackCount();
-
-        // Set up MediaMuxer for the destination.
-        MediaMuxer muxer;
-        muxer = new MediaMuxer(dstPath, MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4);
-
-        // Set up the tracks and retrieve the max buffer size for selected
-        // tracks.
-        HashMap<Integer, Integer> indexMap = new HashMap<Integer,
-                Integer>(trackCount);
-        int bufferSize = -1;
-        for (int i = 0; i < trackCount; i++) {
-            MediaFormat format = extractor.getTrackFormat(i);
-            String mime = format.getString(MediaFormat.KEY_MIME);
-
-            boolean selectCurrentTrack = false;
-
-            if (mime.startsWith("audio/") && useAudio) {
-                selectCurrentTrack = true;
-            } else if (mime.startsWith("video/") && useVideo) {
-                selectCurrentTrack = true;
-            }
-
-            if (selectCurrentTrack) {
-                extractor.selectTrack(i);
-                int dstIndex = muxer.addTrack(format);
-                indexMap.put(i, dstIndex);
-                if (format.containsKey(MediaFormat.KEY_MAX_INPUT_SIZE)) {
-                    int newSize = format.getInteger(MediaFormat.KEY_MAX_INPUT_SIZE);
-                    bufferSize = newSize > bufferSize ? newSize : bufferSize;
-                }
-            }
-        }
-
-        if (bufferSize < 0) {
-            bufferSize = DEFAULT_BUFFER_SIZE;
-        }
-
-        // Set up the orientation and starting time for extractor.
-        MediaMetadataRetriever retrieverSrc = new MediaMetadataRetriever();
-        retrieverSrc.setDataSource(srcPath);
-        String degreesString = retrieverSrc.extractMetadata(
-                MediaMetadataRetriever.METADATA_KEY_VIDEO_ROTATION);
-        if (degreesString != null) {
-            int degrees = Integer.parseInt(degreesString);
-            if (degrees >= 0) {
-                muxer.setOrientationHint(degrees);
-            }
-        }
-
-        if (startMs > 0) {
-            extractor.seekTo(startMs * 1000, MediaExtractor.SEEK_TO_CLOSEST_SYNC);
-        }
-
-        // Copy the samples from MediaExtractor to MediaMuxer. We will loop
-        // for copying each sample and stop when we get to the end of the source
-        // file or exceed the end time of the trimming.
-        int offset = 0;
-        int trackIndex = -1;
-        ByteBuffer dstBuf = ByteBuffer.allocate(bufferSize);
-        BufferInfo bufferInfo = new BufferInfo();
-
-        muxer.start();
-        while (true) {
-            bufferInfo.offset = offset;
-            bufferInfo.size = extractor.readSampleData(dstBuf, offset);
-            if (bufferInfo.size < 0) {
-                Log.d(LOGTAG, "Saw input EOS.");
-                bufferInfo.size = 0;
-                break;
-            } else {
-                bufferInfo.presentationTimeUs = extractor.getSampleTime();
-                if (endMs > 0 && bufferInfo.presentationTimeUs > (endMs * 1000)) {
-                    Log.d(LOGTAG, "The current sample is over the trim end time.");
-                    break;
-                } else {
-                    bufferInfo.flags = extractor.getSampleFlags();
-                    trackIndex = extractor.getSampleTrackIndex();
-
-                    muxer.writeSampleData(indexMap.get(trackIndex), dstBuf,
-                            bufferInfo);
-                    extractor.advance();
-                }
-            }
-        }
-
-        muxer.stop();
-        muxer.release();
-        return;
-    }
-
-    private static void trimUsingMp4Parser(File src, File dst, int startMs, int endMs)
-            throws FileNotFoundException, IOException {
-        RandomAccessFile randomAccessFile = new RandomAccessFile(src, "r");
-        Movie movie = MovieCreator.build(randomAccessFile.getChannel());
-
-        // remove all tracks we will create new tracks from the old
-        List<Track> tracks = movie.getTracks();
-        movie.setTracks(new LinkedList<Track>());
-
-        double startTime = startMs / 1000;
-        double endTime = endMs / 1000;
-
-        boolean timeCorrected = false;
-
-        // Here we try to find a track that has sync samples. Since we can only
-        // start decoding at such a sample we SHOULD make sure that the start of
-        // the new fragment is exactly such a frame.
-        for (Track track : tracks) {
-            if (track.getSyncSamples() != null && track.getSyncSamples().length > 0) {
-                if (timeCorrected) {
-                    // This exception here could be a false positive in case we
-                    // have multiple tracks with sync samples at exactly the
-                    // same positions. E.g. a single movie containing multiple
-                    // qualities of the same video (Microsoft Smooth Streaming
-                    // file)
-                    throw new RuntimeException(
-                            "The startTime has already been corrected by" +
-                            " another track with SyncSample. Not Supported.");
-                }
-                startTime = correctTimeToSyncSample(track, startTime, false);
-                endTime = correctTimeToSyncSample(track, endTime, true);
-                timeCorrected = true;
-            }
-        }
-
-        for (Track track : tracks) {
-            long currentSample = 0;
-            double currentTime = 0;
-            long startSample = -1;
-            long endSample = -1;
-
-            for (int i = 0; i < track.getDecodingTimeEntries().size(); i++) {
-                TimeToSampleBox.Entry entry = track.getDecodingTimeEntries().get(i);
-                for (int j = 0; j < entry.getCount(); j++) {
-                    // entry.getDelta() is the amount of time the current sample
-                    // covers.
-
-                    if (currentTime <= startTime) {
-                        // current sample is still before the new starttime
-                        startSample = currentSample;
-                    }
-                    if (currentTime <= endTime) {
-                        // current sample is after the new start time and still
-                        // before the new endtime
-                        endSample = currentSample;
-                    } else {
-                        // current sample is after the end of the cropped video
-                        break;
-                    }
-                    currentTime += (double) entry.getDelta()
-                            / (double) track.getTrackMetaData().getTimescale();
-                    currentSample++;
-                }
-            }
-            movie.addTrack(new CroppedTrack(track, startSample, endSample));
-        }
-        writeMovieIntoFile(dst, movie);
-        randomAccessFile.close();
-    }
-
-    private static double correctTimeToSyncSample(Track track, double cutHere,
-            boolean next) {
-        double[] timeOfSyncSamples = new double[track.getSyncSamples().length];
-        long currentSample = 0;
-        double currentTime = 0;
-        for (int i = 0; i < track.getDecodingTimeEntries().size(); i++) {
-            TimeToSampleBox.Entry entry = track.getDecodingTimeEntries().get(i);
-            for (int j = 0; j < entry.getCount(); j++) {
-                if (Arrays.binarySearch(track.getSyncSamples(), currentSample + 1) >= 0) {
-                    // samples always start with 1 but we start with zero
-                    // therefore +1
-                    timeOfSyncSamples[Arrays.binarySearch(
-                            track.getSyncSamples(), currentSample + 1)] = currentTime;
-                }
-                currentTime += (double) entry.getDelta()
-                        / (double) track.getTrackMetaData().getTimescale();
-                currentSample++;
-            }
-        }
-        double previous = 0;
-        for (double timeOfSyncSample : timeOfSyncSamples) {
-            if (timeOfSyncSample > cutHere) {
-                if (next) {
-                    return timeOfSyncSample;
-                } else {
-                    return previous;
-                }
-            }
-            previous = timeOfSyncSample;
-        }
-        return timeOfSyncSamples[timeOfSyncSamples.length - 1];
-    }
-
-}
diff --git a/src/com/android/gallery3d/app/Wallpaper.java b/src/com/android/gallery3d/app/Wallpaper.java
deleted file mode 100644
index b0a26c2..0000000
--- a/src/com/android/gallery3d/app/Wallpaper.java
+++ /dev/null
@@ -1,135 +0,0 @@
-/*
- * Copyright (C) 2007 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.gallery3d.app;
-
-import android.annotation.TargetApi;
-import android.app.Activity;
-import android.content.Intent;
-import android.graphics.Point;
-import android.net.Uri;
-import android.os.Build;
-import android.os.Bundle;
-import android.view.Display;
-
-import com.android.gallery3d.common.ApiHelper;
-import com.android.gallery3d.filtershow.crop.CropActivity;
-import com.android.gallery3d.filtershow.crop.CropExtras;
-
-/**
- * Wallpaper picker for the gallery application. This just redirects to the
- * standard pick action.
- */
-public class Wallpaper extends Activity {
-    @SuppressWarnings("unused")
-    private static final String TAG = "Wallpaper";
-
-    private static final String IMAGE_TYPE = "image/*";
-    private static final String KEY_STATE = "activity-state";
-    private static final String KEY_PICKED_ITEM = "picked-item";
-
-    private static final int STATE_INIT = 0;
-    private static final int STATE_PHOTO_PICKED = 1;
-
-    private int mState = STATE_INIT;
-    private Uri mPickedItem;
-
-    @Override
-    protected void onCreate(Bundle bundle) {
-        super.onCreate(bundle);
-        if (bundle != null) {
-            mState = bundle.getInt(KEY_STATE);
-            mPickedItem = (Uri) bundle.getParcelable(KEY_PICKED_ITEM);
-        }
-    }
-
-    @Override
-    protected void onSaveInstanceState(Bundle saveState) {
-        saveState.putInt(KEY_STATE, mState);
-        if (mPickedItem != null) {
-            saveState.putParcelable(KEY_PICKED_ITEM, mPickedItem);
-        }
-    }
-
-    @SuppressWarnings("deprecation")
-    @TargetApi(Build.VERSION_CODES.HONEYCOMB_MR2)
-    private Point getDefaultDisplaySize(Point size) {
-        Display d = getWindowManager().getDefaultDisplay();
-        if (Build.VERSION.SDK_INT >= ApiHelper.VERSION_CODES.HONEYCOMB_MR2) {
-            d.getSize(size);
-        } else {
-            size.set(d.getWidth(), d.getHeight());
-        }
-        return size;
-    }
-
-    @SuppressWarnings("fallthrough")
-    @Override
-    protected void onResume() {
-        super.onResume();
-        Intent intent = getIntent();
-        switch (mState) {
-            case STATE_INIT: {
-                mPickedItem = intent.getData();
-                if (mPickedItem == null) {
-                    Intent request = new Intent(Intent.ACTION_GET_CONTENT)
-                            .setClass(this, DialogPicker.class)
-                            .setType(IMAGE_TYPE);
-                    startActivityForResult(request, STATE_PHOTO_PICKED);
-                    return;
-                }
-                mState = STATE_PHOTO_PICKED;
-                // fall-through
-            }
-            case STATE_PHOTO_PICKED: {
-                int width = getWallpaperDesiredMinimumWidth();
-                int height = getWallpaperDesiredMinimumHeight();
-                Point size = getDefaultDisplaySize(new Point());
-                float spotlightX = (float) size.x / width;
-                float spotlightY = (float) size.y / height;
-                Intent request = new Intent(CropActivity.CROP_ACTION)
-                        .setDataAndType(mPickedItem, IMAGE_TYPE)
-                        .addFlags(Intent.FLAG_ACTIVITY_FORWARD_RESULT)
-                        .putExtra(CropExtras.KEY_OUTPUT_X, width)
-                        .putExtra(CropExtras.KEY_OUTPUT_Y, height)
-                        .putExtra(CropExtras.KEY_ASPECT_X, width)
-                        .putExtra(CropExtras.KEY_ASPECT_Y, height)
-                        .putExtra(CropExtras.KEY_SPOTLIGHT_X, spotlightX)
-                        .putExtra(CropExtras.KEY_SPOTLIGHT_Y, spotlightY)
-                        .putExtra(CropExtras.KEY_SCALE, true)
-                        .putExtra(CropExtras.KEY_SCALE_UP_IF_NEEDED, true)
-                        .putExtra(CropExtras.KEY_SET_AS_WALLPAPER, true);
-                startActivity(request);
-                finish();
-            }
-        }
-    }
-
-    @Override
-    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
-        if (resultCode != RESULT_OK) {
-            setResult(resultCode);
-            finish();
-            return;
-        }
-        mState = requestCode;
-        if (mState == STATE_PHOTO_PICKED) {
-            mPickedItem = data.getData();
-        }
-
-        // onResume() would be called next
-    }
-}
diff --git a/src/com/android/gallery3d/data/ActionImage.java b/src/com/android/gallery3d/data/ActionImage.java
deleted file mode 100644
index 58e30b1..0000000
--- a/src/com/android/gallery3d/data/ActionImage.java
+++ /dev/null
@@ -1,103 +0,0 @@
-/*
- * 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.gallery3d.data;
-
-import android.graphics.Bitmap;
-import android.graphics.BitmapFactory;
-import android.graphics.BitmapRegionDecoder;
-import android.net.Uri;
-
-import com.android.gallery3d.app.GalleryApp;
-import com.android.gallery3d.common.BitmapUtils;
-import com.android.gallery3d.common.Utils;
-import com.android.gallery3d.util.ThreadPool.Job;
-import com.android.gallery3d.util.ThreadPool.JobContext;
-
-public class ActionImage extends MediaItem {
-    @SuppressWarnings("unused")
-    private static final String TAG = "ActionImage";
-    private GalleryApp mApplication;
-    private int mResourceId;
-
-    public ActionImage(Path path, GalleryApp application, int resourceId) {
-        super(path, nextVersionNumber());
-        mApplication = Utils.checkNotNull(application);
-        mResourceId = resourceId;
-    }
-
-    @Override
-    public Job<Bitmap> requestImage(int type) {
-        return new BitmapJob(type);
-    }
-
-    @Override
-    public Job<BitmapRegionDecoder> requestLargeImage() {
-        return null;
-    }
-
-    private class BitmapJob implements Job<Bitmap> {
-        private int mType;
-
-        protected BitmapJob(int type) {
-            mType = type;
-        }
-
-        @Override
-        public Bitmap run(JobContext jc) {
-            int targetSize = MediaItem.getTargetSize(mType);
-            Bitmap bitmap = BitmapFactory.decodeResource(mApplication.getResources(),
-                    mResourceId);
-
-            if (mType == MediaItem.TYPE_MICROTHUMBNAIL) {
-                bitmap = BitmapUtils.resizeAndCropCenter(bitmap, targetSize, true);
-            } else {
-                bitmap = BitmapUtils.resizeDownBySideLength(bitmap, targetSize, true);
-            }
-            return bitmap;
-        }
-    }
-
-    @Override
-    public int getSupportedOperations() {
-        return SUPPORT_ACTION;
-    }
-
-    @Override
-    public int getMediaType() {
-        return MEDIA_TYPE_UNKNOWN;
-    }
-
-    @Override
-    public Uri getContentUri() {
-        return null;
-    }
-
-    @Override
-    public String getMimeType() {
-        return "";
-    }
-
-    @Override
-    public int getWidth() {
-        return 0;
-    }
-
-    @Override
-    public int getHeight() {
-        return 0;
-    }
-}
diff --git a/src/com/android/gallery3d/data/BucketHelper.java b/src/com/android/gallery3d/data/BucketHelper.java
deleted file mode 100644
index 3418daf..0000000
--- a/src/com/android/gallery3d/data/BucketHelper.java
+++ /dev/null
@@ -1,241 +0,0 @@
-package com.android.gallery3d.data;
-
-import android.annotation.TargetApi;
-import android.content.ContentResolver;
-import android.database.Cursor;
-import android.net.Uri;
-import android.provider.MediaStore.Files;
-import android.provider.MediaStore.Files.FileColumns;
-import android.provider.MediaStore.Images;
-import android.provider.MediaStore.Images.ImageColumns;
-import android.provider.MediaStore.Video;
-import android.util.Log;
-
-import com.android.gallery3d.common.ApiHelper;
-import com.android.gallery3d.common.Utils;
-import com.android.gallery3d.util.ThreadPool.JobContext;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Comparator;
-import java.util.HashMap;
-
-class BucketHelper {
-
-    private static final String TAG = "BucketHelper";
-    private static final String EXTERNAL_MEDIA = "external";
-
-    // BUCKET_DISPLAY_NAME is a string like "Camera" which is the directory
-    // name of where an image or video is in. BUCKET_ID is a hash of the path
-    // name of that directory (see computeBucketValues() in MediaProvider for
-    // details). MEDIA_TYPE is video, image, audio, etc.
-    //
-    // The "albums" are not explicitly recorded in the database, but each image
-    // or video has the two columns (BUCKET_ID, MEDIA_TYPE). We define an
-    // "album" to be the collection of images/videos which have the same value
-    // for the two columns.
-    //
-    // The goal of the query (used in loadSubMediaSetsFromFilesTable()) is to
-    // find all albums, that is, all unique values for (BUCKET_ID, MEDIA_TYPE).
-    // In the meantime sort them by the timestamp of the latest image/video in
-    // each of the album.
-    //
-    // The order of columns below is important: it must match to the index in
-    // MediaStore.
-    private static final String[] PROJECTION_BUCKET = {
-            ImageColumns.BUCKET_ID,
-            FileColumns.MEDIA_TYPE,
-            ImageColumns.BUCKET_DISPLAY_NAME};
-
-    // The indices should match the above projections.
-    private static final int INDEX_BUCKET_ID = 0;
-    private static final int INDEX_MEDIA_TYPE = 1;
-    private static final int INDEX_BUCKET_NAME = 2;
-
-    // We want to order the albums by reverse chronological order. We abuse the
-    // "WHERE" parameter to insert a "GROUP BY" clause into the SQL statement.
-    // The template for "WHERE" parameter is like:
-    //    SELECT ... FROM ... WHERE (%s)
-    // and we make it look like:
-    //    SELECT ... FROM ... WHERE (1) GROUP BY 1,(2)
-    // The "(1)" means true. The "1,(2)" means the first two columns specified
-    // after SELECT. Note that because there is a ")" in the template, we use
-    // "(2" to match it.
-    private static final String BUCKET_GROUP_BY = "1) GROUP BY 1,(2";
-
-    private static final String BUCKET_ORDER_BY = "MAX(datetaken) DESC";
-
-    // Before HoneyComb there is no Files table. Thus, we need to query the
-    // bucket info from the Images and Video tables and then merge them
-    // together.
-    //
-    // A bucket can exist in both tables. In this case, we need to find the
-    // latest timestamp from the two tables and sort ourselves. So we add the
-    // MAX(date_taken) to the projection and remove the media_type since we
-    // already know the media type from the table we query from.
-    private static final String[] PROJECTION_BUCKET_IN_ONE_TABLE = {
-            ImageColumns.BUCKET_ID,
-            "MAX(datetaken)",
-            ImageColumns.BUCKET_DISPLAY_NAME};
-
-    // We keep the INDEX_BUCKET_ID and INDEX_BUCKET_NAME the same as
-    // PROJECTION_BUCKET so we can reuse the values defined before.
-    private static final int INDEX_DATE_TAKEN = 1;
-
-    // When query from the Images or Video tables, we only need to group by BUCKET_ID.
-    private static final String BUCKET_GROUP_BY_IN_ONE_TABLE = "1) GROUP BY (1";
-
-    public static BucketEntry[] loadBucketEntries(
-            JobContext jc, ContentResolver resolver, int type) {
-        if (ApiHelper.HAS_MEDIA_PROVIDER_FILES_TABLE) {
-            return loadBucketEntriesFromFilesTable(jc, resolver, type);
-        } else {
-            return loadBucketEntriesFromImagesAndVideoTable(jc, resolver, type);
-        }
-    }
-
-    private static void updateBucketEntriesFromTable(JobContext jc,
-            ContentResolver resolver, Uri tableUri, HashMap<Integer, BucketEntry> buckets) {
-        Cursor cursor = resolver.query(tableUri, PROJECTION_BUCKET_IN_ONE_TABLE,
-                BUCKET_GROUP_BY_IN_ONE_TABLE, null, null);
-        if (cursor == null) {
-            Log.w(TAG, "cannot open media database: " + tableUri);
-            return;
-        }
-        try {
-            while (cursor.moveToNext()) {
-                int bucketId = cursor.getInt(INDEX_BUCKET_ID);
-                int dateTaken = cursor.getInt(INDEX_DATE_TAKEN);
-                BucketEntry entry = buckets.get(bucketId);
-                if (entry == null) {
-                    entry = new BucketEntry(bucketId, cursor.getString(INDEX_BUCKET_NAME));
-                    buckets.put(bucketId, entry);
-                    entry.dateTaken = dateTaken;
-                } else {
-                    entry.dateTaken = Math.max(entry.dateTaken, dateTaken);
-                }
-            }
-        } finally {
-            Utils.closeSilently(cursor);
-        }
-    }
-
-    private static BucketEntry[] loadBucketEntriesFromImagesAndVideoTable(
-            JobContext jc, ContentResolver resolver, int type) {
-        HashMap<Integer, BucketEntry> buckets = new HashMap<Integer, BucketEntry>(64);
-        if ((type & MediaObject.MEDIA_TYPE_IMAGE) != 0) {
-            updateBucketEntriesFromTable(
-                    jc, resolver, Images.Media.EXTERNAL_CONTENT_URI, buckets);
-        }
-        if ((type & MediaObject.MEDIA_TYPE_VIDEO) != 0) {
-            updateBucketEntriesFromTable(
-                    jc, resolver, Video.Media.EXTERNAL_CONTENT_URI, buckets);
-        }
-        BucketEntry[] entries = buckets.values().toArray(new BucketEntry[buckets.size()]);
-        Arrays.sort(entries, new Comparator<BucketEntry>() {
-            @Override
-            public int compare(BucketEntry a, BucketEntry b) {
-                // sorted by dateTaken in descending order
-                return b.dateTaken - a.dateTaken;
-            }
-        });
-        return entries;
-    }
-
-    private static BucketEntry[] loadBucketEntriesFromFilesTable(
-            JobContext jc, ContentResolver resolver, int type) {
-        Uri uri = getFilesContentUri();
-
-        Cursor cursor = resolver.query(uri,
-                PROJECTION_BUCKET, BUCKET_GROUP_BY,
-                null, BUCKET_ORDER_BY);
-        if (cursor == null) {
-            Log.w(TAG, "cannot open local database: " + uri);
-            return new BucketEntry[0];
-        }
-        ArrayList<BucketEntry> buffer = new ArrayList<BucketEntry>();
-        int typeBits = 0;
-        if ((type & MediaObject.MEDIA_TYPE_IMAGE) != 0) {
-            typeBits |= (1 << FileColumns.MEDIA_TYPE_IMAGE);
-        }
-        if ((type & MediaObject.MEDIA_TYPE_VIDEO) != 0) {
-            typeBits |= (1 << FileColumns.MEDIA_TYPE_VIDEO);
-        }
-        try {
-            while (cursor.moveToNext()) {
-                if ((typeBits & (1 << cursor.getInt(INDEX_MEDIA_TYPE))) != 0) {
-                    BucketEntry entry = new BucketEntry(
-                            cursor.getInt(INDEX_BUCKET_ID),
-                            cursor.getString(INDEX_BUCKET_NAME));
-                    if (!buffer.contains(entry)) {
-                        buffer.add(entry);
-                    }
-                }
-                if (jc.isCancelled()) return null;
-            }
-        } finally {
-            Utils.closeSilently(cursor);
-        }
-        return buffer.toArray(new BucketEntry[buffer.size()]);
-    }
-
-    private static String getBucketNameInTable(
-            ContentResolver resolver, Uri tableUri, int bucketId) {
-        String selectionArgs[] = new String[] {String.valueOf(bucketId)};
-        Uri uri = tableUri.buildUpon()
-                .appendQueryParameter("limit", "1")
-                .build();
-        Cursor cursor = resolver.query(uri, PROJECTION_BUCKET_IN_ONE_TABLE,
-                "bucket_id = ?", selectionArgs, null);
-        try {
-            if (cursor != null && cursor.moveToNext()) {
-                return cursor.getString(INDEX_BUCKET_NAME);
-            }
-        } finally {
-            Utils.closeSilently(cursor);
-        }
-        return null;
-    }
-
-    @TargetApi(ApiHelper.VERSION_CODES.HONEYCOMB)
-    private static Uri getFilesContentUri() {
-        return Files.getContentUri(EXTERNAL_MEDIA);
-    }
-
-    public static String getBucketName(ContentResolver resolver, int bucketId) {
-        if (ApiHelper.HAS_MEDIA_PROVIDER_FILES_TABLE) {
-            String result = getBucketNameInTable(resolver, getFilesContentUri(), bucketId);
-            return result == null ? "" : result;
-        } else {
-            String result = getBucketNameInTable(
-                    resolver, Images.Media.EXTERNAL_CONTENT_URI, bucketId);
-            if (result != null) return result;
-            result = getBucketNameInTable(
-                    resolver, Video.Media.EXTERNAL_CONTENT_URI, bucketId);
-            return result == null ? "" : result;
-        }
-    }
-
-    public static class BucketEntry {
-        public String bucketName;
-        public int bucketId;
-        public int dateTaken;
-
-        public BucketEntry(int id, String name) {
-            bucketId = id;
-            bucketName = Utils.ensureNotNull(name);
-        }
-
-        @Override
-        public int hashCode() {
-            return bucketId;
-        }
-
-        @Override
-        public boolean equals(Object object) {
-            if (!(object instanceof BucketEntry)) return false;
-            BucketEntry entry = (BucketEntry) object;
-            return bucketId == entry.bucketId;
-        }
-    }
-}
diff --git a/src/com/android/gallery3d/data/BytesBufferPool.java b/src/com/android/gallery3d/data/BytesBufferPool.java
deleted file mode 100644
index d2da323..0000000
--- a/src/com/android/gallery3d/data/BytesBufferPool.java
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- * 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.gallery3d.data;
-
-import com.android.gallery3d.util.ThreadPool.JobContext;
-
-import java.io.FileDescriptor;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.util.ArrayList;
-
-public class BytesBufferPool {
-
-    private static final int READ_STEP = 4096;
-
-    public static class BytesBuffer {
-        public byte[] data;
-        public int offset;
-        public int length;
-
-        private BytesBuffer(int capacity) {
-            this.data = new byte[capacity];
-        }
-
-        // an helper function to read content from FileDescriptor
-        public void readFrom(JobContext jc, FileDescriptor fd) throws IOException {
-            FileInputStream fis = new FileInputStream(fd);
-            length = 0;
-            try {
-                int capacity = data.length;
-                while (true) {
-                    int step = Math.min(READ_STEP, capacity - length);
-                    int rc = fis.read(data, length, step);
-                    if (rc < 0 || jc.isCancelled()) return;
-                    length += rc;
-
-                    if (length == capacity) {
-                        byte[] newData = new byte[data.length * 2];
-                        System.arraycopy(data, 0, newData, 0, data.length);
-                        data = newData;
-                        capacity = data.length;
-                    }
-                }
-            } finally {
-                fis.close();
-            }
-        }
-    }
-
-    private final int mPoolSize;
-    private final int mBufferSize;
-    private final ArrayList<BytesBuffer> mList;
-
-    public BytesBufferPool(int poolSize, int bufferSize) {
-        mList = new ArrayList<BytesBuffer>(poolSize);
-        mPoolSize = poolSize;
-        mBufferSize = bufferSize;
-    }
-
-    public synchronized BytesBuffer get() {
-        int n = mList.size();
-        return n > 0 ? mList.remove(n - 1) : new BytesBuffer(mBufferSize);
-    }
-
-    public synchronized void recycle(BytesBuffer buffer) {
-        if (buffer.data.length != mBufferSize) return;
-        if (mList.size() < mPoolSize) {
-            buffer.offset = 0;
-            buffer.length = 0;
-            mList.add(buffer);
-        }
-    }
-
-    public synchronized void clear() {
-        mList.clear();
-    }
-}
diff --git a/src/com/android/gallery3d/data/CameraShortcutImage.java b/src/com/android/gallery3d/data/CameraShortcutImage.java
deleted file mode 100644
index 865270b..0000000
--- a/src/com/android/gallery3d/data/CameraShortcutImage.java
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * 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.gallery3d.data;
-
-import com.android.gallery3d.R;
-import com.android.gallery3d.app.GalleryApp;
-
-public class CameraShortcutImage extends ActionImage {
-    @SuppressWarnings("unused")
-    private static final String TAG = "CameraShortcutImage";
-
-    public CameraShortcutImage(Path path, GalleryApp application) {
-        super(path, application, R.drawable.placeholder_camera);
-    }
-
-    @Override
-    public int getSupportedOperations() {
-        return super.getSupportedOperations() | SUPPORT_CAMERA_SHORTCUT;
-    }
-}
diff --git a/src/com/android/gallery3d/data/ChangeNotifier.java b/src/com/android/gallery3d/data/ChangeNotifier.java
deleted file mode 100644
index 558a864..0000000
--- a/src/com/android/gallery3d/data/ChangeNotifier.java
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Copyright (C) 2010 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.gallery3d.data;
-
-import android.net.Uri;
-
-import com.android.gallery3d.app.GalleryApp;
-
-import java.util.concurrent.atomic.AtomicBoolean;
-
-// This handles change notification for media sets.
-public class ChangeNotifier {
-
-    private MediaSet mMediaSet;
-    private AtomicBoolean mContentDirty = new AtomicBoolean(true);
-
-    public ChangeNotifier(MediaSet set, Uri uri, GalleryApp application) {
-        mMediaSet = set;
-        application.getDataManager().registerChangeNotifier(uri, this);
-    }
-
-    public ChangeNotifier(MediaSet set, Uri[] uris, GalleryApp application) {
-        mMediaSet = set;
-        for (int i = 0; i < uris.length; i++) {
-            application.getDataManager().registerChangeNotifier(uris[i], this);
-        }
-    }
-
-    // Returns the dirty flag and clear it.
-    public boolean isDirty() {
-        return mContentDirty.compareAndSet(true, false);
-    }
-
-    public void fakeChange() {
-        onChange(false);
-    }
-
-    protected void onChange(boolean selfChange) {
-        if (mContentDirty.compareAndSet(false, true)) {
-            mMediaSet.notifyContentChanged();
-        }
-    }
-}
\ No newline at end of file
diff --git a/src/com/android/gallery3d/data/ClusterAlbum.java b/src/com/android/gallery3d/data/ClusterAlbum.java
deleted file mode 100644
index 8681952..0000000
--- a/src/com/android/gallery3d/data/ClusterAlbum.java
+++ /dev/null
@@ -1,143 +0,0 @@
-/*
- * Copyright (C) 2010 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.gallery3d.data;
-
-import java.util.ArrayList;
-
-public class ClusterAlbum extends MediaSet implements ContentListener {
-    @SuppressWarnings("unused")
-    private static final String TAG = "ClusterAlbum";
-    private ArrayList<Path> mPaths = new ArrayList<Path>();
-    private String mName = "";
-    private DataManager mDataManager;
-    private MediaSet mClusterAlbumSet;
-    private MediaItem mCover;
-
-    public ClusterAlbum(Path path, DataManager dataManager,
-            MediaSet clusterAlbumSet) {
-        super(path, nextVersionNumber());
-        mDataManager = dataManager;
-        mClusterAlbumSet = clusterAlbumSet;
-        mClusterAlbumSet.addContentListener(this);
-    }
-
-    public void setCoverMediaItem(MediaItem cover) {
-        mCover = cover;
-    }
-
-    @Override
-    public MediaItem getCoverMediaItem() {
-        return mCover != null ? mCover : super.getCoverMediaItem();
-    }
-
-    void setMediaItems(ArrayList<Path> paths) {
-        mPaths = paths;
-    }
-
-    ArrayList<Path> getMediaItems() {
-        return mPaths;
-    }
-
-    public void setName(String name) {
-        mName = name;
-    }
-
-    @Override
-    public String getName() {
-        return mName;
-    }
-
-    @Override
-    public int getMediaItemCount() {
-        return mPaths.size();
-    }
-
-    @Override
-    public ArrayList<MediaItem> getMediaItem(int start, int count) {
-        return getMediaItemFromPath(mPaths, start, count, mDataManager);
-    }
-
-    public static ArrayList<MediaItem> getMediaItemFromPath(
-            ArrayList<Path> paths, int start, int count,
-            DataManager dataManager) {
-        if (start >= paths.size()) {
-            return new ArrayList<MediaItem>();
-        }
-        int end = Math.min(start + count, paths.size());
-        ArrayList<Path> subset = new ArrayList<Path>(paths.subList(start, end));
-        final MediaItem[] buf = new MediaItem[end - start];
-        ItemConsumer consumer = new ItemConsumer() {
-            @Override
-            public void consume(int index, MediaItem item) {
-                buf[index] = item;
-            }
-        };
-        dataManager.mapMediaItems(subset, consumer, 0);
-        ArrayList<MediaItem> result = new ArrayList<MediaItem>(end - start);
-        for (int i = 0; i < buf.length; i++) {
-            result.add(buf[i]);
-        }
-        return result;
-    }
-
-    @Override
-    protected int enumerateMediaItems(ItemConsumer consumer, int startIndex) {
-        mDataManager.mapMediaItems(mPaths, consumer, startIndex);
-        return mPaths.size();
-    }
-
-    @Override
-    public int getTotalMediaItemCount() {
-        return mPaths.size();
-    }
-
-    @Override
-    public long reload() {
-        if (mClusterAlbumSet.reload() > mDataVersion) {
-            mDataVersion = nextVersionNumber();
-        }
-        return mDataVersion;
-    }
-
-    @Override
-    public void onContentDirty() {
-        notifyContentChanged();
-    }
-
-    @Override
-    public int getSupportedOperations() {
-        return SUPPORT_SHARE | SUPPORT_DELETE | SUPPORT_INFO;
-    }
-
-    @Override
-    public void delete() {
-        ItemConsumer consumer = new ItemConsumer() {
-            @Override
-            public void consume(int index, MediaItem item) {
-                if ((item.getSupportedOperations() & SUPPORT_DELETE) != 0) {
-                    item.delete();
-                }
-            }
-        };
-        mDataManager.mapMediaItems(mPaths, consumer, 0);
-    }
-
-    @Override
-    public boolean isLeafAlbum() {
-        return true;
-    }
-}
diff --git a/src/com/android/gallery3d/data/ClusterAlbumSet.java b/src/com/android/gallery3d/data/ClusterAlbumSet.java
deleted file mode 100644
index cb212ba..0000000
--- a/src/com/android/gallery3d/data/ClusterAlbumSet.java
+++ /dev/null
@@ -1,159 +0,0 @@
-/*
- * Copyright (C) 2010 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.gallery3d.data;
-
-import android.content.Context;
-import android.net.Uri;
-
-import com.android.gallery3d.app.GalleryApp;
-
-import java.util.ArrayList;
-import java.util.HashSet;
-
-public class ClusterAlbumSet extends MediaSet implements ContentListener {
-    @SuppressWarnings("unused")
-    private static final String TAG = "ClusterAlbumSet";
-    private GalleryApp mApplication;
-    private MediaSet mBaseSet;
-    private int mKind;
-    private ArrayList<ClusterAlbum> mAlbums = new ArrayList<ClusterAlbum>();
-    private boolean mFirstReloadDone;
-
-    public ClusterAlbumSet(Path path, GalleryApp application,
-            MediaSet baseSet, int kind) {
-        super(path, INVALID_DATA_VERSION);
-        mApplication = application;
-        mBaseSet = baseSet;
-        mKind = kind;
-        baseSet.addContentListener(this);
-    }
-
-    @Override
-    public MediaSet getSubMediaSet(int index) {
-        return mAlbums.get(index);
-    }
-
-    @Override
-    public int getSubMediaSetCount() {
-        return mAlbums.size();
-    }
-
-    @Override
-    public String getName() {
-        return mBaseSet.getName();
-    }
-
-    @Override
-    public long reload() {
-        if (mBaseSet.reload() > mDataVersion) {
-            if (mFirstReloadDone) {
-                updateClustersContents();
-            } else {
-                updateClusters();
-                mFirstReloadDone = true;
-            }
-            mDataVersion = nextVersionNumber();
-        }
-        return mDataVersion;
-    }
-
-    @Override
-    public void onContentDirty() {
-        notifyContentChanged();
-    }
-
-    private void updateClusters() {
-        mAlbums.clear();
-        Clustering clustering;
-        Context context = mApplication.getAndroidContext();
-        switch (mKind) {
-            case ClusterSource.CLUSTER_ALBUMSET_TIME:
-                clustering = new TimeClustering(context);
-                break;
-            case ClusterSource.CLUSTER_ALBUMSET_LOCATION:
-                clustering = new LocationClustering(context);
-                break;
-            case ClusterSource.CLUSTER_ALBUMSET_TAG:
-                clustering = new TagClustering(context);
-                break;
-            case ClusterSource.CLUSTER_ALBUMSET_FACE:
-                clustering = new FaceClustering(context);
-                break;
-            default: /* CLUSTER_ALBUMSET_SIZE */
-                clustering = new SizeClustering(context);
-                break;
-        }
-
-        clustering.run(mBaseSet);
-        int n = clustering.getNumberOfClusters();
-        DataManager dataManager = mApplication.getDataManager();
-        for (int i = 0; i < n; i++) {
-            Path childPath;
-            String childName = clustering.getClusterName(i);
-            if (mKind == ClusterSource.CLUSTER_ALBUMSET_TAG) {
-                childPath = mPath.getChild(Uri.encode(childName));
-            } else if (mKind == ClusterSource.CLUSTER_ALBUMSET_SIZE) {
-                long minSize = ((SizeClustering) clustering).getMinSize(i);
-                childPath = mPath.getChild(minSize);
-            } else {
-                childPath = mPath.getChild(i);
-            }
-
-            ClusterAlbum album;
-            synchronized (DataManager.LOCK) {
-                album = (ClusterAlbum) dataManager.peekMediaObject(childPath);
-                if (album == null) {
-                    album = new ClusterAlbum(childPath, dataManager, this);
-                }
-            }
-            album.setMediaItems(clustering.getCluster(i));
-            album.setName(childName);
-            album.setCoverMediaItem(clustering.getClusterCover(i));
-            mAlbums.add(album);
-        }
-    }
-
-    private void updateClustersContents() {
-        final HashSet<Path> existing = new HashSet<Path>();
-        mBaseSet.enumerateTotalMediaItems(new MediaSet.ItemConsumer() {
-            @Override
-            public void consume(int index, MediaItem item) {
-                existing.add(item.getPath());
-            }
-        });
-
-        int n = mAlbums.size();
-
-        // The loop goes backwards because we may remove empty albums from
-        // mAlbums.
-        for (int i = n - 1; i >= 0; i--) {
-            ArrayList<Path> oldPaths = mAlbums.get(i).getMediaItems();
-            ArrayList<Path> newPaths = new ArrayList<Path>();
-            int m = oldPaths.size();
-            for (int j = 0; j < m; j++) {
-                Path p = oldPaths.get(j);
-                if (existing.contains(p)) {
-                    newPaths.add(p);
-                }
-            }
-            mAlbums.get(i).setMediaItems(newPaths);
-            if (newPaths.isEmpty()) {
-                mAlbums.remove(i);
-            }
-        }
-    }
-}
diff --git a/src/com/android/gallery3d/data/ClusterSource.java b/src/com/android/gallery3d/data/ClusterSource.java
deleted file mode 100644
index a1f22e5..0000000
--- a/src/com/android/gallery3d/data/ClusterSource.java
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * Copyright (C) 2010 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.gallery3d.data;
-
-import com.android.gallery3d.app.GalleryApp;
-
-class ClusterSource extends MediaSource {
-    static final int CLUSTER_ALBUMSET_TIME = 0;
-    static final int CLUSTER_ALBUMSET_LOCATION = 1;
-    static final int CLUSTER_ALBUMSET_TAG = 2;
-    static final int CLUSTER_ALBUMSET_SIZE = 3;
-    static final int CLUSTER_ALBUMSET_FACE = 4;
-
-    static final int CLUSTER_ALBUM_TIME = 0x100;
-    static final int CLUSTER_ALBUM_LOCATION = 0x101;
-    static final int CLUSTER_ALBUM_TAG = 0x102;
-    static final int CLUSTER_ALBUM_SIZE = 0x103;
-    static final int CLUSTER_ALBUM_FACE = 0x104;
-
-    GalleryApp mApplication;
-    PathMatcher mMatcher;
-
-    public ClusterSource(GalleryApp application) {
-        super("cluster");
-        mApplication = application;
-        mMatcher = new PathMatcher();
-        mMatcher.add("/cluster/*/time", CLUSTER_ALBUMSET_TIME);
-        mMatcher.add("/cluster/*/location", CLUSTER_ALBUMSET_LOCATION);
-        mMatcher.add("/cluster/*/tag", CLUSTER_ALBUMSET_TAG);
-        mMatcher.add("/cluster/*/size", CLUSTER_ALBUMSET_SIZE);
-        mMatcher.add("/cluster/*/face", CLUSTER_ALBUMSET_FACE);
-
-        mMatcher.add("/cluster/*/time/*", CLUSTER_ALBUM_TIME);
-        mMatcher.add("/cluster/*/location/*", CLUSTER_ALBUM_LOCATION);
-        mMatcher.add("/cluster/*/tag/*", CLUSTER_ALBUM_TAG);
-        mMatcher.add("/cluster/*/size/*", CLUSTER_ALBUM_SIZE);
-        mMatcher.add("/cluster/*/face/*", CLUSTER_ALBUM_FACE);
-    }
-
-    // The names we accept are:
-    // /cluster/{set}/time      /cluster/{set}/time/k
-    // /cluster/{set}/location  /cluster/{set}/location/k
-    // /cluster/{set}/tag       /cluster/{set}/tag/encoded_tag
-    // /cluster/{set}/size      /cluster/{set}/size/min_size
-    @Override
-    public MediaObject createMediaObject(Path path) {
-        int matchType = mMatcher.match(path);
-        String setsName = mMatcher.getVar(0);
-        DataManager dataManager = mApplication.getDataManager();
-        MediaSet[] sets = dataManager.getMediaSetsFromString(setsName);
-        switch (matchType) {
-            case CLUSTER_ALBUMSET_TIME:
-            case CLUSTER_ALBUMSET_LOCATION:
-            case CLUSTER_ALBUMSET_TAG:
-            case CLUSTER_ALBUMSET_SIZE:
-            case CLUSTER_ALBUMSET_FACE:
-                return new ClusterAlbumSet(path, mApplication, sets[0], matchType);
-            case CLUSTER_ALBUM_TIME:
-            case CLUSTER_ALBUM_LOCATION:
-            case CLUSTER_ALBUM_TAG:
-            case CLUSTER_ALBUM_SIZE:
-            case CLUSTER_ALBUM_FACE: {
-                MediaSet parent = dataManager.getMediaSet(path.getParent());
-                // The actual content in the ClusterAlbum will be filled later
-                // when the reload() method in the parent is run.
-                return new ClusterAlbum(path, dataManager, parent);
-            }
-            default:
-                throw new RuntimeException("bad path: " + path);
-        }
-    }
-}
diff --git a/src/com/android/gallery3d/data/Clustering.java b/src/com/android/gallery3d/data/Clustering.java
deleted file mode 100644
index 4072bf5..0000000
--- a/src/com/android/gallery3d/data/Clustering.java
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright (C) 2010 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.gallery3d.data;
-
-import java.util.ArrayList;
-
-public abstract class Clustering {
-    public abstract void run(MediaSet baseSet);
-    public abstract int getNumberOfClusters();
-    public abstract ArrayList<Path> getCluster(int index);
-    public abstract String getClusterName(int index);
-    public MediaItem getClusterCover(int index) {
-        return null;
-    }
-}
diff --git a/src/com/android/gallery3d/data/ComboAlbum.java b/src/com/android/gallery3d/data/ComboAlbum.java
deleted file mode 100644
index cadd9f8..0000000
--- a/src/com/android/gallery3d/data/ComboAlbum.java
+++ /dev/null
@@ -1,103 +0,0 @@
-/*
- * Copyright (C) 2011 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.gallery3d.data;
-
-import com.android.gallery3d.util.Future;
-
-import java.util.ArrayList;
-
-// ComboAlbum combines multiple media sets into one. It lists all media items
-// from the input albums.
-// This only handles SubMediaSets, not MediaItems. (That's all we need now)
-public class ComboAlbum extends MediaSet implements ContentListener {
-    @SuppressWarnings("unused")
-    private static final String TAG = "ComboAlbum";
-    private final MediaSet[] mSets;
-    private String mName;
-
-    public ComboAlbum(Path path, MediaSet[] mediaSets, String name) {
-        super(path, nextVersionNumber());
-        mSets = mediaSets;
-        for (MediaSet set : mSets) {
-            set.addContentListener(this);
-        }
-        mName = name;
-    }
-
-    @Override
-    public ArrayList<MediaItem> getMediaItem(int start, int count) {
-        ArrayList<MediaItem> items = new ArrayList<MediaItem>();
-        for (MediaSet set : mSets) {
-            int size = set.getMediaItemCount();
-            if (count < 1) break;
-            if (start < size) {
-                int fetchCount = (start + count <= size) ? count : size - start;
-                ArrayList<MediaItem> fetchItems = set.getMediaItem(start, fetchCount);
-                items.addAll(fetchItems);
-                count -= fetchItems.size();
-                start = 0;
-            } else {
-                start -= size;
-            }
-        }
-        return items;
-    }
-
-    @Override
-    public int getMediaItemCount() {
-        int count = 0;
-        for (MediaSet set : mSets) {
-            count += set.getMediaItemCount();
-        }
-        return count;
-    }
-
-    @Override
-    public boolean isLeafAlbum() {
-        return true;
-    }
-
-    @Override
-    public String getName() {
-        return mName;
-    }
-
-    public void useNameOfChild(int i) {
-        if (i < mSets.length) mName = mSets[i].getName();
-    }
-
-    @Override
-    public long reload() {
-        boolean changed = false;
-        for (int i = 0, n = mSets.length; i < n; ++i) {
-            long version = mSets[i].reload();
-            if (version > mDataVersion) changed = true;
-        }
-        if (changed) mDataVersion = nextVersionNumber();
-        return mDataVersion;
-    }
-
-    @Override
-    public void onContentDirty() {
-        notifyContentChanged();
-    }
-
-    @Override
-    public Future<Integer> requestSync(SyncListener listener) {
-        return requestSyncOnMultipleSets(mSets, listener);
-    }
-}
diff --git a/src/com/android/gallery3d/data/ComboAlbumSet.java b/src/com/android/gallery3d/data/ComboAlbumSet.java
deleted file mode 100644
index 3f36745..0000000
--- a/src/com/android/gallery3d/data/ComboAlbumSet.java
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- * Copyright (C) 2010 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.gallery3d.data;
-
-import com.android.gallery3d.R;
-import com.android.gallery3d.app.GalleryApp;
-import com.android.gallery3d.util.Future;
-
-// ComboAlbumSet combines multiple media sets into one. It lists all sub
-// media sets from the input album sets.
-// This only handles SubMediaSets, not MediaItems. (That's all we need now)
-public class ComboAlbumSet extends MediaSet implements ContentListener {
-    @SuppressWarnings("unused")
-    private static final String TAG = "ComboAlbumSet";
-    private final MediaSet[] mSets;
-    private final String mName;
-
-    public ComboAlbumSet(Path path, GalleryApp application, MediaSet[] mediaSets) {
-        super(path, nextVersionNumber());
-        mSets = mediaSets;
-        for (MediaSet set : mSets) {
-            set.addContentListener(this);
-        }
-        mName = application.getResources().getString(
-                R.string.set_label_all_albums);
-    }
-
-    @Override
-    public MediaSet getSubMediaSet(int index) {
-        for (MediaSet set : mSets) {
-            int size = set.getSubMediaSetCount();
-            if (index < size) {
-                return set.getSubMediaSet(index);
-            }
-            index -= size;
-        }
-        return null;
-    }
-
-    @Override
-    public int getSubMediaSetCount() {
-        int count = 0;
-        for (MediaSet set : mSets) {
-            count += set.getSubMediaSetCount();
-        }
-        return count;
-    }
-
-    @Override
-    public String getName() {
-        return mName;
-    }
-
-    @Override
-    public boolean isLoading() {
-        for (int i = 0, n = mSets.length; i < n; ++i) {
-            if (mSets[i].isLoading()) return true;
-        }
-        return false;
-    }
-
-    @Override
-    public long reload() {
-        boolean changed = false;
-        for (int i = 0, n = mSets.length; i < n; ++i) {
-            long version = mSets[i].reload();
-            if (version > mDataVersion) changed = true;
-        }
-        if (changed) mDataVersion = nextVersionNumber();
-        return mDataVersion;
-    }
-
-    @Override
-    public void onContentDirty() {
-        notifyContentChanged();
-    }
-
-    @Override
-    public Future<Integer> requestSync(SyncListener listener) {
-        return requestSyncOnMultipleSets(mSets, listener);
-    }
-}
diff --git a/src/com/android/gallery3d/data/ComboSource.java b/src/com/android/gallery3d/data/ComboSource.java
deleted file mode 100644
index 867d47e..0000000
--- a/src/com/android/gallery3d/data/ComboSource.java
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Copyright (C) 2010 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.gallery3d.data;
-
-import com.android.gallery3d.app.GalleryApp;
-
-class ComboSource extends MediaSource {
-    private static final int COMBO_ALBUMSET = 0;
-    private static final int COMBO_ALBUM = 1;
-    private GalleryApp mApplication;
-    private PathMatcher mMatcher;
-
-    public ComboSource(GalleryApp application) {
-        super("combo");
-        mApplication = application;
-        mMatcher = new PathMatcher();
-        mMatcher.add("/combo/*", COMBO_ALBUMSET);
-        mMatcher.add("/combo/*/*", COMBO_ALBUM);
-    }
-
-    // The only path we accept is "/combo/{set1, set2, ...} and /combo/item/{set1, set2, ...}"
-    @Override
-    public MediaObject createMediaObject(Path path) {
-        String[] segments = path.split();
-        if (segments.length < 2) {
-            throw new RuntimeException("bad path: " + path);
-        }
-
-        DataManager dataManager = mApplication.getDataManager();
-        switch (mMatcher.match(path)) {
-            case COMBO_ALBUMSET:
-                return new ComboAlbumSet(path, mApplication,
-                        dataManager.getMediaSetsFromString(segments[1]));
-
-            case COMBO_ALBUM:
-                return new ComboAlbum(path,
-                        dataManager.getMediaSetsFromString(segments[2]), segments[1]);
-        }
-        return null;
-    }
-}
diff --git a/src/com/android/gallery3d/data/ContentListener.java b/src/com/android/gallery3d/data/ContentListener.java
deleted file mode 100644
index 5e29526..0000000
--- a/src/com/android/gallery3d/data/ContentListener.java
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- * Copyright (C) 2010 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.gallery3d.data;
-
-public interface ContentListener {
-    public void onContentDirty();
-}
\ No newline at end of file
diff --git a/src/com/android/gallery3d/data/DataManager.java b/src/com/android/gallery3d/data/DataManager.java
deleted file mode 100644
index 38865e9..0000000
--- a/src/com/android/gallery3d/data/DataManager.java
+++ /dev/null
@@ -1,371 +0,0 @@
-/*
- * Copyright (C) 2010 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.gallery3d.data;
-
-import android.content.Context;
-import android.database.ContentObserver;
-import android.net.Uri;
-import android.os.Handler;
-
-import com.android.gallery3d.app.GalleryApp;
-import com.android.gallery3d.app.StitchingChangeListener;
-import com.android.gallery3d.common.Utils;
-import com.android.gallery3d.data.MediaObject.PanoramaSupportCallback;
-import com.android.gallery3d.data.MediaSet.ItemConsumer;
-import com.android.gallery3d.data.MediaSource.PathId;
-import com.android.gallery3d.picasasource.PicasaSource;
-
-import java.util.ArrayList;
-import java.util.Comparator;
-import java.util.HashMap;
-import java.util.LinkedHashMap;
-import java.util.Map.Entry;
-import java.util.WeakHashMap;
-
-// DataManager manages all media sets and media items in the system.
-//
-// Each MediaSet and MediaItem has a unique 64 bits id. The most significant
-// 32 bits represents its parent, and the least significant 32 bits represents
-// the self id. For MediaSet the self id is is globally unique, but for
-// MediaItem it's unique only relative to its parent.
-//
-// To make sure the id is the same when the MediaSet is re-created, a child key
-// is provided to obtainSetId() to make sure the same self id will be used as
-// when the parent and key are the same. A sequence of child keys is called a
-// path. And it's used to identify a specific media set even if the process is
-// killed and re-created, so child keys should be stable identifiers.
-
-public class DataManager implements StitchingChangeListener {
-    public static final int INCLUDE_IMAGE = 1;
-    public static final int INCLUDE_VIDEO = 2;
-    public static final int INCLUDE_ALL = INCLUDE_IMAGE | INCLUDE_VIDEO;
-    public static final int INCLUDE_LOCAL_ONLY = 4;
-    public static final int INCLUDE_LOCAL_IMAGE_ONLY =
-            INCLUDE_LOCAL_ONLY | INCLUDE_IMAGE;
-    public static final int INCLUDE_LOCAL_VIDEO_ONLY =
-            INCLUDE_LOCAL_ONLY | INCLUDE_VIDEO;
-    public static final int INCLUDE_LOCAL_ALL_ONLY =
-            INCLUDE_LOCAL_ONLY | INCLUDE_IMAGE | INCLUDE_VIDEO;
-
-    // Any one who would like to access data should require this lock
-    // to prevent concurrency issue.
-    public static final Object LOCK = new Object();
-
-    public static DataManager from(Context context) {
-        GalleryApp app = (GalleryApp) context.getApplicationContext();
-        return app.getDataManager();
-    }
-
-    private static final String TAG = "DataManager";
-
-    // This is the path for the media set seen by the user at top level.
-    private static final String TOP_SET_PATH = "/combo/{/local/all,/picasa/all}";
-
-    private static final String TOP_IMAGE_SET_PATH = "/combo/{/local/image,/picasa/image}";
-
-    private static final String TOP_VIDEO_SET_PATH =
-            "/combo/{/local/video,/picasa/video}";
-
-    private static final String TOP_LOCAL_SET_PATH = "/local/all";
-
-    private static final String TOP_LOCAL_IMAGE_SET_PATH = "/local/image";
-
-    private static final String TOP_LOCAL_VIDEO_SET_PATH = "/local/video";
-
-    public static final Comparator<MediaItem> sDateTakenComparator =
-            new DateTakenComparator();
-
-    private static class DateTakenComparator implements Comparator<MediaItem> {
-        @Override
-        public int compare(MediaItem item1, MediaItem item2) {
-            return -Utils.compare(item1.getDateInMs(), item2.getDateInMs());
-        }
-    }
-
-    private final Handler mDefaultMainHandler;
-
-    private GalleryApp mApplication;
-    private int mActiveCount = 0;
-
-    private HashMap<Uri, NotifyBroker> mNotifierMap =
-            new HashMap<Uri, NotifyBroker>();
-
-
-    private HashMap<String, MediaSource> mSourceMap =
-            new LinkedHashMap<String, MediaSource>();
-
-    public DataManager(GalleryApp application) {
-        mApplication = application;
-        mDefaultMainHandler = new Handler(application.getMainLooper());
-    }
-
-    public synchronized void initializeSourceMap() {
-        if (!mSourceMap.isEmpty()) return;
-
-        // the order matters, the UriSource must come last
-        addSource(new LocalSource(mApplication));
-        addSource(new PicasaSource(mApplication));
-        addSource(new ComboSource(mApplication));
-        addSource(new ClusterSource(mApplication));
-        addSource(new FilterSource(mApplication));
-        addSource(new SecureSource(mApplication));
-        addSource(new UriSource(mApplication));
-        addSource(new SnailSource(mApplication));
-
-        if (mActiveCount > 0) {
-            for (MediaSource source : mSourceMap.values()) {
-                source.resume();
-            }
-        }
-    }
-
-    public String getTopSetPath(int typeBits) {
-
-        switch (typeBits) {
-            case INCLUDE_IMAGE: return TOP_IMAGE_SET_PATH;
-            case INCLUDE_VIDEO: return TOP_VIDEO_SET_PATH;
-            case INCLUDE_ALL: return TOP_SET_PATH;
-            case INCLUDE_LOCAL_IMAGE_ONLY: return TOP_LOCAL_IMAGE_SET_PATH;
-            case INCLUDE_LOCAL_VIDEO_ONLY: return TOP_LOCAL_VIDEO_SET_PATH;
-            case INCLUDE_LOCAL_ALL_ONLY: return TOP_LOCAL_SET_PATH;
-            default: throw new IllegalArgumentException();
-        }
-    }
-
-    // open for debug
-    void addSource(MediaSource source) {
-        if (source == null) return;
-        mSourceMap.put(source.getPrefix(), source);
-    }
-
-    // A common usage of this method is:
-    // synchronized (DataManager.LOCK) {
-    //     MediaObject object = peekMediaObject(path);
-    //     if (object == null) {
-    //         object = createMediaObject(...);
-    //     }
-    // }
-    public MediaObject peekMediaObject(Path path) {
-        return path.getObject();
-    }
-
-    public MediaObject getMediaObject(Path path) {
-        synchronized (LOCK) {
-            MediaObject obj = path.getObject();
-            if (obj != null) return obj;
-
-            MediaSource source = mSourceMap.get(path.getPrefix());
-            if (source == null) {
-                Log.w(TAG, "cannot find media source for path: " + path);
-                return null;
-            }
-
-            try {
-                MediaObject object = source.createMediaObject(path);
-                if (object == null) {
-                    Log.w(TAG, "cannot create media object: " + path);
-                }
-                return object;
-            } catch (Throwable t) {
-                Log.w(TAG, "exception in creating media object: " + path, t);
-                return null;
-            }
-        }
-    }
-
-    public MediaObject getMediaObject(String s) {
-        return getMediaObject(Path.fromString(s));
-    }
-
-    public MediaSet getMediaSet(Path path) {
-        return (MediaSet) getMediaObject(path);
-    }
-
-    public MediaSet getMediaSet(String s) {
-        return (MediaSet) getMediaObject(s);
-    }
-
-    public MediaSet[] getMediaSetsFromString(String segment) {
-        String[] seq = Path.splitSequence(segment);
-        int n = seq.length;
-        MediaSet[] sets = new MediaSet[n];
-        for (int i = 0; i < n; i++) {
-            sets[i] = getMediaSet(seq[i]);
-        }
-        return sets;
-    }
-
-    // Maps a list of Paths to MediaItems, and invoke consumer.consume()
-    // for each MediaItem (may not be in the same order as the input list).
-    // An index number is also passed to consumer.consume() to identify
-    // the original position in the input list of the corresponding Path (plus
-    // startIndex).
-    public void mapMediaItems(ArrayList<Path> list, ItemConsumer consumer,
-            int startIndex) {
-        HashMap<String, ArrayList<PathId>> map =
-                new HashMap<String, ArrayList<PathId>>();
-
-        // Group the path by the prefix.
-        int n = list.size();
-        for (int i = 0; i < n; i++) {
-            Path path = list.get(i);
-            String prefix = path.getPrefix();
-            ArrayList<PathId> group = map.get(prefix);
-            if (group == null) {
-                group = new ArrayList<PathId>();
-                map.put(prefix, group);
-            }
-            group.add(new PathId(path, i + startIndex));
-        }
-
-        // For each group, ask the corresponding media source to map it.
-        for (Entry<String, ArrayList<PathId>> entry : map.entrySet()) {
-            String prefix = entry.getKey();
-            MediaSource source = mSourceMap.get(prefix);
-            source.mapMediaItems(entry.getValue(), consumer);
-        }
-    }
-
-    // The following methods forward the request to the proper object.
-    public int getSupportedOperations(Path path) {
-        return getMediaObject(path).getSupportedOperations();
-    }
-
-    public void getPanoramaSupport(Path path, PanoramaSupportCallback callback) {
-        getMediaObject(path).getPanoramaSupport(callback);
-    }
-
-    public void delete(Path path) {
-        getMediaObject(path).delete();
-    }
-
-    public void rotate(Path path, int degrees) {
-        getMediaObject(path).rotate(degrees);
-    }
-
-    public Uri getContentUri(Path path) {
-        return getMediaObject(path).getContentUri();
-    }
-
-    public int getMediaType(Path path) {
-        return getMediaObject(path).getMediaType();
-    }
-
-    public Path findPathByUri(Uri uri, String type) {
-        if (uri == null) return null;
-        for (MediaSource source : mSourceMap.values()) {
-            Path path = source.findPathByUri(uri, type);
-            if (path != null) return path;
-        }
-        return null;
-    }
-
-    public Path getDefaultSetOf(Path item) {
-        MediaSource source = mSourceMap.get(item.getPrefix());
-        return source == null ? null : source.getDefaultSetOf(item);
-    }
-
-    // Returns number of bytes used by cached pictures currently downloaded.
-    public long getTotalUsedCacheSize() {
-        long sum = 0;
-        for (MediaSource source : mSourceMap.values()) {
-            sum += source.getTotalUsedCacheSize();
-        }
-        return sum;
-    }
-
-    // Returns number of bytes used by cached pictures if all pending
-    // downloads and removals are completed.
-    public long getTotalTargetCacheSize() {
-        long sum = 0;
-        for (MediaSource source : mSourceMap.values()) {
-            sum += source.getTotalTargetCacheSize();
-        }
-        return sum;
-    }
-
-    public void registerChangeNotifier(Uri uri, ChangeNotifier notifier) {
-        NotifyBroker broker = null;
-        synchronized (mNotifierMap) {
-            broker = mNotifierMap.get(uri);
-            if (broker == null) {
-                broker = new NotifyBroker(mDefaultMainHandler);
-                mApplication.getContentResolver()
-                        .registerContentObserver(uri, true, broker);
-                mNotifierMap.put(uri, broker);
-            }
-        }
-        broker.registerNotifier(notifier);
-    }
-
-    public void resume() {
-        if (++mActiveCount == 1) {
-            for (MediaSource source : mSourceMap.values()) {
-                source.resume();
-            }
-        }
-    }
-
-    public void pause() {
-        if (--mActiveCount == 0) {
-            for (MediaSource source : mSourceMap.values()) {
-                source.pause();
-            }
-        }
-    }
-
-    private static class NotifyBroker extends ContentObserver {
-        private WeakHashMap<ChangeNotifier, Object> mNotifiers =
-                new WeakHashMap<ChangeNotifier, Object>();
-
-        public NotifyBroker(Handler handler) {
-            super(handler);
-        }
-
-        public synchronized void registerNotifier(ChangeNotifier notifier) {
-            mNotifiers.put(notifier, null);
-        }
-
-        @Override
-        public synchronized void onChange(boolean selfChange) {
-            for(ChangeNotifier notifier : mNotifiers.keySet()) {
-                notifier.onChange(selfChange);
-            }
-        }
-    }
-
-    @Override
-    public void onStitchingQueued(Uri uri) {
-        // Do nothing.
-    }
-
-    @Override
-    public void onStitchingResult(Uri uri) {
-        Path path = findPathByUri(uri, null);
-        if (path != null) {
-            MediaObject mediaObject = getMediaObject(path);
-            if (mediaObject != null) {
-                mediaObject.clearCachedPanoramaSupport();
-            }
-        }
-    }
-
-    @Override
-    public void onStitchingProgress(Uri uri, int progress) {
-        // Do nothing.
-    }
-}
diff --git a/src/com/android/gallery3d/data/DataSourceType.java b/src/com/android/gallery3d/data/DataSourceType.java
deleted file mode 100644
index ab534d0..0000000
--- a/src/com/android/gallery3d/data/DataSourceType.java
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright (C) 2010 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.gallery3d.data;
-
-import com.android.gallery3d.util.MediaSetUtils;
-
-public final class DataSourceType {
-    public static final int TYPE_NOT_CATEGORIZED = 0;
-    public static final int TYPE_LOCAL = 1;
-    public static final int TYPE_PICASA = 2;
-    public static final int TYPE_CAMERA = 3;
-
-    private static final Path PICASA_ROOT = Path.fromString("/picasa");
-    private static final Path LOCAL_ROOT = Path.fromString("/local");
-
-    public static int identifySourceType(MediaSet set) {
-        if (set == null) {
-            return TYPE_NOT_CATEGORIZED;
-        }
-
-        Path path = set.getPath();
-        if (MediaSetUtils.isCameraSource(path)) return TYPE_CAMERA;
-
-        Path prefix = path.getPrefixPath();
-
-        if (prefix == PICASA_ROOT) return TYPE_PICASA;
-        if (prefix == LOCAL_ROOT) return TYPE_LOCAL;
-
-        return TYPE_NOT_CATEGORIZED;
-    }
-}
diff --git a/src/com/android/gallery3d/data/DecodeUtils.java b/src/com/android/gallery3d/data/DecodeUtils.java
deleted file mode 100644
index fa70915..0000000
--- a/src/com/android/gallery3d/data/DecodeUtils.java
+++ /dev/null
@@ -1,312 +0,0 @@
-/*
- * Copyright (C) 2010 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.gallery3d.data;
-
-import android.annotation.TargetApi;
-import android.graphics.Bitmap;
-import android.graphics.Bitmap.Config;
-import android.graphics.BitmapFactory;
-import android.graphics.BitmapFactory.Options;
-import android.graphics.BitmapRegionDecoder;
-import android.os.Build;
-import android.util.FloatMath;
-
-import com.android.gallery3d.common.ApiHelper;
-import com.android.gallery3d.common.BitmapUtils;
-import com.android.gallery3d.common.Utils;
-import com.android.photos.data.GalleryBitmapPool;
-import com.android.gallery3d.ui.Log;
-import com.android.gallery3d.util.ThreadPool.CancelListener;
-import com.android.gallery3d.util.ThreadPool.JobContext;
-
-import java.io.FileDescriptor;
-import java.io.FileInputStream;
-import java.io.InputStream;
-
-public class DecodeUtils {
-    private static final String TAG = "DecodeUtils";
-
-    private static class DecodeCanceller implements CancelListener {
-        Options mOptions;
-
-        public DecodeCanceller(Options options) {
-            mOptions = options;
-        }
-
-        @Override
-        public void onCancel() {
-            mOptions.requestCancelDecode();
-        }
-    }
-
-    @TargetApi(ApiHelper.VERSION_CODES.HONEYCOMB)
-    public static void setOptionsMutable(Options options) {
-        if (ApiHelper.HAS_OPTIONS_IN_MUTABLE) options.inMutable = true;
-    }
-
-    public static Bitmap decode(JobContext jc, FileDescriptor fd, Options options) {
-        if (options == null) options = new Options();
-        jc.setCancelListener(new DecodeCanceller(options));
-        setOptionsMutable(options);
-        return ensureGLCompatibleBitmap(
-                BitmapFactory.decodeFileDescriptor(fd, null, options));
-    }
-
-    public static void decodeBounds(JobContext jc, FileDescriptor fd,
-            Options options) {
-        Utils.assertTrue(options != null);
-        options.inJustDecodeBounds = true;
-        jc.setCancelListener(new DecodeCanceller(options));
-        BitmapFactory.decodeFileDescriptor(fd, null, options);
-        options.inJustDecodeBounds = false;
-    }
-
-    public static Bitmap decode(JobContext jc, byte[] bytes, Options options) {
-        return decode(jc, bytes, 0, bytes.length, options);
-    }
-
-    public static Bitmap decode(JobContext jc, byte[] bytes, int offset,
-            int length, Options options) {
-        if (options == null) options = new Options();
-        jc.setCancelListener(new DecodeCanceller(options));
-        setOptionsMutable(options);
-        return ensureGLCompatibleBitmap(
-                BitmapFactory.decodeByteArray(bytes, offset, length, options));
-    }
-
-    public static void decodeBounds(JobContext jc, byte[] bytes, int offset,
-            int length, Options options) {
-        Utils.assertTrue(options != null);
-        options.inJustDecodeBounds = true;
-        jc.setCancelListener(new DecodeCanceller(options));
-        BitmapFactory.decodeByteArray(bytes, offset, length, options);
-        options.inJustDecodeBounds = false;
-    }
-
-    public static Bitmap decodeThumbnail(
-            JobContext jc, String filePath, Options options, int targetSize, int type) {
-        FileInputStream fis = null;
-        try {
-            fis = new FileInputStream(filePath);
-            FileDescriptor fd = fis.getFD();
-            return decodeThumbnail(jc, fd, options, targetSize, type);
-        } catch (Exception ex) {
-            Log.w(TAG, ex);
-            return null;
-        } finally {
-            Utils.closeSilently(fis);
-        }
-    }
-
-    public static Bitmap decodeThumbnail(
-            JobContext jc, FileDescriptor fd, Options options, int targetSize, int type) {
-        if (options == null) options = new Options();
-        jc.setCancelListener(new DecodeCanceller(options));
-
-        options.inJustDecodeBounds = true;
-        BitmapFactory.decodeFileDescriptor(fd, null, options);
-        if (jc.isCancelled()) return null;
-
-        int w = options.outWidth;
-        int h = options.outHeight;
-
-        if (type == MediaItem.TYPE_MICROTHUMBNAIL) {
-            // We center-crop the original image as it's micro thumbnail. In this case,
-            // we want to make sure the shorter side >= "targetSize".
-            float scale = (float) targetSize / Math.min(w, h);
-            options.inSampleSize = BitmapUtils.computeSampleSizeLarger(scale);
-
-            // For an extremely wide image, e.g. 300x30000, we may got OOM when decoding
-            // it for TYPE_MICROTHUMBNAIL. So we add a max number of pixels limit here.
-            final int MAX_PIXEL_COUNT = 640000; // 400 x 1600
-            if ((w / options.inSampleSize) * (h / options.inSampleSize) > MAX_PIXEL_COUNT) {
-                options.inSampleSize = BitmapUtils.computeSampleSize(
-                        FloatMath.sqrt((float) MAX_PIXEL_COUNT / (w * h)));
-            }
-        } else {
-            // For screen nail, we only want to keep the longer side >= targetSize.
-            float scale = (float) targetSize / Math.max(w, h);
-            options.inSampleSize = BitmapUtils.computeSampleSizeLarger(scale);
-        }
-
-        options.inJustDecodeBounds = false;
-        setOptionsMutable(options);
-
-        Bitmap result = BitmapFactory.decodeFileDescriptor(fd, null, options);
-        if (result == null) return null;
-
-        // We need to resize down if the decoder does not support inSampleSize
-        // (For example, GIF images)
-        float scale = (float) targetSize / (type == MediaItem.TYPE_MICROTHUMBNAIL
-                ? Math.min(result.getWidth(), result.getHeight())
-                : Math.max(result.getWidth(), result.getHeight()));
-
-        if (scale <= 0.5) result = BitmapUtils.resizeBitmapByScale(result, scale, true);
-        return ensureGLCompatibleBitmap(result);
-    }
-
-    /**
-     * Decodes the bitmap from the given byte array if the image size is larger than the given
-     * requirement.
-     *
-     * Note: The returned image may be resized down. However, both width and height must be
-     * larger than the <code>targetSize</code>.
-     */
-    public static Bitmap decodeIfBigEnough(JobContext jc, byte[] data,
-            Options options, int targetSize) {
-        if (options == null) options = new Options();
-        jc.setCancelListener(new DecodeCanceller(options));
-
-        options.inJustDecodeBounds = true;
-        BitmapFactory.decodeByteArray(data, 0, data.length, options);
-        if (jc.isCancelled()) return null;
-        if (options.outWidth < targetSize || options.outHeight < targetSize) {
-            return null;
-        }
-        options.inSampleSize = BitmapUtils.computeSampleSizeLarger(
-                options.outWidth, options.outHeight, targetSize);
-        options.inJustDecodeBounds = false;
-        setOptionsMutable(options);
-
-        return ensureGLCompatibleBitmap(
-                BitmapFactory.decodeByteArray(data, 0, data.length, options));
-    }
-
-    // TODO: This function should not be called directly from
-    // DecodeUtils.requestDecode(...), since we don't have the knowledge
-    // if the bitmap will be uploaded to GL.
-    public static Bitmap ensureGLCompatibleBitmap(Bitmap bitmap) {
-        if (bitmap == null || bitmap.getConfig() != null) return bitmap;
-        Bitmap newBitmap = bitmap.copy(Config.ARGB_8888, false);
-        bitmap.recycle();
-        return newBitmap;
-    }
-
-    public static BitmapRegionDecoder createBitmapRegionDecoder(
-            JobContext jc, byte[] bytes, int offset, int length,
-            boolean shareable) {
-        if (offset < 0 || length <= 0 || offset + length > bytes.length) {
-            throw new IllegalArgumentException(String.format(
-                    "offset = %s, length = %s, bytes = %s",
-                    offset, length, bytes.length));
-        }
-
-        try {
-            return BitmapRegionDecoder.newInstance(
-                    bytes, offset, length, shareable);
-        } catch (Throwable t)  {
-            Log.w(TAG, t);
-            return null;
-        }
-    }
-
-    public static BitmapRegionDecoder createBitmapRegionDecoder(
-            JobContext jc, String filePath, boolean shareable) {
-        try {
-            return BitmapRegionDecoder.newInstance(filePath, shareable);
-        } catch (Throwable t)  {
-            Log.w(TAG, t);
-            return null;
-        }
-    }
-
-    public static BitmapRegionDecoder createBitmapRegionDecoder(
-            JobContext jc, FileDescriptor fd, boolean shareable) {
-        try {
-            return BitmapRegionDecoder.newInstance(fd, shareable);
-        } catch (Throwable t)  {
-            Log.w(TAG, t);
-            return null;
-        }
-    }
-
-    public static BitmapRegionDecoder createBitmapRegionDecoder(
-            JobContext jc, InputStream is, boolean shareable) {
-        try {
-            return BitmapRegionDecoder.newInstance(is, shareable);
-        } catch (Throwable t)  {
-            // We often cancel the creating of bitmap region decoder,
-            // so just log one line.
-            Log.w(TAG, "requestCreateBitmapRegionDecoder: " + t);
-            return null;
-        }
-    }
-
-    @TargetApi(Build.VERSION_CODES.HONEYCOMB)
-    public static Bitmap decodeUsingPool(JobContext jc, byte[] data, int offset,
-            int length, BitmapFactory.Options options) {
-        if (options == null) options = new BitmapFactory.Options();
-        if (options.inSampleSize < 1) options.inSampleSize = 1;
-        options.inPreferredConfig = Bitmap.Config.ARGB_8888;
-        options.inBitmap = (options.inSampleSize == 1)
-                ? findCachedBitmap(jc, data, offset, length, options) : null;
-        try {
-            Bitmap bitmap = decode(jc, data, offset, length, options);
-            if (options.inBitmap != null && options.inBitmap != bitmap) {
-                GalleryBitmapPool.getInstance().put(options.inBitmap);
-                options.inBitmap = null;
-            }
-            return bitmap;
-        } catch (IllegalArgumentException e) {
-            if (options.inBitmap == null) throw e;
-
-            Log.w(TAG, "decode fail with a given bitmap, try decode to a new bitmap");
-            GalleryBitmapPool.getInstance().put(options.inBitmap);
-            options.inBitmap = null;
-            return decode(jc, data, offset, length, options);
-        }
-    }
-
-    // This is the same as the method above except the source data comes
-    // from a file descriptor instead of a byte array.
-    @TargetApi(Build.VERSION_CODES.HONEYCOMB)
-    public static Bitmap decodeUsingPool(JobContext jc,
-            FileDescriptor fileDescriptor, Options options) {
-        if (options == null) options = new BitmapFactory.Options();
-        if (options.inSampleSize < 1) options.inSampleSize = 1;
-        options.inPreferredConfig = Bitmap.Config.ARGB_8888;
-        options.inBitmap = (options.inSampleSize == 1)
-                ? findCachedBitmap(jc, fileDescriptor, options) : null;
-        try {
-            Bitmap bitmap = DecodeUtils.decode(jc, fileDescriptor, options);
-            if (options.inBitmap != null && options.inBitmap != bitmap) {
-                GalleryBitmapPool.getInstance().put(options.inBitmap);
-                options.inBitmap = null;
-            }
-            return bitmap;
-        } catch (IllegalArgumentException e) {
-            if (options.inBitmap == null) throw e;
-
-            Log.w(TAG, "decode fail with a given bitmap, try decode to a new bitmap");
-            GalleryBitmapPool.getInstance().put(options.inBitmap);
-            options.inBitmap = null;
-            return decode(jc, fileDescriptor, options);
-        }
-    }
-
-    private static Bitmap findCachedBitmap(JobContext jc, byte[] data,
-            int offset, int length, Options options) {
-        decodeBounds(jc, data, offset, length, options);
-        return GalleryBitmapPool.getInstance().get(options.outWidth, options.outHeight);
-    }
-
-    private static Bitmap findCachedBitmap(JobContext jc, FileDescriptor fileDescriptor,
-            Options options) {
-        decodeBounds(jc, fileDescriptor, options);
-        return GalleryBitmapPool.getInstance().get(options.outWidth, options.outHeight);
-    }
-}
diff --git a/src/com/android/gallery3d/data/DownloadCache.java b/src/com/android/gallery3d/data/DownloadCache.java
deleted file mode 100644
index be7820b..0000000
--- a/src/com/android/gallery3d/data/DownloadCache.java
+++ /dev/null
@@ -1,370 +0,0 @@
-/*
- * Copyright (C) 2010 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.gallery3d.data;
-
-import android.content.ContentValues;
-import android.content.Context;
-import android.database.Cursor;
-import android.database.sqlite.SQLiteDatabase;
-import android.database.sqlite.SQLiteOpenHelper;
-
-import com.android.gallery3d.app.GalleryApp;
-import com.android.gallery3d.common.LruCache;
-import com.android.gallery3d.common.Utils;
-import com.android.gallery3d.data.DownloadEntry.Columns;
-import com.android.gallery3d.util.Future;
-import com.android.gallery3d.util.FutureListener;
-import com.android.gallery3d.util.ThreadPool;
-import com.android.gallery3d.util.ThreadPool.CancelListener;
-import com.android.gallery3d.util.ThreadPool.Job;
-import com.android.gallery3d.util.ThreadPool.JobContext;
-
-import java.io.File;
-import java.net.URL;
-import java.util.HashMap;
-import java.util.HashSet;
-
-public class DownloadCache {
-    private static final String TAG = "DownloadCache";
-    private static final int MAX_DELETE_COUNT = 16;
-    private static final int LRU_CAPACITY = 4;
-
-    private static final String TABLE_NAME = DownloadEntry.SCHEMA.getTableName();
-
-    private static final String QUERY_PROJECTION[] = {Columns.ID, Columns.DATA};
-    private static final String WHERE_HASH_AND_URL = String.format(
-            "%s = ? AND %s = ?", Columns.HASH_CODE, Columns.CONTENT_URL);
-    private static final int QUERY_INDEX_ID = 0;
-    private static final int QUERY_INDEX_DATA = 1;
-
-    private static final String FREESPACE_PROJECTION[] = {
-            Columns.ID, Columns.DATA, Columns.CONTENT_URL, Columns.CONTENT_SIZE};
-    private static final String FREESPACE_ORDER_BY =
-            String.format("%s ASC", Columns.LAST_ACCESS);
-    private static final int FREESPACE_IDNEX_ID = 0;
-    private static final int FREESPACE_IDNEX_DATA = 1;
-    private static final int FREESPACE_INDEX_CONTENT_URL = 2;
-    private static final int FREESPACE_INDEX_CONTENT_SIZE = 3;
-
-    private static final String ID_WHERE = Columns.ID + " = ?";
-
-    private static final String SUM_PROJECTION[] =
-            {String.format("sum(%s)", Columns.CONTENT_SIZE)};
-    private static final int SUM_INDEX_SUM = 0;
-
-    private final LruCache<String, Entry> mEntryMap =
-            new LruCache<String, Entry>(LRU_CAPACITY);
-    private final HashMap<String, DownloadTask> mTaskMap =
-            new HashMap<String, DownloadTask>();
-    private final File mRoot;
-    private final GalleryApp mApplication;
-    private final SQLiteDatabase mDatabase;
-    private final long mCapacity;
-
-    private long mTotalBytes = 0;
-    private boolean mInitialized = false;
-
-    public DownloadCache(GalleryApp application, File root, long capacity) {
-        mRoot = Utils.checkNotNull(root);
-        mApplication = Utils.checkNotNull(application);
-        mCapacity = capacity;
-        mDatabase = new DatabaseHelper(application.getAndroidContext())
-                .getWritableDatabase();
-    }
-
-    private Entry findEntryInDatabase(String stringUrl) {
-        long hash = Utils.crc64Long(stringUrl);
-        String whereArgs[] = {String.valueOf(hash), stringUrl};
-        Cursor cursor = mDatabase.query(TABLE_NAME, QUERY_PROJECTION,
-                WHERE_HASH_AND_URL, whereArgs, null, null, null);
-        try {
-            if (cursor.moveToNext()) {
-                File file = new File(cursor.getString(QUERY_INDEX_DATA));
-                long id = cursor.getInt(QUERY_INDEX_ID);
-                Entry entry = null;
-                synchronized (mEntryMap) {
-                    entry = mEntryMap.get(stringUrl);
-                    if (entry == null) {
-                        entry = new Entry(id, file);
-                        mEntryMap.put(stringUrl, entry);
-                    }
-                }
-                return entry;
-            }
-        } finally {
-            cursor.close();
-        }
-        return null;
-    }
-
-    public Entry download(JobContext jc, URL url) {
-        if (!mInitialized) initialize();
-
-        String stringUrl = url.toString();
-
-        // First find in the entry-pool
-        synchronized (mEntryMap) {
-            Entry entry = mEntryMap.get(stringUrl);
-            if (entry != null) {
-                updateLastAccess(entry.mId);
-                return entry;
-            }
-        }
-
-        // Then, find it in database
-        TaskProxy proxy = new TaskProxy();
-        synchronized (mTaskMap) {
-            Entry entry = findEntryInDatabase(stringUrl);
-            if (entry != null) {
-                updateLastAccess(entry.mId);
-                return entry;
-            }
-
-            // Finally, we need to download the file ....
-            // First check if we are downloading it now ...
-            DownloadTask task = mTaskMap.get(stringUrl);
-            if (task == null) { // if not, start the download task now
-                task = new DownloadTask(stringUrl);
-                mTaskMap.put(stringUrl, task);
-                task.mFuture = mApplication.getThreadPool().submit(task, task);
-            }
-            task.addProxy(proxy);
-        }
-
-        return proxy.get(jc);
-    }
-
-    private void updateLastAccess(long id) {
-        ContentValues values = new ContentValues();
-        values.put(Columns.LAST_ACCESS, System.currentTimeMillis());
-        mDatabase.update(TABLE_NAME, values,
-                ID_WHERE, new String[] {String.valueOf(id)});
-    }
-
-    private synchronized void freeSomeSpaceIfNeed(int maxDeleteFileCount) {
-        if (mTotalBytes <= mCapacity) return;
-        Cursor cursor = mDatabase.query(TABLE_NAME,
-                FREESPACE_PROJECTION, null, null, null, null, FREESPACE_ORDER_BY);
-        try {
-            while (maxDeleteFileCount > 0
-                    && mTotalBytes > mCapacity && cursor.moveToNext()) {
-                long id = cursor.getLong(FREESPACE_IDNEX_ID);
-                String url = cursor.getString(FREESPACE_INDEX_CONTENT_URL);
-                long size = cursor.getLong(FREESPACE_INDEX_CONTENT_SIZE);
-                String path = cursor.getString(FREESPACE_IDNEX_DATA);
-                boolean containsKey;
-                synchronized (mEntryMap) {
-                    containsKey = mEntryMap.containsKey(url);
-                }
-                if (!containsKey) {
-                    --maxDeleteFileCount;
-                    mTotalBytes -= size;
-                    new File(path).delete();
-                    mDatabase.delete(TABLE_NAME,
-                            ID_WHERE, new String[]{String.valueOf(id)});
-                } else {
-                    // skip delete, since it is being used
-                }
-            }
-        } finally {
-            cursor.close();
-        }
-    }
-
-    private synchronized long insertEntry(String url, File file) {
-        long size = file.length();
-        mTotalBytes += size;
-
-        ContentValues values = new ContentValues();
-        String hashCode = String.valueOf(Utils.crc64Long(url));
-        values.put(Columns.DATA, file.getAbsolutePath());
-        values.put(Columns.HASH_CODE, hashCode);
-        values.put(Columns.CONTENT_URL, url);
-        values.put(Columns.CONTENT_SIZE, size);
-        values.put(Columns.LAST_UPDATED, System.currentTimeMillis());
-        return mDatabase.insert(TABLE_NAME, "", values);
-    }
-
-    private synchronized void initialize() {
-        if (mInitialized) return;
-        mInitialized = true;
-        if (!mRoot.isDirectory()) mRoot.mkdirs();
-        if (!mRoot.isDirectory()) {
-            throw new RuntimeException("cannot create " + mRoot.getAbsolutePath());
-        }
-
-        Cursor cursor = mDatabase.query(
-                TABLE_NAME, SUM_PROJECTION, null, null, null, null, null);
-        mTotalBytes = 0;
-        try {
-            if (cursor.moveToNext()) {
-                mTotalBytes = cursor.getLong(SUM_INDEX_SUM);
-            }
-        } finally {
-            cursor.close();
-        }
-        if (mTotalBytes > mCapacity) freeSomeSpaceIfNeed(MAX_DELETE_COUNT);
-    }
-
-    private final class DatabaseHelper extends SQLiteOpenHelper {
-        public static final String DATABASE_NAME = "download.db";
-        public static final int DATABASE_VERSION = 2;
-
-        public DatabaseHelper(Context context) {
-            super(context, DATABASE_NAME, null, DATABASE_VERSION);
-        }
-
-        @Override
-        public void onCreate(SQLiteDatabase db) {
-            DownloadEntry.SCHEMA.createTables(db);
-            // Delete old files
-            for (File file : mRoot.listFiles()) {
-                if (!file.delete()) {
-                    Log.w(TAG, "fail to remove: " + file.getAbsolutePath());
-                }
-            }
-        }
-
-        @Override
-        public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
-            //reset everything
-            DownloadEntry.SCHEMA.dropTables(db);
-            onCreate(db);
-        }
-    }
-
-    public class Entry {
-        public File cacheFile;
-        protected long mId;
-
-        Entry(long id, File cacheFile) {
-            mId = id;
-            this.cacheFile = Utils.checkNotNull(cacheFile);
-        }
-    }
-
-    private class DownloadTask implements Job<File>, FutureListener<File> {
-        private HashSet<TaskProxy> mProxySet = new HashSet<TaskProxy>();
-        private Future<File> mFuture;
-        private final String mUrl;
-
-        public DownloadTask(String url) {
-            mUrl = Utils.checkNotNull(url);
-        }
-
-        public void removeProxy(TaskProxy proxy) {
-            synchronized (mTaskMap) {
-                Utils.assertTrue(mProxySet.remove(proxy));
-                if (mProxySet.isEmpty()) {
-                    mFuture.cancel();
-                    mTaskMap.remove(mUrl);
-                }
-            }
-        }
-
-        // should be used in synchronized block of mDatabase
-        public void addProxy(TaskProxy proxy) {
-            proxy.mTask = this;
-            mProxySet.add(proxy);
-        }
-
-        @Override
-        public void onFutureDone(Future<File> future) {
-            File file = future.get();
-            long id = 0;
-            if (file != null) { // insert to database
-                id = insertEntry(mUrl, file);
-            }
-
-            if (future.isCancelled()) {
-                Utils.assertTrue(mProxySet.isEmpty());
-                return;
-            }
-
-            synchronized (mTaskMap) {
-                Entry entry = null;
-                synchronized (mEntryMap) {
-                    if (file != null) {
-                        entry = new Entry(id, file);
-                        Utils.assertTrue(mEntryMap.put(mUrl, entry) == null);
-                    }
-                }
-                for (TaskProxy proxy : mProxySet) {
-                    proxy.setResult(entry);
-                }
-                mTaskMap.remove(mUrl);
-                freeSomeSpaceIfNeed(MAX_DELETE_COUNT);
-            }
-        }
-
-        @Override
-        public File run(JobContext jc) {
-            // TODO: utilize etag
-            jc.setMode(ThreadPool.MODE_NETWORK);
-            File tempFile = null;
-            try {
-                URL url = new URL(mUrl);
-                tempFile = File.createTempFile("cache", ".tmp", mRoot);
-                // download from url to tempFile
-                jc.setMode(ThreadPool.MODE_NETWORK);
-                boolean downloaded = DownloadUtils.requestDownload(jc, url, tempFile);
-                jc.setMode(ThreadPool.MODE_NONE);
-                if (downloaded) return tempFile;
-            } catch (Exception e) {
-                Log.e(TAG, String.format("fail to download %s", mUrl), e);
-            } finally {
-                jc.setMode(ThreadPool.MODE_NONE);
-            }
-            if (tempFile != null) tempFile.delete();
-            return null;
-        }
-    }
-
-    public static class TaskProxy {
-        private DownloadTask mTask;
-        private boolean mIsCancelled = false;
-        private Entry mEntry;
-
-        synchronized void setResult(Entry entry) {
-            if (mIsCancelled) return;
-            mEntry = entry;
-            notifyAll();
-        }
-
-        public synchronized Entry get(JobContext jc) {
-            jc.setCancelListener(new CancelListener() {
-                @Override
-                public void onCancel() {
-                    mTask.removeProxy(TaskProxy.this);
-                    synchronized (TaskProxy.this) {
-                        mIsCancelled = true;
-                        TaskProxy.this.notifyAll();
-                    }
-                }
-            });
-            while (!mIsCancelled && mEntry == null) {
-                try {
-                    wait();
-                } catch (InterruptedException e) {
-                    Log.w(TAG, "ignore interrupt", e);
-                }
-            }
-            jc.setCancelListener(null);
-            return mEntry;
-        }
-    }
-}
diff --git a/src/com/android/gallery3d/data/DownloadEntry.java b/src/com/android/gallery3d/data/DownloadEntry.java
deleted file mode 100644
index 578523f..0000000
--- a/src/com/android/gallery3d/data/DownloadEntry.java
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * Copyright (C) 2010 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.gallery3d.data;
-
-import com.android.gallery3d.common.Entry;
-import com.android.gallery3d.common.EntrySchema;
-
-
-@Entry.Table("download")
-public class DownloadEntry extends Entry {
-    public static final EntrySchema SCHEMA = new EntrySchema(DownloadEntry.class);
-
-    public static interface Columns extends Entry.Columns {
-        public static final String HASH_CODE = "hash_code";
-        public static final String CONTENT_URL = "content_url";
-        public static final String CONTENT_SIZE = "_size";
-        public static final String ETAG = "etag";
-        public static final String LAST_ACCESS = "last_access";
-        public static final String LAST_UPDATED = "last_updated";
-        public static final String DATA = "_data";
-    }
-
-    @Column(value = "hash_code", indexed = true)
-    public long hashCode;
-
-    @Column("content_url")
-    public String contentUrl;
-
-    @Column("_size")
-    public long contentSize;
-
-    @Column("etag")
-    public String eTag;
-
-    @Column(value = "last_access", indexed = true)
-    public long lastAccessTime;
-
-    @Column(value = "last_updated")
-    public long lastUpdatedTime;
-
-    @Column("_data")
-    public String path;
-
-    @Override
-    public String toString() {
-        // Note: THIS IS REQUIRED. We used all the fields here. Otherwise,
-        //       ProGuard will remove these UNUSED fields. However, these
-        //       fields are needed to generate database.
-        return new StringBuilder()
-                .append("hash_code: ").append(hashCode).append(", ")
-                .append("content_url").append(contentUrl).append(", ")
-                .append("_size").append(contentSize).append(", ")
-                .append("etag").append(eTag).append(", ")
-                .append("last_access").append(lastAccessTime).append(", ")
-                .append("last_updated").append(lastUpdatedTime).append(",")
-                .append("_data").append(path)
-                .toString();
-    }
-}
diff --git a/src/com/android/gallery3d/data/DownloadUtils.java b/src/com/android/gallery3d/data/DownloadUtils.java
deleted file mode 100644
index 137898e..0000000
--- a/src/com/android/gallery3d/data/DownloadUtils.java
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * Copyright (C) 2010 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.gallery3d.data;
-
-import com.android.gallery3d.common.Utils;
-import com.android.gallery3d.util.ThreadPool.CancelListener;
-import com.android.gallery3d.util.ThreadPool.JobContext;
-
-import java.io.File;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InterruptedIOException;
-import java.io.OutputStream;
-import java.net.URL;
-
-public class DownloadUtils {
-    private static final String TAG = "DownloadService";
-
-    public static boolean requestDownload(JobContext jc, URL url, File file) {
-        FileOutputStream fos = null;
-        try {
-            fos = new FileOutputStream(file);
-            return download(jc, url, fos);
-        } catch (Throwable t) {
-            return false;
-        } finally {
-            Utils.closeSilently(fos);
-        }
-    }
-
-    public static void dump(JobContext jc, InputStream is, OutputStream os)
-            throws IOException {
-        byte buffer[] = new byte[4096];
-        int rc = is.read(buffer, 0, buffer.length);
-        final Thread thread = Thread.currentThread();
-        jc.setCancelListener(new CancelListener() {
-            @Override
-            public void onCancel() {
-                thread.interrupt();
-            }
-        });
-        while (rc > 0) {
-            if (jc.isCancelled()) throw new InterruptedIOException();
-            os.write(buffer, 0, rc);
-            rc = is.read(buffer, 0, buffer.length);
-        }
-        jc.setCancelListener(null);
-        Thread.interrupted(); // consume the interrupt signal
-    }
-
-    public static boolean download(JobContext jc, URL url, OutputStream output) {
-        InputStream input = null;
-        try {
-            input = url.openStream();
-            dump(jc, input, output);
-            return true;
-        } catch (Throwable t) {
-            Log.w(TAG, "fail to download", t);
-            return false;
-        } finally {
-            Utils.closeSilently(input);
-        }
-    }
-}
\ No newline at end of file
diff --git a/src/com/android/gallery3d/data/EmptyAlbumImage.java b/src/com/android/gallery3d/data/EmptyAlbumImage.java
deleted file mode 100644
index 6f8c37c..0000000
--- a/src/com/android/gallery3d/data/EmptyAlbumImage.java
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * 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.gallery3d.data;
-
-import com.android.gallery3d.R;
-import com.android.gallery3d.app.GalleryApp;
-
-public class EmptyAlbumImage extends ActionImage {
-    @SuppressWarnings("unused")
-    private static final String TAG = "EmptyAlbumImage";
-
-    public EmptyAlbumImage(Path path, GalleryApp application) {
-        super(path, application, R.drawable.placeholder_empty);
-    }
-
-    @Override
-    public int getSupportedOperations() {
-        return super.getSupportedOperations() | SUPPORT_BACK;
-    }
-}
diff --git a/src/com/android/gallery3d/data/Exif.java b/src/com/android/gallery3d/data/Exif.java
deleted file mode 100644
index 950e7de..0000000
--- a/src/com/android/gallery3d/data/Exif.java
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Copyright (C) 2011 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.gallery3d.data;
-
-import android.util.Log;
-
-import com.android.gallery3d.exif.ExifInterface;
-
-import java.io.IOException;
-import java.io.InputStream;
-
-public class Exif {
-    private static final String TAG = "CameraExif";
-
-    // Returns the degrees in clockwise. Values are 0, 90, 180, or 270.
-    public static int getOrientation(InputStream is) {
-        if (is == null) {
-            return 0;
-        }
-        ExifInterface exif = new ExifInterface();
-        try {
-            exif.readExif(is);
-            Integer val = exif.getTagIntValue(ExifInterface.TAG_ORIENTATION);
-            if (val == null) {
-                return 0;
-            } else {
-                return ExifInterface.getRotationForOrientationValue(val.shortValue());
-            }
-        } catch (IOException e) {
-            Log.w(TAG, "Failed to read EXIF orientation", e);
-            return 0;
-        }
-    }
-}
diff --git a/src/com/android/gallery3d/data/Face.java b/src/com/android/gallery3d/data/Face.java
deleted file mode 100644
index d2dc22b..0000000
--- a/src/com/android/gallery3d/data/Face.java
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * Copyright (C) 2011 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.gallery3d.data;
-
-import android.graphics.Rect;
-
-import com.android.gallery3d.common.Utils;
-
-import java.util.StringTokenizer;
-
-public class Face implements Comparable<Face> {
-    private String mName;
-    private String mPersonId;
-    private Rect mPosition;
-
-    public Face(String name, String personId, String rect) {
-        mName = name;
-        mPersonId = personId;
-        Utils.assertTrue(mName != null && mPersonId != null && rect != null);
-        StringTokenizer tokenizer = new StringTokenizer(rect);
-        mPosition = new Rect();
-        while (tokenizer.hasMoreElements()) {
-            mPosition.left = Integer.parseInt(tokenizer.nextToken());
-            mPosition.top = Integer.parseInt(tokenizer.nextToken());
-            mPosition.right = Integer.parseInt(tokenizer.nextToken());
-            mPosition.bottom = Integer.parseInt(tokenizer.nextToken());
-        }
-    }
-
-    public Rect getPosition() {
-        return mPosition;
-    }
-
-    public String getName() {
-        return mName;
-    }
-
-    @Override
-    public boolean equals(Object obj) {
-        if (obj instanceof Face) {
-            Face face = (Face) obj;
-            return mPersonId.equals(face.mPersonId);
-        }
-        return false;
-    }
-
-    @Override
-    public int compareTo(Face another) {
-        return mName.compareTo(another.mName);
-    }
-}
diff --git a/src/com/android/gallery3d/data/FaceClustering.java b/src/com/android/gallery3d/data/FaceClustering.java
deleted file mode 100644
index 819915e..0000000
--- a/src/com/android/gallery3d/data/FaceClustering.java
+++ /dev/null
@@ -1,142 +0,0 @@
-/*
- * Copyright (C) 2011 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.gallery3d.data;
-
-import android.content.Context;
-import android.graphics.Rect;
-
-import com.android.gallery3d.R;
-import com.android.gallery3d.picasasource.PicasaSource;
-
-import java.util.ArrayList;
-import java.util.TreeMap;
-
-public class FaceClustering extends Clustering {
-    @SuppressWarnings("unused")
-    private static final String TAG = "FaceClustering";
-
-    private FaceCluster[] mClusters;
-    private String mUntaggedString;
-    private Context mContext;
-
-    private class FaceCluster {
-        ArrayList<Path> mPaths = new ArrayList<Path>();
-        String mName;
-        MediaItem mCoverItem;
-        Rect mCoverRegion;
-        int mCoverFaceIndex;
-
-        public FaceCluster(String name) {
-            mName = name;
-        }
-
-        public void add(MediaItem item, int faceIndex) {
-            Path path = item.getPath();
-            mPaths.add(path);
-            Face[] faces = item.getFaces();
-            if (faces != null) {
-                Face face = faces[faceIndex];
-                if (mCoverItem == null) {
-                    mCoverItem = item;
-                    mCoverRegion = face.getPosition();
-                    mCoverFaceIndex = faceIndex;
-                } else {
-                    Rect region = face.getPosition();
-                    if (mCoverRegion.width() < region.width() &&
-                            mCoverRegion.height() < region.height()) {
-                        mCoverItem = item;
-                        mCoverRegion = face.getPosition();
-                        mCoverFaceIndex = faceIndex;
-                    }
-                }
-            }
-        }
-
-        public int size() {
-            return mPaths.size();
-        }
-
-        public MediaItem getCover() {
-            if (mCoverItem != null) {
-                if (PicasaSource.isPicasaImage(mCoverItem)) {
-                    return PicasaSource.getFaceItem(mContext, mCoverItem, mCoverFaceIndex);
-                } else {
-                    return mCoverItem;
-                }
-            }
-            return null;
-        }
-    }
-
-    public FaceClustering(Context context) {
-        mUntaggedString = context.getResources().getString(R.string.untagged);
-        mContext = context;
-    }
-
-    @Override
-    public void run(MediaSet baseSet) {
-        final TreeMap<Face, FaceCluster> map =
-                new TreeMap<Face, FaceCluster>();
-        final FaceCluster untagged = new FaceCluster(mUntaggedString);
-
-        baseSet.enumerateTotalMediaItems(new MediaSet.ItemConsumer() {
-            @Override
-            public void consume(int index, MediaItem item) {
-                Face[] faces = item.getFaces();
-                if (faces == null || faces.length == 0) {
-                    untagged.add(item, -1);
-                    return;
-                }
-                for (int j = 0; j < faces.length; j++) {
-                    Face face = faces[j];
-                    FaceCluster cluster = map.get(face);
-                    if (cluster == null) {
-                        cluster = new FaceCluster(face.getName());
-                        map.put(face, cluster);
-                    }
-                    cluster.add(item, j);
-                }
-            }
-        });
-
-        int m = map.size();
-        mClusters = map.values().toArray(new FaceCluster[m + ((untagged.size() > 0) ? 1 : 0)]);
-        if (untagged.size() > 0) {
-            mClusters[m] = untagged;
-        }
-    }
-
-    @Override
-    public int getNumberOfClusters() {
-        return mClusters.length;
-    }
-
-    @Override
-    public ArrayList<Path> getCluster(int index) {
-        return mClusters[index].mPaths;
-    }
-
-    @Override
-    public String getClusterName(int index) {
-        return mClusters[index].mName;
-    }
-
-    @Override
-    public MediaItem getClusterCover(int index) {
-        return mClusters[index].getCover();
-    }
-}
diff --git a/src/com/android/gallery3d/data/FilterDeleteSet.java b/src/com/android/gallery3d/data/FilterDeleteSet.java
deleted file mode 100644
index c76412f..0000000
--- a/src/com/android/gallery3d/data/FilterDeleteSet.java
+++ /dev/null
@@ -1,256 +0,0 @@
-/*
- * 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.gallery3d.data;
-
-import java.util.ArrayList;
-
-// FilterDeleteSet filters a base MediaSet to remove some deletion items (we
-// expect the number to be small). The user can use the following methods to
-// add/remove deletion items:
-//
-// void addDeletion(Path path, int index);
-// void removeDelection(Path path);
-// void clearDeletion();
-// int getNumberOfDeletions();
-//
-public class FilterDeleteSet extends MediaSet implements ContentListener {
-    @SuppressWarnings("unused")
-    private static final String TAG = "FilterDeleteSet";
-
-    private static final int REQUEST_ADD = 1;
-    private static final int REQUEST_REMOVE = 2;
-    private static final int REQUEST_CLEAR = 3;
-
-    private static class Request {
-        int type;  // one of the REQUEST_* constants
-        Path path;
-        int indexHint;
-        public Request(int type, Path path, int indexHint) {
-            this.type = type;
-            this.path = path;
-            this.indexHint = indexHint;
-        }
-    }
-
-    private static class Deletion {
-        Path path;
-        int index;
-        public Deletion(Path path, int index) {
-            this.path = path;
-            this.index = index;
-        }
-    }
-
-    // The underlying MediaSet
-    private final MediaSet mBaseSet;
-
-    // Pending Requests
-    private ArrayList<Request> mRequests = new ArrayList<Request>();
-
-    // Deletions currently in effect, ordered by index
-    private ArrayList<Deletion> mCurrent = new ArrayList<Deletion>();
-
-    public FilterDeleteSet(Path path, MediaSet baseSet) {
-        super(path, INVALID_DATA_VERSION);
-        mBaseSet = baseSet;
-        mBaseSet.addContentListener(this);
-    }
-
-    @Override
-    public boolean isCameraRoll() {
-        return mBaseSet.isCameraRoll();
-    }
-
-    @Override
-    public String getName() {
-        return mBaseSet.getName();
-    }
-
-    @Override
-    public int getMediaItemCount() {
-        return mBaseSet.getMediaItemCount() - mCurrent.size();
-    }
-
-    // Gets the MediaItems whose (post-deletion) index are in the range [start,
-    // start + count). Because we remove some of the MediaItems, the index need
-    // to be adjusted.
-    //
-    // For example, if there are 12 items in total. The deleted items are 3, 5,
-    // 10, and the the requested range is [3, 7]:
-    //
-    // The original index:   0 1 2 3 4 5 6 7 8 9 A B C
-    // The deleted items:          X   X         X
-    // The new index:        0 1 2   3   4 5 6 7   8 9
-    // Requested:                    *   * * * *
-    //
-    // We need to figure out the [3, 7] actually maps to the original index 4,
-    // 6, 7, 8, 9.
-    //
-    // We can break the MediaItems into segments, each segment other than the
-    // last one ends in a deleted item. The difference between the new index and
-    // the original index increases with each segment:
-    //
-    // 0 1 2 X     (new index = old index)
-    // 4 X         (new index = old index - 1)
-    // 6 7 8 9 X   (new index = old index - 2)
-    // B C         (new index = old index - 3)
-    //
-    @Override
-    public ArrayList<MediaItem> getMediaItem(int start, int count) {
-        if (count <= 0) return new ArrayList<MediaItem>();
-
-        int end = start + count - 1;
-        int n = mCurrent.size();
-        // Find the segment that "start" falls into. Count the number of items
-        // not yet deleted until it reaches "start".
-        int i = 0;
-        for (i = 0; i < n; i++) {
-            Deletion d = mCurrent.get(i);
-            if (d.index - i > start) break;
-        }
-        // Find the segment that "end" falls into.
-        int j = i;
-        for (; j < n; j++) {
-            Deletion d = mCurrent.get(j);
-            if (d.index - j > end) break;
-        }
-
-        // Now get enough to cover deleted items in [start, end]
-        ArrayList<MediaItem> base = mBaseSet.getMediaItem(start + i, count + (j - i));
-
-        // Remove the deleted items.
-        for (int m = j - 1; m >= i; m--) {
-            Deletion d = mCurrent.get(m);
-            int k = d.index - (start + i);
-            base.remove(k);
-        }
-        return base;
-    }
-
-    // We apply the pending requests in the mRequests to construct mCurrent in reload().
-    @Override
-    public long reload() {
-        boolean newData = mBaseSet.reload() > mDataVersion;
-        synchronized (mRequests) {
-            if (!newData && mRequests.isEmpty()) {
-                return mDataVersion;
-            }
-            for (int i = 0; i < mRequests.size(); i++) {
-                Request r = mRequests.get(i);
-                switch (r.type) {
-                    case REQUEST_ADD: {
-                        // Add the path into mCurrent if there is no duplicate.
-                        int n = mCurrent.size();
-                        int j;
-                        for (j = 0; j < n; j++) {
-                            if (mCurrent.get(j).path == r.path) break;
-                        }
-                        if (j == n) {
-                            mCurrent.add(new Deletion(r.path, r.indexHint));
-                        }
-                        break;
-                    }
-                    case REQUEST_REMOVE: {
-                        // Remove the path from mCurrent.
-                        int n = mCurrent.size();
-                        for (int j = 0; j < n; j++) {
-                            if (mCurrent.get(j).path == r.path) {
-                                mCurrent.remove(j);
-                                break;
-                            }
-                        }
-                        break;
-                    }
-                    case REQUEST_CLEAR: {
-                        mCurrent.clear();
-                        break;
-                    }
-                }
-            }
-            mRequests.clear();
-        }
-
-        if (!mCurrent.isEmpty()) {
-            // See if the elements in mCurrent can be found in the MediaSet. We
-            // don't want to search the whole mBaseSet, so we just search a
-            // small window that contains the index hints (plus some margin).
-            int minIndex = mCurrent.get(0).index;
-            int maxIndex = minIndex;
-            for (int i = 1; i < mCurrent.size(); i++) {
-                Deletion d = mCurrent.get(i);
-                minIndex = Math.min(d.index, minIndex);
-                maxIndex = Math.max(d.index, maxIndex);
-            }
-
-            int n = mBaseSet.getMediaItemCount();
-            int from = Math.max(minIndex - 5, 0);
-            int to = Math.min(maxIndex + 5, n);
-            ArrayList<MediaItem> items = mBaseSet.getMediaItem(from, to - from);
-            ArrayList<Deletion> result = new ArrayList<Deletion>();
-            for (int i = 0; i < items.size(); i++) {
-                MediaItem item = items.get(i);
-                if (item == null) continue;
-                Path p = item.getPath();
-                // Find the matching path in mCurrent, if found move it to result
-                for (int j = 0; j < mCurrent.size(); j++) {
-                    Deletion d = mCurrent.get(j);
-                    if (d.path == p) {
-                        d.index = from + i;
-                        result.add(d);
-                        mCurrent.remove(j);
-                        break;
-                    }
-                }
-            }
-            mCurrent = result;
-        }
-
-        mDataVersion = nextVersionNumber();
-        return mDataVersion;
-    }
-
-    private void sendRequest(int type, Path path, int indexHint) {
-        Request r = new Request(type, path, indexHint);
-        synchronized (mRequests) {
-            mRequests.add(r);
-        }
-        notifyContentChanged();
-    }
-
-    @Override
-    public void onContentDirty() {
-        notifyContentChanged();
-    }
-
-    public void addDeletion(Path path, int indexHint) {
-        sendRequest(REQUEST_ADD, path, indexHint);
-    }
-
-    public void removeDeletion(Path path) {
-        sendRequest(REQUEST_REMOVE, path, 0 /* unused */);
-    }
-
-    public void clearDeletion() {
-        sendRequest(REQUEST_CLEAR, null /* unused */ , 0 /* unused */);
-    }
-
-    // Returns number of deletions _in effect_ (the number will only gets
-    // updated after a reload()).
-    public int getNumberOfDeletions() {
-        return mCurrent.size();
-    }
-}
diff --git a/src/com/android/gallery3d/data/FilterEmptyPromptSet.java b/src/com/android/gallery3d/data/FilterEmptyPromptSet.java
deleted file mode 100644
index b576e06..0000000
--- a/src/com/android/gallery3d/data/FilterEmptyPromptSet.java
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * 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.gallery3d.data;
-
-import java.util.ArrayList;
-
-public class FilterEmptyPromptSet extends MediaSet implements ContentListener {
-    @SuppressWarnings("unused")
-    private static final String TAG = "FilterEmptyPromptSet";
-
-    private ArrayList<MediaItem> mEmptyItem;
-    private MediaSet mBaseSet;
-
-    public FilterEmptyPromptSet(Path path, MediaSet baseSet, MediaItem emptyItem) {
-        super(path, INVALID_DATA_VERSION);
-        mEmptyItem = new ArrayList<MediaItem>(1);
-        mEmptyItem.add(emptyItem);
-        mBaseSet = baseSet;
-        mBaseSet.addContentListener(this);
-    }
-
-    @Override
-    public int getMediaItemCount() {
-        int itemCount = mBaseSet.getMediaItemCount();
-        if (itemCount > 0) {
-            return itemCount;
-        } else {
-            return 1;
-        }
-    }
-
-    @Override
-    public ArrayList<MediaItem> getMediaItem(int start, int count) {
-        int itemCount = mBaseSet.getMediaItemCount();
-        if (itemCount > 0) {
-            return mBaseSet.getMediaItem(start, count);
-        } else if (start == 0 && count == 1) {
-            return mEmptyItem;
-        } else {
-            throw new ArrayIndexOutOfBoundsException();
-        }
-    }
-
-    @Override
-    public void onContentDirty() {
-        notifyContentChanged();
-    }
-
-    @Override
-    public boolean isLeafAlbum() {
-        return true;
-    }
-
-    @Override
-    public boolean isCameraRoll() {
-        return mBaseSet.isCameraRoll();
-    }
-
-    @Override
-    public long reload() {
-        return mBaseSet.reload();
-    }
-
-    @Override
-    public String getName() {
-        return mBaseSet.getName();
-    }
-}
diff --git a/src/com/android/gallery3d/data/FilterSource.java b/src/com/android/gallery3d/data/FilterSource.java
deleted file mode 100644
index d689fe3..0000000
--- a/src/com/android/gallery3d/data/FilterSource.java
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
- * Copyright (C) 2010 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.gallery3d.data;
-
-import com.android.gallery3d.app.GalleryApp;
-
-public class FilterSource extends MediaSource {
-    @SuppressWarnings("unused")
-    private static final String TAG = "FilterSource";
-    private static final int FILTER_BY_MEDIATYPE = 0;
-    private static final int FILTER_BY_DELETE = 1;
-    private static final int FILTER_BY_EMPTY = 2;
-    private static final int FILTER_BY_EMPTY_ITEM = 3;
-    private static final int FILTER_BY_CAMERA_SHORTCUT = 4;
-    private static final int FILTER_BY_CAMERA_SHORTCUT_ITEM = 5;
-
-    public static final String FILTER_EMPTY_ITEM = "/filter/empty_prompt";
-    public static final String FILTER_CAMERA_SHORTCUT = "/filter/camera_shortcut";
-    private static final String FILTER_CAMERA_SHORTCUT_ITEM = "/filter/camera_shortcut_item";
-
-    private GalleryApp mApplication;
-    private PathMatcher mMatcher;
-    private MediaItem mEmptyItem;
-    private MediaItem mCameraShortcutItem;
-
-    public FilterSource(GalleryApp application) {
-        super("filter");
-        mApplication = application;
-        mMatcher = new PathMatcher();
-        mMatcher.add("/filter/mediatype/*/*", FILTER_BY_MEDIATYPE);
-        mMatcher.add("/filter/delete/*", FILTER_BY_DELETE);
-        mMatcher.add("/filter/empty/*", FILTER_BY_EMPTY);
-        mMatcher.add(FILTER_EMPTY_ITEM, FILTER_BY_EMPTY_ITEM);
-        mMatcher.add(FILTER_CAMERA_SHORTCUT, FILTER_BY_CAMERA_SHORTCUT);
-        mMatcher.add(FILTER_CAMERA_SHORTCUT_ITEM, FILTER_BY_CAMERA_SHORTCUT_ITEM);
-
-        mEmptyItem = new EmptyAlbumImage(Path.fromString(FILTER_EMPTY_ITEM),
-                mApplication);
-        mCameraShortcutItem = new CameraShortcutImage(
-                Path.fromString(FILTER_CAMERA_SHORTCUT_ITEM), mApplication);
-    }
-
-    // The name we accept are:
-    // /filter/mediatype/k/{set}    where k is the media type we want.
-    // /filter/delete/{set}
-    @Override
-    public MediaObject createMediaObject(Path path) {
-        int matchType = mMatcher.match(path);
-        DataManager dataManager = mApplication.getDataManager();
-        switch (matchType) {
-            case FILTER_BY_MEDIATYPE: {
-                int mediaType = mMatcher.getIntVar(0);
-                String setsName = mMatcher.getVar(1);
-                MediaSet[] sets = dataManager.getMediaSetsFromString(setsName);
-                return new FilterTypeSet(path, dataManager, sets[0], mediaType);
-            }
-            case FILTER_BY_DELETE: {
-                String setsName = mMatcher.getVar(0);
-                MediaSet[] sets = dataManager.getMediaSetsFromString(setsName);
-                return new FilterDeleteSet(path, sets[0]);
-            }
-            case FILTER_BY_EMPTY: {
-                String setsName = mMatcher.getVar(0);
-                MediaSet[] sets = dataManager.getMediaSetsFromString(setsName);
-                return new FilterEmptyPromptSet(path, sets[0], mEmptyItem);
-            }
-            case FILTER_BY_EMPTY_ITEM: {
-                return mEmptyItem;
-            }
-            case FILTER_BY_CAMERA_SHORTCUT: {
-                return new SingleItemAlbum(path, mCameraShortcutItem);
-            }
-            case FILTER_BY_CAMERA_SHORTCUT_ITEM: {
-                return mCameraShortcutItem;
-            }
-            default:
-                throw new RuntimeException("bad path: " + path);
-        }
-    }
-}
diff --git a/src/com/android/gallery3d/data/FilterTypeSet.java b/src/com/android/gallery3d/data/FilterTypeSet.java
deleted file mode 100644
index 477ef73..0000000
--- a/src/com/android/gallery3d/data/FilterTypeSet.java
+++ /dev/null
@@ -1,137 +0,0 @@
-/*
- * Copyright (C) 2010 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.gallery3d.data;
-
-import java.util.ArrayList;
-
-// FilterTypeSet filters a base MediaSet according to a matching media type.
-public class FilterTypeSet extends MediaSet implements ContentListener {
-    @SuppressWarnings("unused")
-    private static final String TAG = "FilterTypeSet";
-
-    private final DataManager mDataManager;
-    private final MediaSet mBaseSet;
-    private final int mMediaType;
-    private final ArrayList<Path> mPaths = new ArrayList<Path>();
-    private final ArrayList<MediaSet> mAlbums = new ArrayList<MediaSet>();
-
-    public FilterTypeSet(Path path, DataManager dataManager, MediaSet baseSet,
-            int mediaType) {
-        super(path, INVALID_DATA_VERSION);
-        mDataManager = dataManager;
-        mBaseSet = baseSet;
-        mMediaType = mediaType;
-        mBaseSet.addContentListener(this);
-    }
-
-    @Override
-    public String getName() {
-        return mBaseSet.getName();
-    }
-
-    @Override
-    public MediaSet getSubMediaSet(int index) {
-        return mAlbums.get(index);
-    }
-
-    @Override
-    public int getSubMediaSetCount() {
-        return mAlbums.size();
-    }
-
-    @Override
-    public int getMediaItemCount() {
-        return mPaths.size();
-    }
-
-    @Override
-    public ArrayList<MediaItem> getMediaItem(int start, int count) {
-        return ClusterAlbum.getMediaItemFromPath(
-                mPaths, start, count, mDataManager);
-    }
-
-    @Override
-    public long reload() {
-        if (mBaseSet.reload() > mDataVersion) {
-            updateData();
-            mDataVersion = nextVersionNumber();
-        }
-        return mDataVersion;
-    }
-
-    @Override
-    public void onContentDirty() {
-        notifyContentChanged();
-    }
-
-    private void updateData() {
-        // Albums
-        mAlbums.clear();
-        String basePath = "/filter/mediatype/" + mMediaType;
-
-        for (int i = 0, n = mBaseSet.getSubMediaSetCount(); i < n; i++) {
-            MediaSet set = mBaseSet.getSubMediaSet(i);
-            String filteredPath = basePath + "/{" + set.getPath().toString() + "}";
-            MediaSet filteredSet = mDataManager.getMediaSet(filteredPath);
-            filteredSet.reload();
-            if (filteredSet.getMediaItemCount() > 0
-                    || filteredSet.getSubMediaSetCount() > 0) {
-                mAlbums.add(filteredSet);
-            }
-        }
-
-        // Items
-        mPaths.clear();
-        final int total = mBaseSet.getMediaItemCount();
-        final Path[] buf = new Path[total];
-
-        mBaseSet.enumerateMediaItems(new MediaSet.ItemConsumer() {
-            @Override
-            public void consume(int index, MediaItem item) {
-                if (item.getMediaType() == mMediaType) {
-                    if (index < 0 || index >= total) return;
-                    Path path = item.getPath();
-                    buf[index] = path;
-                }
-            }
-        });
-
-        for (int i = 0; i < total; i++) {
-            if (buf[i] != null) {
-                mPaths.add(buf[i]);
-            }
-        }
-    }
-
-    @Override
-    public int getSupportedOperations() {
-        return SUPPORT_SHARE | SUPPORT_DELETE;
-    }
-
-    @Override
-    public void delete() {
-        ItemConsumer consumer = new ItemConsumer() {
-            @Override
-            public void consume(int index, MediaItem item) {
-                if ((item.getSupportedOperations() & SUPPORT_DELETE) != 0) {
-                    item.delete();
-                }
-            }
-        };
-        mDataManager.mapMediaItems(mPaths, consumer, 0);
-    }
-}
diff --git a/src/com/android/gallery3d/data/ImageCacheRequest.java b/src/com/android/gallery3d/data/ImageCacheRequest.java
deleted file mode 100644
index 6cbc5c5..0000000
--- a/src/com/android/gallery3d/data/ImageCacheRequest.java
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- * Copyright (C) 2010 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.gallery3d.data;
-
-import android.graphics.Bitmap;
-import android.graphics.BitmapFactory;
-
-import com.android.gallery3d.app.GalleryApp;
-import com.android.gallery3d.common.BitmapUtils;
-import com.android.gallery3d.data.BytesBufferPool.BytesBuffer;
-import com.android.gallery3d.util.ThreadPool.Job;
-import com.android.gallery3d.util.ThreadPool.JobContext;
-
-abstract class ImageCacheRequest implements Job<Bitmap> {
-    private static final String TAG = "ImageCacheRequest";
-
-    protected GalleryApp mApplication;
-    private Path mPath;
-    private int mType;
-    private int mTargetSize;
-    private long mTimeModified;
-
-    public ImageCacheRequest(GalleryApp application,
-            Path path, long timeModified, int type, int targetSize) {
-        mApplication = application;
-        mPath = path;
-        mType = type;
-        mTargetSize = targetSize;
-        mTimeModified = timeModified;
-    }
-
-    private String debugTag() {
-        return mPath + "," + mTimeModified + "," +
-                ((mType == MediaItem.TYPE_THUMBNAIL) ? "THUMB" :
-                (mType == MediaItem.TYPE_MICROTHUMBNAIL) ? "MICROTHUMB" : "?");
-    }
-
-    @Override
-    public Bitmap run(JobContext jc) {
-        ImageCacheService cacheService = mApplication.getImageCacheService();
-
-        BytesBuffer buffer = MediaItem.getBytesBufferPool().get();
-        try {
-            boolean found = cacheService.getImageData(mPath, mTimeModified, mType, buffer);
-            if (jc.isCancelled()) return null;
-            if (found) {
-                BitmapFactory.Options options = new BitmapFactory.Options();
-                options.inPreferredConfig = Bitmap.Config.ARGB_8888;
-                Bitmap bitmap;
-                if (mType == MediaItem.TYPE_MICROTHUMBNAIL) {
-                    bitmap = DecodeUtils.decodeUsingPool(jc,
-                            buffer.data, buffer.offset, buffer.length, options);
-                } else {
-                    bitmap = DecodeUtils.decodeUsingPool(jc,
-                            buffer.data, buffer.offset, buffer.length, options);
-                }
-                if (bitmap == null && !jc.isCancelled()) {
-                    Log.w(TAG, "decode cached failed " + debugTag());
-                }
-                return bitmap;
-            }
-        } finally {
-            MediaItem.getBytesBufferPool().recycle(buffer);
-        }
-        Bitmap bitmap = onDecodeOriginal(jc, mType);
-        if (jc.isCancelled()) return null;
-
-        if (bitmap == null) {
-            Log.w(TAG, "decode orig failed " + debugTag());
-            return null;
-        }
-
-        if (mType == MediaItem.TYPE_MICROTHUMBNAIL) {
-            bitmap = BitmapUtils.resizeAndCropCenter(bitmap, mTargetSize, true);
-        } else {
-            bitmap = BitmapUtils.resizeDownBySideLength(bitmap, mTargetSize, true);
-        }
-        if (jc.isCancelled()) return null;
-
-        byte[] array = BitmapUtils.compressToBytes(bitmap);
-        if (jc.isCancelled()) return null;
-
-        cacheService.putImageData(mPath, mTimeModified, mType, array);
-        return bitmap;
-    }
-
-    public abstract Bitmap onDecodeOriginal(JobContext jc, int targetSize);
-}
diff --git a/src/com/android/gallery3d/data/ImageCacheService.java b/src/com/android/gallery3d/data/ImageCacheService.java
deleted file mode 100644
index 1c7cb8c..0000000
--- a/src/com/android/gallery3d/data/ImageCacheService.java
+++ /dev/null
@@ -1,123 +0,0 @@
-/*
- * Copyright (C) 2010 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.gallery3d.data;
-
-import android.content.Context;
-
-import com.android.gallery3d.common.BlobCache;
-import com.android.gallery3d.common.BlobCache.LookupRequest;
-import com.android.gallery3d.common.Utils;
-import com.android.gallery3d.data.BytesBufferPool.BytesBuffer;
-import com.android.gallery3d.util.CacheManager;
-import com.android.gallery3d.util.GalleryUtils;
-
-import java.io.IOException;
-import java.nio.ByteBuffer;
-
-public class ImageCacheService {
-    @SuppressWarnings("unused")
-    private static final String TAG = "ImageCacheService";
-
-    private static final String IMAGE_CACHE_FILE = "imgcache";
-    private static final int IMAGE_CACHE_MAX_ENTRIES = 5000;
-    private static final int IMAGE_CACHE_MAX_BYTES = 200 * 1024 * 1024;
-    private static final int IMAGE_CACHE_VERSION = 7;
-
-    private BlobCache mCache;
-
-    public ImageCacheService(Context context) {
-        mCache = CacheManager.getCache(context, IMAGE_CACHE_FILE,
-                IMAGE_CACHE_MAX_ENTRIES, IMAGE_CACHE_MAX_BYTES,
-                IMAGE_CACHE_VERSION);
-    }
-
-    /**
-     * Gets the cached image data for the given <code>path</code>,
-     *  <code>timeModified</code> and <code>type</code>.
-     *
-     * The image data will be stored in <code>buffer.data</code>, started from
-     * <code>buffer.offset</code> for <code>buffer.length</code> bytes. If the
-     * buffer.data is not big enough, a new byte array will be allocated and returned.
-     *
-     * @return true if the image data is found; false if not found.
-     */
-    public boolean getImageData(Path path, long timeModified, int type, BytesBuffer buffer) {
-        byte[] key = makeKey(path, timeModified, type);
-        long cacheKey = Utils.crc64Long(key);
-        try {
-            LookupRequest request = new LookupRequest();
-            request.key = cacheKey;
-            request.buffer = buffer.data;
-            synchronized (mCache) {
-                if (!mCache.lookup(request)) return false;
-            }
-            if (isSameKey(key, request.buffer)) {
-                buffer.data = request.buffer;
-                buffer.offset = key.length;
-                buffer.length = request.length - buffer.offset;
-                return true;
-            }
-        } catch (IOException ex) {
-            // ignore.
-        }
-        return false;
-    }
-
-    public void putImageData(Path path, long timeModified, int type, byte[] value) {
-        byte[] key = makeKey(path, timeModified, type);
-        long cacheKey = Utils.crc64Long(key);
-        ByteBuffer buffer = ByteBuffer.allocate(key.length + value.length);
-        buffer.put(key);
-        buffer.put(value);
-        synchronized (mCache) {
-            try {
-                mCache.insert(cacheKey, buffer.array());
-            } catch (IOException ex) {
-                // ignore.
-            }
-        }
-    }
-
-    public void clearImageData(Path path, long timeModified, int type) {
-        byte[] key = makeKey(path, timeModified, type);
-        long cacheKey = Utils.crc64Long(key);
-        synchronized (mCache) {
-            try {
-                mCache.clearEntry(cacheKey);
-            } catch (IOException ex) {
-                // ignore.
-            }
-        }
-    }
-
-    private static byte[] makeKey(Path path, long timeModified, int type) {
-        return GalleryUtils.getBytes(path.toString() + "+" + timeModified + "+" + type);
-    }
-
-    private static boolean isSameKey(byte[] key, byte[] buffer) {
-        int n = key.length;
-        if (buffer.length < n) {
-            return false;
-        }
-        for (int i = 0; i < n; ++i) {
-            if (key[i] != buffer[i]) {
-                return false;
-            }
-        }
-        return true;
-    }
-}
diff --git a/src/com/android/gallery3d/data/LocalAlbum.java b/src/com/android/gallery3d/data/LocalAlbum.java
deleted file mode 100644
index 7b7015a..0000000
--- a/src/com/android/gallery3d/data/LocalAlbum.java
+++ /dev/null
@@ -1,325 +0,0 @@
-/*
- * Copyright (C) 2010 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.gallery3d.data;
-
-import android.content.ContentResolver;
-import android.content.res.Resources;
-import android.database.Cursor;
-import android.net.Uri;
-import android.os.Environment;
-import android.provider.MediaStore;
-import android.provider.MediaStore.Images;
-import android.provider.MediaStore.Images.ImageColumns;
-import android.provider.MediaStore.Video;
-import android.provider.MediaStore.Video.VideoColumns;
-
-import com.android.gallery3d.R;
-import com.android.gallery3d.app.GalleryApp;
-import com.android.gallery3d.common.Utils;
-import com.android.gallery3d.util.BucketNames;
-import com.android.gallery3d.util.GalleryUtils;
-import com.android.gallery3d.util.MediaSetUtils;
-
-import java.io.File;
-import java.util.ArrayList;
-
-// LocalAlbumSet lists all media items in one bucket on local storage.
-// The media items need to be all images or all videos, but not both.
-public class LocalAlbum extends MediaSet {
-    private static final String TAG = "LocalAlbum";
-    private static final String[] COUNT_PROJECTION = { "count(*)" };
-
-    private static final int INVALID_COUNT = -1;
-    private final String mWhereClause;
-    private final String mOrderClause;
-    private final Uri mBaseUri;
-    private final String[] mProjection;
-
-    private final GalleryApp mApplication;
-    private final ContentResolver mResolver;
-    private final int mBucketId;
-    private final String mName;
-    private final boolean mIsImage;
-    private final ChangeNotifier mNotifier;
-    private final Path mItemPath;
-    private int mCachedCount = INVALID_COUNT;
-
-    public LocalAlbum(Path path, GalleryApp application, int bucketId,
-            boolean isImage, String name) {
-        super(path, nextVersionNumber());
-        mApplication = application;
-        mResolver = application.getContentResolver();
-        mBucketId = bucketId;
-        mName = name;
-        mIsImage = isImage;
-
-        if (isImage) {
-            mWhereClause = ImageColumns.BUCKET_ID + " = ?";
-            mOrderClause = ImageColumns.DATE_TAKEN + " DESC, "
-                    + ImageColumns._ID + " DESC";
-            mBaseUri = Images.Media.EXTERNAL_CONTENT_URI;
-            mProjection = LocalImage.PROJECTION;
-            mItemPath = LocalImage.ITEM_PATH;
-        } else {
-            mWhereClause = VideoColumns.BUCKET_ID + " = ?";
-            mOrderClause = VideoColumns.DATE_TAKEN + " DESC, "
-                    + VideoColumns._ID + " DESC";
-            mBaseUri = Video.Media.EXTERNAL_CONTENT_URI;
-            mProjection = LocalVideo.PROJECTION;
-            mItemPath = LocalVideo.ITEM_PATH;
-        }
-
-        mNotifier = new ChangeNotifier(this, mBaseUri, application);
-    }
-
-    public LocalAlbum(Path path, GalleryApp application, int bucketId,
-            boolean isImage) {
-        this(path, application, bucketId, isImage,
-                BucketHelper.getBucketName(
-                application.getContentResolver(), bucketId));
-    }
-
-    @Override
-    public boolean isCameraRoll() {
-        return mBucketId == MediaSetUtils.CAMERA_BUCKET_ID;
-    }
-
-    @Override
-    public Uri getContentUri() {
-        if (mIsImage) {
-            return MediaStore.Images.Media.EXTERNAL_CONTENT_URI.buildUpon()
-                    .appendQueryParameter(LocalSource.KEY_BUCKET_ID,
-                            String.valueOf(mBucketId)).build();
-        } else {
-            return MediaStore.Video.Media.EXTERNAL_CONTENT_URI.buildUpon()
-                    .appendQueryParameter(LocalSource.KEY_BUCKET_ID,
-                            String.valueOf(mBucketId)).build();
-        }
-    }
-
-    @Override
-    public ArrayList<MediaItem> getMediaItem(int start, int count) {
-        DataManager dataManager = mApplication.getDataManager();
-        Uri uri = mBaseUri.buildUpon()
-                .appendQueryParameter("limit", start + "," + count).build();
-        ArrayList<MediaItem> list = new ArrayList<MediaItem>();
-        GalleryUtils.assertNotInRenderThread();
-        Cursor cursor = mResolver.query(
-                uri, mProjection, mWhereClause,
-                new String[]{String.valueOf(mBucketId)},
-                mOrderClause);
-        if (cursor == null) {
-            Log.w(TAG, "query fail: " + uri);
-            return list;
-        }
-
-        try {
-            while (cursor.moveToNext()) {
-                int id = cursor.getInt(0);  // _id must be in the first column
-                Path childPath = mItemPath.getChild(id);
-                MediaItem item = loadOrUpdateItem(childPath, cursor,
-                        dataManager, mApplication, mIsImage);
-                list.add(item);
-            }
-        } finally {
-            cursor.close();
-        }
-        return list;
-    }
-
-    private static MediaItem loadOrUpdateItem(Path path, Cursor cursor,
-            DataManager dataManager, GalleryApp app, boolean isImage) {
-        synchronized (DataManager.LOCK) {
-            LocalMediaItem item = (LocalMediaItem) dataManager.peekMediaObject(path);
-            if (item == null) {
-                if (isImage) {
-                    item = new LocalImage(path, app, cursor);
-                } else {
-                    item = new LocalVideo(path, app, cursor);
-                }
-            } else {
-                item.updateContent(cursor);
-            }
-            return item;
-        }
-    }
-
-    // The pids array are sorted by the (path) id.
-    public static MediaItem[] getMediaItemById(
-            GalleryApp application, boolean isImage, ArrayList<Integer> ids) {
-        // get the lower and upper bound of (path) id
-        MediaItem[] result = new MediaItem[ids.size()];
-        if (ids.isEmpty()) return result;
-        int idLow = ids.get(0);
-        int idHigh = ids.get(ids.size() - 1);
-
-        // prepare the query parameters
-        Uri baseUri;
-        String[] projection;
-        Path itemPath;
-        if (isImage) {
-            baseUri = Images.Media.EXTERNAL_CONTENT_URI;
-            projection = LocalImage.PROJECTION;
-            itemPath = LocalImage.ITEM_PATH;
-        } else {
-            baseUri = Video.Media.EXTERNAL_CONTENT_URI;
-            projection = LocalVideo.PROJECTION;
-            itemPath = LocalVideo.ITEM_PATH;
-        }
-
-        ContentResolver resolver = application.getContentResolver();
-        DataManager dataManager = application.getDataManager();
-        Cursor cursor = resolver.query(baseUri, projection, "_id BETWEEN ? AND ?",
-                new String[]{String.valueOf(idLow), String.valueOf(idHigh)},
-                "_id");
-        if (cursor == null) {
-            Log.w(TAG, "query fail" + baseUri);
-            return result;
-        }
-        try {
-            int n = ids.size();
-            int i = 0;
-
-            while (i < n && cursor.moveToNext()) {
-                int id = cursor.getInt(0);  // _id must be in the first column
-
-                // Match id with the one on the ids list.
-                if (ids.get(i) > id) {
-                    continue;
-                }
-
-                while (ids.get(i) < id) {
-                    if (++i >= n) {
-                        return result;
-                    }
-                }
-
-                Path childPath = itemPath.getChild(id);
-                MediaItem item = loadOrUpdateItem(childPath, cursor, dataManager,
-                        application, isImage);
-                result[i] = item;
-                ++i;
-            }
-            return result;
-        } finally {
-            cursor.close();
-        }
-    }
-
-    public static Cursor getItemCursor(ContentResolver resolver, Uri uri,
-            String[] projection, int id) {
-        return resolver.query(uri, projection, "_id=?",
-                new String[]{String.valueOf(id)}, null);
-    }
-
-    @Override
-    public int getMediaItemCount() {
-        if (mCachedCount == INVALID_COUNT) {
-            Cursor cursor = mResolver.query(
-                    mBaseUri, COUNT_PROJECTION, mWhereClause,
-                    new String[]{String.valueOf(mBucketId)}, null);
-            if (cursor == null) {
-                Log.w(TAG, "query fail");
-                return 0;
-            }
-            try {
-                Utils.assertTrue(cursor.moveToNext());
-                mCachedCount = cursor.getInt(0);
-            } finally {
-                cursor.close();
-            }
-        }
-        return mCachedCount;
-    }
-
-    @Override
-    public String getName() {
-        return getLocalizedName(mApplication.getResources(), mBucketId, mName);
-    }
-
-    @Override
-    public long reload() {
-        if (mNotifier.isDirty()) {
-            mDataVersion = nextVersionNumber();
-            mCachedCount = INVALID_COUNT;
-        }
-        return mDataVersion;
-    }
-
-    @Override
-    public int getSupportedOperations() {
-        return SUPPORT_DELETE | SUPPORT_SHARE | SUPPORT_INFO;
-    }
-
-    @Override
-    public void delete() {
-        GalleryUtils.assertNotInRenderThread();
-        mResolver.delete(mBaseUri, mWhereClause,
-                new String[]{String.valueOf(mBucketId)});
-    }
-
-    @Override
-    public boolean isLeafAlbum() {
-        return true;
-    }
-
-    public static String getLocalizedName(Resources res, int bucketId,
-            String name) {
-        if (bucketId == MediaSetUtils.CAMERA_BUCKET_ID) {
-            return res.getString(R.string.folder_camera);
-        } else if (bucketId == MediaSetUtils.DOWNLOAD_BUCKET_ID) {
-            return res.getString(R.string.folder_download);
-        } else if (bucketId == MediaSetUtils.IMPORTED_BUCKET_ID) {
-            return res.getString(R.string.folder_imported);
-        } else if (bucketId == MediaSetUtils.SNAPSHOT_BUCKET_ID) {
-            return res.getString(R.string.folder_screenshot);
-        } else if (bucketId == MediaSetUtils.EDITED_ONLINE_PHOTOS_BUCKET_ID) {
-            return res.getString(R.string.folder_edited_online_photos);
-        } else {
-            return name;
-        }
-    }
-
-    // Relative path is the absolute path minus external storage path
-    public static String getRelativePath(int bucketId) {
-        String relativePath = "/";
-        if (bucketId == MediaSetUtils.CAMERA_BUCKET_ID) {
-            relativePath += BucketNames.CAMERA;
-        } else if (bucketId == MediaSetUtils.DOWNLOAD_BUCKET_ID) {
-            relativePath += BucketNames.DOWNLOAD;
-        } else if (bucketId == MediaSetUtils.IMPORTED_BUCKET_ID) {
-            relativePath += BucketNames.IMPORTED;
-        } else if (bucketId == MediaSetUtils.SNAPSHOT_BUCKET_ID) {
-            relativePath += BucketNames.SCREENSHOTS;
-        } else if (bucketId == MediaSetUtils.EDITED_ONLINE_PHOTOS_BUCKET_ID) {
-            relativePath += BucketNames.EDITED_ONLINE_PHOTOS;
-        } else {
-            // If the first few cases didn't hit the matching path, do a
-            // thorough search in the local directories.
-            File extStorage = Environment.getExternalStorageDirectory();
-            String path = GalleryUtils.searchDirForPath(extStorage, bucketId);
-            if (path == null) {
-                Log.w(TAG, "Relative path for bucket id: " + bucketId + " is not found.");
-                relativePath = null;
-            } else {
-                relativePath = path.substring(extStorage.getAbsolutePath().length());
-            }
-        }
-        return relativePath;
-    }
-
-}
diff --git a/src/com/android/gallery3d/data/LocalAlbumSet.java b/src/com/android/gallery3d/data/LocalAlbumSet.java
deleted file mode 100644
index b2b4b8c..0000000
--- a/src/com/android/gallery3d/data/LocalAlbumSet.java
+++ /dev/null
@@ -1,211 +0,0 @@
-/*
- * Copyright (C) 2010 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.gallery3d.data;
-
-import android.net.Uri;
-import android.os.Handler;
-import android.provider.MediaStore.Images;
-import android.provider.MediaStore.Video;
-
-import com.android.gallery3d.R;
-import com.android.gallery3d.app.GalleryApp;
-import com.android.gallery3d.data.BucketHelper.BucketEntry;
-import com.android.gallery3d.util.Future;
-import com.android.gallery3d.util.FutureListener;
-import com.android.gallery3d.util.MediaSetUtils;
-import com.android.gallery3d.util.ThreadPool;
-import com.android.gallery3d.util.ThreadPool.JobContext;
-
-import java.util.ArrayList;
-import java.util.Comparator;
-
-// LocalAlbumSet lists all image or video albums in the local storage.
-// The path should be "/local/image", "local/video" or "/local/all"
-public class LocalAlbumSet extends MediaSet
-        implements FutureListener<ArrayList<MediaSet>> {
-    @SuppressWarnings("unused")
-    private static final String TAG = "LocalAlbumSet";
-
-    public static final Path PATH_ALL = Path.fromString("/local/all");
-    public static final Path PATH_IMAGE = Path.fromString("/local/image");
-    public static final Path PATH_VIDEO = Path.fromString("/local/video");
-
-    private static final Uri[] mWatchUris =
-        {Images.Media.EXTERNAL_CONTENT_URI, Video.Media.EXTERNAL_CONTENT_URI};
-
-    private final GalleryApp mApplication;
-    private final int mType;
-    private ArrayList<MediaSet> mAlbums = new ArrayList<MediaSet>();
-    private final ChangeNotifier mNotifier;
-    private final String mName;
-    private final Handler mHandler;
-    private boolean mIsLoading;
-
-    private Future<ArrayList<MediaSet>> mLoadTask;
-    private ArrayList<MediaSet> mLoadBuffer;
-
-    public LocalAlbumSet(Path path, GalleryApp application) {
-        super(path, nextVersionNumber());
-        mApplication = application;
-        mHandler = new Handler(application.getMainLooper());
-        mType = getTypeFromPath(path);
-        mNotifier = new ChangeNotifier(this, mWatchUris, application);
-        mName = application.getResources().getString(
-                R.string.set_label_local_albums);
-    }
-
-    private static int getTypeFromPath(Path path) {
-        String name[] = path.split();
-        if (name.length < 2) {
-            throw new IllegalArgumentException(path.toString());
-        }
-        return getTypeFromString(name[1]);
-    }
-
-    @Override
-    public MediaSet getSubMediaSet(int index) {
-        return mAlbums.get(index);
-    }
-
-    @Override
-    public int getSubMediaSetCount() {
-        return mAlbums.size();
-    }
-
-    @Override
-    public String getName() {
-        return mName;
-    }
-
-    private static int findBucket(BucketEntry entries[], int bucketId) {
-        for (int i = 0, n = entries.length; i < n; ++i) {
-            if (entries[i].bucketId == bucketId) return i;
-        }
-        return -1;
-    }
-
-    private class AlbumsLoader implements ThreadPool.Job<ArrayList<MediaSet>> {
-
-        @Override
-        @SuppressWarnings("unchecked")
-        public ArrayList<MediaSet> run(JobContext jc) {
-            // Note: it will be faster if we only select media_type and bucket_id.
-            //       need to test the performance if that is worth
-            BucketEntry[] entries = BucketHelper.loadBucketEntries(
-                    jc, mApplication.getContentResolver(), mType);
-
-            if (jc.isCancelled()) return null;
-
-            int offset = 0;
-            // Move camera and download bucket to the front, while keeping the
-            // order of others.
-            int index = findBucket(entries, MediaSetUtils.CAMERA_BUCKET_ID);
-            if (index != -1) {
-                circularShiftRight(entries, offset++, index);
-            }
-            index = findBucket(entries, MediaSetUtils.DOWNLOAD_BUCKET_ID);
-            if (index != -1) {
-                circularShiftRight(entries, offset++, index);
-            }
-
-            ArrayList<MediaSet> albums = new ArrayList<MediaSet>();
-            DataManager dataManager = mApplication.getDataManager();
-            for (BucketEntry entry : entries) {
-                MediaSet album = getLocalAlbum(dataManager,
-                        mType, mPath, entry.bucketId, entry.bucketName);
-                albums.add(album);
-            }
-            return albums;
-        }
-    }
-
-    private MediaSet getLocalAlbum(
-            DataManager manager, int type, Path parent, int id, String name) {
-        synchronized (DataManager.LOCK) {
-            Path path = parent.getChild(id);
-            MediaObject object = manager.peekMediaObject(path);
-            if (object != null) return (MediaSet) object;
-            switch (type) {
-                case MEDIA_TYPE_IMAGE:
-                    return new LocalAlbum(path, mApplication, id, true, name);
-                case MEDIA_TYPE_VIDEO:
-                    return new LocalAlbum(path, mApplication, id, false, name);
-                case MEDIA_TYPE_ALL:
-                    Comparator<MediaItem> comp = DataManager.sDateTakenComparator;
-                    return new LocalMergeAlbum(path, comp, new MediaSet[] {
-                            getLocalAlbum(manager, MEDIA_TYPE_IMAGE, PATH_IMAGE, id, name),
-                            getLocalAlbum(manager, MEDIA_TYPE_VIDEO, PATH_VIDEO, id, name)}, id);
-            }
-            throw new IllegalArgumentException(String.valueOf(type));
-        }
-    }
-
-    @Override
-    public synchronized boolean isLoading() {
-        return mIsLoading;
-    }
-
-    @Override
-    // synchronized on this function for
-    //   1. Prevent calling reload() concurrently.
-    //   2. Prevent calling onFutureDone() and reload() concurrently
-    public synchronized long reload() {
-        if (mNotifier.isDirty()) {
-            if (mLoadTask != null) mLoadTask.cancel();
-            mIsLoading = true;
-            mLoadTask = mApplication.getThreadPool().submit(new AlbumsLoader(), this);
-        }
-        if (mLoadBuffer != null) {
-            mAlbums = mLoadBuffer;
-            mLoadBuffer = null;
-            for (MediaSet album : mAlbums) {
-                album.reload();
-            }
-            mDataVersion = nextVersionNumber();
-        }
-        return mDataVersion;
-    }
-
-    @Override
-    public synchronized void onFutureDone(Future<ArrayList<MediaSet>> future) {
-        if (mLoadTask != future) return; // ignore, wait for the latest task
-        mLoadBuffer = future.get();
-        mIsLoading = false;
-        if (mLoadBuffer == null) mLoadBuffer = new ArrayList<MediaSet>();
-        mHandler.post(new Runnable() {
-            @Override
-            public void run() {
-                notifyContentChanged();
-            }
-        });
-    }
-
-    // For debug only. Fake there is a ContentObserver.onChange() event.
-    void fakeChange() {
-        mNotifier.fakeChange();
-    }
-
-    // Circular shift the array range from a[i] to a[j] (inclusive). That is,
-    // a[i] -> a[i+1] -> a[i+2] -> ... -> a[j], and a[j] -> a[i]
-    private static <T> void circularShiftRight(T[] array, int i, int j) {
-        T temp = array[j];
-        for (int k = j; k > i; k--) {
-            array[k] = array[k - 1];
-        }
-        array[i] = temp;
-    }
-}
diff --git a/src/com/android/gallery3d/data/LocalImage.java b/src/com/android/gallery3d/data/LocalImage.java
deleted file mode 100644
index cc70dd4..0000000
--- a/src/com/android/gallery3d/data/LocalImage.java
+++ /dev/null
@@ -1,355 +0,0 @@
-/*
- * Copyright (C) 2010 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.gallery3d.data;
-
-import android.annotation.TargetApi;
-import android.content.ContentResolver;
-import android.content.ContentValues;
-import android.database.Cursor;
-import android.graphics.Bitmap;
-import android.graphics.BitmapFactory;
-import android.graphics.BitmapRegionDecoder;
-import android.net.Uri;
-import android.os.Build;
-import android.provider.MediaStore.Images;
-import android.provider.MediaStore.Images.ImageColumns;
-import android.provider.MediaStore.MediaColumns;
-import android.util.Log;
-
-import com.android.gallery3d.app.GalleryApp;
-import com.android.gallery3d.app.PanoramaMetadataSupport;
-import com.android.gallery3d.app.StitchingProgressManager;
-import com.android.gallery3d.common.ApiHelper;
-import com.android.gallery3d.common.BitmapUtils;
-import com.android.gallery3d.exif.ExifInterface;
-import com.android.gallery3d.exif.ExifTag;
-import com.android.gallery3d.filtershow.tools.SaveImage;
-import com.android.gallery3d.util.GalleryUtils;
-import com.android.gallery3d.util.ThreadPool.Job;
-import com.android.gallery3d.util.ThreadPool.JobContext;
-import com.android.gallery3d.util.UpdateHelper;
-
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.IOException;
-
-// LocalImage represents an image in the local storage.
-public class LocalImage extends LocalMediaItem {
-    private static final String TAG = "LocalImage";
-
-    static final Path ITEM_PATH = Path.fromString("/local/image/item");
-
-    // Must preserve order between these indices and the order of the terms in
-    // the following PROJECTION array.
-    private static final int INDEX_ID = 0;
-    private static final int INDEX_CAPTION = 1;
-    private static final int INDEX_MIME_TYPE = 2;
-    private static final int INDEX_LATITUDE = 3;
-    private static final int INDEX_LONGITUDE = 4;
-    private static final int INDEX_DATE_TAKEN = 5;
-    private static final int INDEX_DATE_ADDED = 6;
-    private static final int INDEX_DATE_MODIFIED = 7;
-    private static final int INDEX_DATA = 8;
-    private static final int INDEX_ORIENTATION = 9;
-    private static final int INDEX_BUCKET_ID = 10;
-    private static final int INDEX_SIZE = 11;
-    private static final int INDEX_WIDTH = 12;
-    private static final int INDEX_HEIGHT = 13;
-
-    static final String[] PROJECTION =  {
-            ImageColumns._ID,           // 0
-            ImageColumns.TITLE,         // 1
-            ImageColumns.MIME_TYPE,     // 2
-            ImageColumns.LATITUDE,      // 3
-            ImageColumns.LONGITUDE,     // 4
-            ImageColumns.DATE_TAKEN,    // 5
-            ImageColumns.DATE_ADDED,    // 6
-            ImageColumns.DATE_MODIFIED, // 7
-            ImageColumns.DATA,          // 8
-            ImageColumns.ORIENTATION,   // 9
-            ImageColumns.BUCKET_ID,     // 10
-            ImageColumns.SIZE,          // 11
-            "0",                        // 12
-            "0"                         // 13
-    };
-
-    static {
-        updateWidthAndHeightProjection();
-    }
-
-    @TargetApi(Build.VERSION_CODES.JELLY_BEAN)
-    private static void updateWidthAndHeightProjection() {
-        if (ApiHelper.HAS_MEDIA_COLUMNS_WIDTH_AND_HEIGHT) {
-            PROJECTION[INDEX_WIDTH] = MediaColumns.WIDTH;
-            PROJECTION[INDEX_HEIGHT] = MediaColumns.HEIGHT;
-        }
-    }
-
-    private final GalleryApp mApplication;
-
-    public int rotation;
-
-    private PanoramaMetadataSupport mPanoramaMetadata = new PanoramaMetadataSupport(this);
-
-    public LocalImage(Path path, GalleryApp application, Cursor cursor) {
-        super(path, nextVersionNumber());
-        mApplication = application;
-        loadFromCursor(cursor);
-    }
-
-    public LocalImage(Path path, GalleryApp application, int id) {
-        super(path, nextVersionNumber());
-        mApplication = application;
-        ContentResolver resolver = mApplication.getContentResolver();
-        Uri uri = Images.Media.EXTERNAL_CONTENT_URI;
-        Cursor cursor = LocalAlbum.getItemCursor(resolver, uri, PROJECTION, id);
-        if (cursor == null) {
-            throw new RuntimeException("cannot get cursor for: " + path);
-        }
-        try {
-            if (cursor.moveToNext()) {
-                loadFromCursor(cursor);
-            } else {
-                throw new RuntimeException("cannot find data for: " + path);
-            }
-        } finally {
-            cursor.close();
-        }
-    }
-
-    private void loadFromCursor(Cursor cursor) {
-        id = cursor.getInt(INDEX_ID);
-        caption = cursor.getString(INDEX_CAPTION);
-        mimeType = cursor.getString(INDEX_MIME_TYPE);
-        latitude = cursor.getDouble(INDEX_LATITUDE);
-        longitude = cursor.getDouble(INDEX_LONGITUDE);
-        dateTakenInMs = cursor.getLong(INDEX_DATE_TAKEN);
-        dateAddedInSec = cursor.getLong(INDEX_DATE_ADDED);
-        dateModifiedInSec = cursor.getLong(INDEX_DATE_MODIFIED);
-        filePath = cursor.getString(INDEX_DATA);
-        rotation = cursor.getInt(INDEX_ORIENTATION);
-        bucketId = cursor.getInt(INDEX_BUCKET_ID);
-        fileSize = cursor.getLong(INDEX_SIZE);
-        width = cursor.getInt(INDEX_WIDTH);
-        height = cursor.getInt(INDEX_HEIGHT);
-    }
-
-    @Override
-    protected boolean updateFromCursor(Cursor cursor) {
-        UpdateHelper uh = new UpdateHelper();
-        id = uh.update(id, cursor.getInt(INDEX_ID));
-        caption = uh.update(caption, cursor.getString(INDEX_CAPTION));
-        mimeType = uh.update(mimeType, cursor.getString(INDEX_MIME_TYPE));
-        latitude = uh.update(latitude, cursor.getDouble(INDEX_LATITUDE));
-        longitude = uh.update(longitude, cursor.getDouble(INDEX_LONGITUDE));
-        dateTakenInMs = uh.update(
-                dateTakenInMs, cursor.getLong(INDEX_DATE_TAKEN));
-        dateAddedInSec = uh.update(
-                dateAddedInSec, cursor.getLong(INDEX_DATE_ADDED));
-        dateModifiedInSec = uh.update(
-                dateModifiedInSec, cursor.getLong(INDEX_DATE_MODIFIED));
-        filePath = uh.update(filePath, cursor.getString(INDEX_DATA));
-        rotation = uh.update(rotation, cursor.getInt(INDEX_ORIENTATION));
-        bucketId = uh.update(bucketId, cursor.getInt(INDEX_BUCKET_ID));
-        fileSize = uh.update(fileSize, cursor.getLong(INDEX_SIZE));
-        width = uh.update(width, cursor.getInt(INDEX_WIDTH));
-        height = uh.update(height, cursor.getInt(INDEX_HEIGHT));
-        return uh.isUpdated();
-    }
-
-    @Override
-    public Job<Bitmap> requestImage(int type) {
-        return new LocalImageRequest(mApplication, mPath, dateModifiedInSec,
-                type, filePath);
-    }
-
-    public static class LocalImageRequest extends ImageCacheRequest {
-        private String mLocalFilePath;
-
-        LocalImageRequest(GalleryApp application, Path path, long timeModified,
-                int type, String localFilePath) {
-            super(application, path, timeModified, type,
-                    MediaItem.getTargetSize(type));
-            mLocalFilePath = localFilePath;
-        }
-
-        @Override
-        public Bitmap onDecodeOriginal(JobContext jc, final int type) {
-            BitmapFactory.Options options = new BitmapFactory.Options();
-            options.inPreferredConfig = Bitmap.Config.ARGB_8888;
-            int targetSize = MediaItem.getTargetSize(type);
-
-            // try to decode from JPEG EXIF
-            if (type == MediaItem.TYPE_MICROTHUMBNAIL) {
-                ExifInterface exif = new ExifInterface();
-                byte[] thumbData = null;
-                try {
-                    exif.readExif(mLocalFilePath);
-                    thumbData = exif.getThumbnail();
-                } catch (FileNotFoundException e) {
-                    Log.w(TAG, "failed to find file to read thumbnail: " + mLocalFilePath);
-                } catch (IOException e) {
-                    Log.w(TAG, "failed to get thumbnail from: " + mLocalFilePath);
-                }
-                if (thumbData != null) {
-                    Bitmap bitmap = DecodeUtils.decodeIfBigEnough(
-                            jc, thumbData, options, targetSize);
-                    if (bitmap != null) return bitmap;
-                }
-            }
-
-            return DecodeUtils.decodeThumbnail(jc, mLocalFilePath, options, targetSize, type);
-        }
-    }
-
-    @Override
-    public Job<BitmapRegionDecoder> requestLargeImage() {
-        return new LocalLargeImageRequest(filePath);
-    }
-
-    public static class LocalLargeImageRequest
-            implements Job<BitmapRegionDecoder> {
-        String mLocalFilePath;
-
-        public LocalLargeImageRequest(String localFilePath) {
-            mLocalFilePath = localFilePath;
-        }
-
-        @Override
-        public BitmapRegionDecoder run(JobContext jc) {
-            return DecodeUtils.createBitmapRegionDecoder(jc, mLocalFilePath, false);
-        }
-    }
-
-    @Override
-    public int getSupportedOperations() {
-        StitchingProgressManager progressManager = mApplication.getStitchingProgressManager();
-        if (progressManager != null && progressManager.getProgress(getContentUri()) != null) {
-            return 0; // doesn't support anything while stitching!
-        }
-        int operation = SUPPORT_DELETE | SUPPORT_SHARE | SUPPORT_CROP
-                | SUPPORT_SETAS | SUPPORT_EDIT | SUPPORT_INFO;
-        if (BitmapUtils.isSupportedByRegionDecoder(mimeType)) {
-            operation |= SUPPORT_FULL_IMAGE;
-        }
-
-        if (BitmapUtils.isRotationSupported(mimeType)) {
-            operation |= SUPPORT_ROTATE;
-        }
-
-        if (GalleryUtils.isValidLocation(latitude, longitude)) {
-            operation |= SUPPORT_SHOW_ON_MAP;
-        }
-        return operation;
-    }
-
-    @Override
-    public void getPanoramaSupport(PanoramaSupportCallback callback) {
-        mPanoramaMetadata.getPanoramaSupport(mApplication, callback);
-    }
-
-    @Override
-    public void clearCachedPanoramaSupport() {
-        mPanoramaMetadata.clearCachedValues();
-    }
-
-    @Override
-    public void delete() {
-        GalleryUtils.assertNotInRenderThread();
-        Uri baseUri = Images.Media.EXTERNAL_CONTENT_URI;
-        ContentResolver contentResolver = mApplication.getContentResolver();
-        SaveImage.deleteAuxFiles(contentResolver, getContentUri());
-        contentResolver.delete(baseUri, "_id=?",
-                new String[]{String.valueOf(id)});
-    }
-
-    @Override
-    public void rotate(int degrees) {
-        GalleryUtils.assertNotInRenderThread();
-        Uri baseUri = Images.Media.EXTERNAL_CONTENT_URI;
-        ContentValues values = new ContentValues();
-        int rotation = (this.rotation + degrees) % 360;
-        if (rotation < 0) rotation += 360;
-
-        if (mimeType.equalsIgnoreCase("image/jpeg")) {
-            ExifInterface exifInterface = new ExifInterface();
-            ExifTag tag = exifInterface.buildTag(ExifInterface.TAG_ORIENTATION,
-                    ExifInterface.getOrientationValueForRotation(rotation));
-            if(tag != null) {
-                exifInterface.setTag(tag);
-                try {
-                    exifInterface.forceRewriteExif(filePath);
-                    fileSize = new File(filePath).length();
-                    values.put(Images.Media.SIZE, fileSize);
-                } catch (FileNotFoundException e) {
-                    Log.w(TAG, "cannot find file to set exif: " + filePath);
-                } catch (IOException e) {
-                    Log.w(TAG, "cannot set exif data: " + filePath);
-                }
-            } else {
-                Log.w(TAG, "Could not build tag: " + ExifInterface.TAG_ORIENTATION);
-            }
-        }
-
-        values.put(Images.Media.ORIENTATION, rotation);
-        mApplication.getContentResolver().update(baseUri, values, "_id=?",
-                new String[]{String.valueOf(id)});
-    }
-
-    @Override
-    public Uri getContentUri() {
-        Uri baseUri = Images.Media.EXTERNAL_CONTENT_URI;
-        return baseUri.buildUpon().appendPath(String.valueOf(id)).build();
-    }
-
-    @Override
-    public int getMediaType() {
-        return MEDIA_TYPE_IMAGE;
-    }
-
-    @Override
-    public MediaDetails getDetails() {
-        MediaDetails details = super.getDetails();
-        details.addDetail(MediaDetails.INDEX_ORIENTATION, Integer.valueOf(rotation));
-        if (MIME_TYPE_JPEG.equals(mimeType)) {
-            // ExifInterface returns incorrect values for photos in other format.
-            // For example, the width and height of an webp images is always '0'.
-            MediaDetails.extractExifInfo(details, filePath);
-        }
-        return details;
-    }
-
-    @Override
-    public int getRotation() {
-        return rotation;
-    }
-
-    @Override
-    public int getWidth() {
-        return width;
-    }
-
-    @Override
-    public int getHeight() {
-        return height;
-    }
-
-    @Override
-    public String getFilePath() {
-        return filePath;
-    }
-}
diff --git a/src/com/android/gallery3d/data/LocalMediaItem.java b/src/com/android/gallery3d/data/LocalMediaItem.java
deleted file mode 100644
index 7e003cd..0000000
--- a/src/com/android/gallery3d/data/LocalMediaItem.java
+++ /dev/null
@@ -1,109 +0,0 @@
-/*
- * Copyright (C) 2010 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.gallery3d.data;
-
-import android.database.Cursor;
-
-import com.android.gallery3d.util.GalleryUtils;
-
-import java.text.DateFormat;
-import java.util.Date;
-
-//
-// LocalMediaItem is an abstract class captures those common fields
-// in LocalImage and LocalVideo.
-//
-public abstract class LocalMediaItem extends MediaItem {
-
-    @SuppressWarnings("unused")
-    private static final String TAG = "LocalMediaItem";
-
-    // database fields
-    public int id;
-    public String caption;
-    public String mimeType;
-    public long fileSize;
-    public double latitude = INVALID_LATLNG;
-    public double longitude = INVALID_LATLNG;
-    public long dateTakenInMs;
-    public long dateAddedInSec;
-    public long dateModifiedInSec;
-    public String filePath;
-    public int bucketId;
-    public int width;
-    public int height;
-
-    public LocalMediaItem(Path path, long version) {
-        super(path, version);
-    }
-
-    @Override
-    public long getDateInMs() {
-        return dateTakenInMs;
-    }
-
-    @Override
-    public String getName() {
-        return caption;
-    }
-
-    @Override
-    public void getLatLong(double[] latLong) {
-        latLong[0] = latitude;
-        latLong[1] = longitude;
-    }
-
-    abstract protected boolean updateFromCursor(Cursor cursor);
-
-    public int getBucketId() {
-        return bucketId;
-    }
-
-    protected void updateContent(Cursor cursor) {
-        if (updateFromCursor(cursor)) {
-            mDataVersion = nextVersionNumber();
-        }
-    }
-
-    @Override
-    public MediaDetails getDetails() {
-        MediaDetails details = super.getDetails();
-        details.addDetail(MediaDetails.INDEX_PATH, filePath);
-        details.addDetail(MediaDetails.INDEX_TITLE, caption);
-        DateFormat formater = DateFormat.getDateTimeInstance();
-        details.addDetail(MediaDetails.INDEX_DATETIME,
-                formater.format(new Date(dateModifiedInSec * 1000)));
-        details.addDetail(MediaDetails.INDEX_WIDTH, width);
-        details.addDetail(MediaDetails.INDEX_HEIGHT, height);
-
-        if (GalleryUtils.isValidLocation(latitude, longitude)) {
-            details.addDetail(MediaDetails.INDEX_LOCATION, new double[] {latitude, longitude});
-        }
-        if (fileSize > 0) details.addDetail(MediaDetails.INDEX_SIZE, fileSize);
-        return details;
-    }
-
-    @Override
-    public String getMimeType() {
-        return mimeType;
-    }
-
-    @Override
-    public long getSize() {
-        return fileSize;
-    }
-}
diff --git a/src/com/android/gallery3d/data/LocalMergeAlbum.java b/src/com/android/gallery3d/data/LocalMergeAlbum.java
deleted file mode 100644
index f0b5e57..0000000
--- a/src/com/android/gallery3d/data/LocalMergeAlbum.java
+++ /dev/null
@@ -1,257 +0,0 @@
-/*
- * Copyright (C) 2010 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.gallery3d.data;
-
-import android.net.Uri;
-import android.provider.MediaStore;
-
-import com.android.gallery3d.common.ApiHelper;
-
-import java.lang.ref.SoftReference;
-import java.util.ArrayList;
-import java.util.Comparator;
-import java.util.NoSuchElementException;
-import java.util.SortedMap;
-import java.util.TreeMap;
-
-// MergeAlbum merges items from two or more MediaSets. It uses a Comparator to
-// determine the order of items. The items are assumed to be sorted in the input
-// media sets (with the same order that the Comparator uses).
-//
-// This only handles MediaItems, not SubMediaSets.
-public class LocalMergeAlbum extends MediaSet implements ContentListener {
-    @SuppressWarnings("unused")
-    private static final String TAG = "LocalMergeAlbum";
-    private static final int PAGE_SIZE = 64;
-
-    private final Comparator<MediaItem> mComparator;
-    private final MediaSet[] mSources;
-
-    private FetchCache[] mFetcher;
-    private int mSupportedOperation;
-    private int mBucketId;
-
-    // mIndex maps global position to the position of each underlying media sets.
-    private TreeMap<Integer, int[]> mIndex = new TreeMap<Integer, int[]>();
-
-    public LocalMergeAlbum(
-            Path path, Comparator<MediaItem> comparator, MediaSet[] sources, int bucketId) {
-        super(path, INVALID_DATA_VERSION);
-        mComparator = comparator;
-        mSources = sources;
-        mBucketId = bucketId;
-        for (MediaSet set : mSources) {
-            set.addContentListener(this);
-        }
-        reload();
-    }
-
-    @Override
-    public boolean isCameraRoll() {
-        if (mSources.length == 0) return false;
-        for(MediaSet set : mSources) {
-            if (!set.isCameraRoll()) return false;
-        }
-        return true;
-    }
-
-    private void updateData() {
-        ArrayList<MediaSet> matches = new ArrayList<MediaSet>();
-        int supported = mSources.length == 0 ? 0 : MediaItem.SUPPORT_ALL;
-        mFetcher = new FetchCache[mSources.length];
-        for (int i = 0, n = mSources.length; i < n; ++i) {
-            mFetcher[i] = new FetchCache(mSources[i]);
-            supported &= mSources[i].getSupportedOperations();
-        }
-        mSupportedOperation = supported;
-        mIndex.clear();
-        mIndex.put(0, new int[mSources.length]);
-    }
-
-    private void invalidateCache() {
-        for (int i = 0, n = mSources.length; i < n; i++) {
-            mFetcher[i].invalidate();
-        }
-        mIndex.clear();
-        mIndex.put(0, new int[mSources.length]);
-    }
-
-    @Override
-    public Uri getContentUri() {
-        String bucketId = String.valueOf(mBucketId);
-        if (ApiHelper.HAS_MEDIA_PROVIDER_FILES_TABLE) {
-            return MediaStore.Files.getContentUri("external").buildUpon()
-                    .appendQueryParameter(LocalSource.KEY_BUCKET_ID, bucketId)
-                    .build();
-        } else {
-            // We don't have a single URL for a merged image before ICS
-            // So we used the image's URL as a substitute.
-            return MediaStore.Images.Media.EXTERNAL_CONTENT_URI.buildUpon()
-                    .appendQueryParameter(LocalSource.KEY_BUCKET_ID, bucketId)
-                    .build();
-        }
-    }
-
-    @Override
-    public String getName() {
-        return mSources.length == 0 ? "" : mSources[0].getName();
-    }
-
-    @Override
-    public int getMediaItemCount() {
-        return getTotalMediaItemCount();
-    }
-
-    @Override
-    public ArrayList<MediaItem> getMediaItem(int start, int count) {
-
-        // First find the nearest mark position <= start.
-        SortedMap<Integer, int[]> head = mIndex.headMap(start + 1);
-        int markPos = head.lastKey();
-        int[] subPos = head.get(markPos).clone();
-        MediaItem[] slot = new MediaItem[mSources.length];
-
-        int size = mSources.length;
-
-        // fill all slots
-        for (int i = 0; i < size; i++) {
-            slot[i] = mFetcher[i].getItem(subPos[i]);
-        }
-
-        ArrayList<MediaItem> result = new ArrayList<MediaItem>();
-
-        for (int i = markPos; i < start + count; i++) {
-            int k = -1;  // k points to the best slot up to now.
-            for (int j = 0; j < size; j++) {
-                if (slot[j] != null) {
-                    if (k == -1 || mComparator.compare(slot[j], slot[k]) < 0) {
-                        k = j;
-                    }
-                }
-            }
-
-            // If we don't have anything, all streams are exhausted.
-            if (k == -1) break;
-
-            // Pick the best slot and refill it.
-            subPos[k]++;
-            if (i >= start) {
-                result.add(slot[k]);
-            }
-            slot[k] = mFetcher[k].getItem(subPos[k]);
-
-            // Periodically leave a mark in the index, so we can come back later.
-            if ((i + 1) % PAGE_SIZE == 0) {
-                mIndex.put(i + 1, subPos.clone());
-            }
-        }
-
-        return result;
-    }
-
-    @Override
-    public int getTotalMediaItemCount() {
-        int count = 0;
-        for (MediaSet set : mSources) {
-            count += set.getTotalMediaItemCount();
-        }
-        return count;
-    }
-
-    @Override
-    public long reload() {
-        boolean changed = false;
-        for (int i = 0, n = mSources.length; i < n; ++i) {
-            if (mSources[i].reload() > mDataVersion) changed = true;
-        }
-        if (changed) {
-            mDataVersion = nextVersionNumber();
-            updateData();
-            invalidateCache();
-        }
-        return mDataVersion;
-    }
-
-    @Override
-    public void onContentDirty() {
-        notifyContentChanged();
-    }
-
-    @Override
-    public int getSupportedOperations() {
-        return mSupportedOperation;
-    }
-
-    @Override
-    public void delete() {
-        for (MediaSet set : mSources) {
-            set.delete();
-        }
-    }
-
-    @Override
-    public void rotate(int degrees) {
-        for (MediaSet set : mSources) {
-            set.rotate(degrees);
-        }
-    }
-
-    private static class FetchCache {
-        private MediaSet mBaseSet;
-        private SoftReference<ArrayList<MediaItem>> mCacheRef;
-        private int mStartPos;
-
-        public FetchCache(MediaSet baseSet) {
-            mBaseSet = baseSet;
-        }
-
-        public void invalidate() {
-            mCacheRef = null;
-        }
-
-        public MediaItem getItem(int index) {
-            boolean needLoading = false;
-            ArrayList<MediaItem> cache = null;
-            if (mCacheRef == null
-                    || index < mStartPos || index >= mStartPos + PAGE_SIZE) {
-                needLoading = true;
-            } else {
-                cache = mCacheRef.get();
-                if (cache == null) {
-                    needLoading = true;
-                }
-            }
-
-            if (needLoading) {
-                cache = mBaseSet.getMediaItem(index, PAGE_SIZE);
-                mCacheRef = new SoftReference<ArrayList<MediaItem>>(cache);
-                mStartPos = index;
-            }
-
-            if (index < mStartPos || index >= mStartPos + cache.size()) {
-                return null;
-            }
-
-            return cache.get(index - mStartPos);
-        }
-    }
-
-    @Override
-    public boolean isLeafAlbum() {
-        return true;
-    }
-}
diff --git a/src/com/android/gallery3d/data/LocalSource.java b/src/com/android/gallery3d/data/LocalSource.java
deleted file mode 100644
index a2e3d14..0000000
--- a/src/com/android/gallery3d/data/LocalSource.java
+++ /dev/null
@@ -1,275 +0,0 @@
-/*
- * Copyright (C) 2010 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.gallery3d.data;
-
-import android.content.ContentProviderClient;
-import android.content.ContentUris;
-import android.content.UriMatcher;
-import android.net.Uri;
-import android.provider.MediaStore;
-
-import com.android.gallery3d.app.Gallery;
-import com.android.gallery3d.app.GalleryApp;
-import com.android.gallery3d.data.MediaSet.ItemConsumer;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Comparator;
-
-class LocalSource extends MediaSource {
-
-    public static final String KEY_BUCKET_ID = "bucketId";
-
-    private GalleryApp mApplication;
-    private PathMatcher mMatcher;
-    private static final int NO_MATCH = -1;
-    private final UriMatcher mUriMatcher = new UriMatcher(NO_MATCH);
-    public static final Comparator<PathId> sIdComparator = new IdComparator();
-
-    private static final int LOCAL_IMAGE_ALBUMSET = 0;
-    private static final int LOCAL_VIDEO_ALBUMSET = 1;
-    private static final int LOCAL_IMAGE_ALBUM = 2;
-    private static final int LOCAL_VIDEO_ALBUM = 3;
-    private static final int LOCAL_IMAGE_ITEM = 4;
-    private static final int LOCAL_VIDEO_ITEM = 5;
-    private static final int LOCAL_ALL_ALBUMSET = 6;
-    private static final int LOCAL_ALL_ALBUM = 7;
-
-    private static final String TAG = "LocalSource";
-
-    private ContentProviderClient mClient;
-
-    public LocalSource(GalleryApp context) {
-        super("local");
-        mApplication = context;
-        mMatcher = new PathMatcher();
-        mMatcher.add("/local/image", LOCAL_IMAGE_ALBUMSET);
-        mMatcher.add("/local/video", LOCAL_VIDEO_ALBUMSET);
-        mMatcher.add("/local/all", LOCAL_ALL_ALBUMSET);
-
-        mMatcher.add("/local/image/*", LOCAL_IMAGE_ALBUM);
-        mMatcher.add("/local/video/*", LOCAL_VIDEO_ALBUM);
-        mMatcher.add("/local/all/*", LOCAL_ALL_ALBUM);
-        mMatcher.add("/local/image/item/*", LOCAL_IMAGE_ITEM);
-        mMatcher.add("/local/video/item/*", LOCAL_VIDEO_ITEM);
-
-        mUriMatcher.addURI(MediaStore.AUTHORITY,
-                "external/images/media/#", LOCAL_IMAGE_ITEM);
-        mUriMatcher.addURI(MediaStore.AUTHORITY,
-                "external/video/media/#", LOCAL_VIDEO_ITEM);
-        mUriMatcher.addURI(MediaStore.AUTHORITY,
-                "external/images/media", LOCAL_IMAGE_ALBUM);
-        mUriMatcher.addURI(MediaStore.AUTHORITY,
-                "external/video/media", LOCAL_VIDEO_ALBUM);
-        mUriMatcher.addURI(MediaStore.AUTHORITY,
-                "external/file", LOCAL_ALL_ALBUM);
-    }
-
-    @Override
-    public MediaObject createMediaObject(Path path) {
-        GalleryApp app = mApplication;
-        switch (mMatcher.match(path)) {
-            case LOCAL_ALL_ALBUMSET:
-            case LOCAL_IMAGE_ALBUMSET:
-            case LOCAL_VIDEO_ALBUMSET:
-                return new LocalAlbumSet(path, mApplication);
-            case LOCAL_IMAGE_ALBUM:
-                return new LocalAlbum(path, app, mMatcher.getIntVar(0), true);
-            case LOCAL_VIDEO_ALBUM:
-                return new LocalAlbum(path, app, mMatcher.getIntVar(0), false);
-            case LOCAL_ALL_ALBUM: {
-                int bucketId = mMatcher.getIntVar(0);
-                DataManager dataManager = app.getDataManager();
-                MediaSet imageSet = (MediaSet) dataManager.getMediaObject(
-                        LocalAlbumSet.PATH_IMAGE.getChild(bucketId));
-                MediaSet videoSet = (MediaSet) dataManager.getMediaObject(
-                        LocalAlbumSet.PATH_VIDEO.getChild(bucketId));
-                Comparator<MediaItem> comp = DataManager.sDateTakenComparator;
-                return new LocalMergeAlbum(
-                        path, comp, new MediaSet[] {imageSet, videoSet}, bucketId);
-            }
-            case LOCAL_IMAGE_ITEM:
-                return new LocalImage(path, mApplication, mMatcher.getIntVar(0));
-            case LOCAL_VIDEO_ITEM:
-                return new LocalVideo(path, mApplication, mMatcher.getIntVar(0));
-            default:
-                throw new RuntimeException("bad path: " + path);
-        }
-    }
-
-    private static int getMediaType(String type, int defaultType) {
-        if (type == null) return defaultType;
-        try {
-            int value = Integer.parseInt(type);
-            if ((value & (MEDIA_TYPE_IMAGE
-                    | MEDIA_TYPE_VIDEO)) != 0) return value;
-        } catch (NumberFormatException e) {
-            Log.w(TAG, "invalid type: " + type, e);
-        }
-        return defaultType;
-    }
-
-    // The media type bit passed by the intent
-    private static final int MEDIA_TYPE_ALL = 0;
-    private static final int MEDIA_TYPE_IMAGE = 1;
-    private static final int MEDIA_TYPE_VIDEO = 4;
-
-    private Path getAlbumPath(Uri uri, int defaultType) {
-        int mediaType = getMediaType(
-                uri.getQueryParameter(Gallery.KEY_MEDIA_TYPES),
-                defaultType);
-        String bucketId = uri.getQueryParameter(KEY_BUCKET_ID);
-        int id = 0;
-        try {
-            id = Integer.parseInt(bucketId);
-        } catch (NumberFormatException e) {
-            Log.w(TAG, "invalid bucket id: " + bucketId, e);
-            return null;
-        }
-        switch (mediaType) {
-            case MEDIA_TYPE_IMAGE:
-                return Path.fromString("/local/image").getChild(id);
-            case MEDIA_TYPE_VIDEO:
-                return Path.fromString("/local/video").getChild(id);
-            default:
-                return Path.fromString("/local/all").getChild(id);
-        }
-    }
-
-    @Override
-    public Path findPathByUri(Uri uri, String type) {
-        try {
-            switch (mUriMatcher.match(uri)) {
-                case LOCAL_IMAGE_ITEM: {
-                    long id = ContentUris.parseId(uri);
-                    return id >= 0 ? LocalImage.ITEM_PATH.getChild(id) : null;
-                }
-                case LOCAL_VIDEO_ITEM: {
-                    long id = ContentUris.parseId(uri);
-                    return id >= 0 ? LocalVideo.ITEM_PATH.getChild(id) : null;
-                }
-                case LOCAL_IMAGE_ALBUM: {
-                    return getAlbumPath(uri, MEDIA_TYPE_IMAGE);
-                }
-                case LOCAL_VIDEO_ALBUM: {
-                    return getAlbumPath(uri, MEDIA_TYPE_VIDEO);
-                }
-                case LOCAL_ALL_ALBUM: {
-                    return getAlbumPath(uri, MEDIA_TYPE_ALL);
-                }
-            }
-        } catch (NumberFormatException e) {
-            Log.w(TAG, "uri: " + uri.toString(), e);
-        }
-        return null;
-    }
-
-    @Override
-    public Path getDefaultSetOf(Path item) {
-        MediaObject object = mApplication.getDataManager().getMediaObject(item);
-        if (object instanceof LocalMediaItem) {
-            return Path.fromString("/local/all").getChild(
-                    String.valueOf(((LocalMediaItem) object).getBucketId()));
-        }
-        return null;
-    }
-
-    @Override
-    public void mapMediaItems(ArrayList<PathId> list, ItemConsumer consumer) {
-        ArrayList<PathId> imageList = new ArrayList<PathId>();
-        ArrayList<PathId> videoList = new ArrayList<PathId>();
-        int n = list.size();
-        for (int i = 0; i < n; i++) {
-            PathId pid = list.get(i);
-            // We assume the form is: "/local/{image,video}/item/#"
-            // We don't use mMatcher for efficiency's reason.
-            Path parent = pid.path.getParent();
-            if (parent == LocalImage.ITEM_PATH) {
-                imageList.add(pid);
-            } else if (parent == LocalVideo.ITEM_PATH) {
-                videoList.add(pid);
-            }
-        }
-        // TODO: use "files" table so we can merge the two cases.
-        processMapMediaItems(imageList, consumer, true);
-        processMapMediaItems(videoList, consumer, false);
-    }
-
-    private void processMapMediaItems(ArrayList<PathId> list,
-            ItemConsumer consumer, boolean isImage) {
-        // Sort path by path id
-        Collections.sort(list, sIdComparator);
-        int n = list.size();
-        for (int i = 0; i < n; ) {
-            PathId pid = list.get(i);
-
-            // Find a range of items.
-            ArrayList<Integer> ids = new ArrayList<Integer>();
-            int startId = Integer.parseInt(pid.path.getSuffix());
-            ids.add(startId);
-
-            int j;
-            for (j = i + 1; j < n; j++) {
-                PathId pid2 = list.get(j);
-                int curId = Integer.parseInt(pid2.path.getSuffix());
-                if (curId - startId >= MediaSet.MEDIAITEM_BATCH_FETCH_COUNT) {
-                    break;
-                }
-                ids.add(curId);
-            }
-
-            MediaItem[] items = LocalAlbum.getMediaItemById(
-                    mApplication, isImage, ids);
-            for(int k = i ; k < j; k++) {
-                PathId pid2 = list.get(k);
-                consumer.consume(pid2.id, items[k - i]);
-            }
-
-            i = j;
-        }
-    }
-
-    // This is a comparator which compares the suffix number in two Paths.
-    private static class IdComparator implements Comparator<PathId> {
-        @Override
-        public int compare(PathId p1, PathId p2) {
-            String s1 = p1.path.getSuffix();
-            String s2 = p2.path.getSuffix();
-            int len1 = s1.length();
-            int len2 = s2.length();
-            if (len1 < len2) {
-                return -1;
-            } else if (len1 > len2) {
-                return 1;
-            } else {
-                return s1.compareTo(s2);
-            }
-        }
-    }
-
-    @Override
-    public void resume() {
-        mClient = mApplication.getContentResolver()
-                .acquireContentProviderClient(MediaStore.AUTHORITY);
-    }
-
-    @Override
-    public void pause() {
-        mClient.release();
-        mClient = null;
-    }
-}
diff --git a/src/com/android/gallery3d/data/LocalVideo.java b/src/com/android/gallery3d/data/LocalVideo.java
deleted file mode 100644
index 4b8774c..0000000
--- a/src/com/android/gallery3d/data/LocalVideo.java
+++ /dev/null
@@ -1,242 +0,0 @@
-/*
- * Copyright (C) 2010 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.gallery3d.data;
-
-import android.content.ContentResolver;
-import android.database.Cursor;
-import android.graphics.Bitmap;
-import android.graphics.BitmapRegionDecoder;
-import android.net.Uri;
-import android.provider.MediaStore.Video;
-import android.provider.MediaStore.Video.VideoColumns;
-
-import com.android.gallery3d.app.GalleryApp;
-import com.android.gallery3d.common.BitmapUtils;
-import com.android.gallery3d.util.GalleryUtils;
-import com.android.gallery3d.util.ThreadPool.Job;
-import com.android.gallery3d.util.ThreadPool.JobContext;
-import com.android.gallery3d.util.UpdateHelper;
-
-// LocalVideo represents a video in the local storage.
-public class LocalVideo extends LocalMediaItem {
-    private static final String TAG = "LocalVideo";
-    static final Path ITEM_PATH = Path.fromString("/local/video/item");
-
-    // Must preserve order between these indices and the order of the terms in
-    // the following PROJECTION array.
-    private static final int INDEX_ID = 0;
-    private static final int INDEX_CAPTION = 1;
-    private static final int INDEX_MIME_TYPE = 2;
-    private static final int INDEX_LATITUDE = 3;
-    private static final int INDEX_LONGITUDE = 4;
-    private static final int INDEX_DATE_TAKEN = 5;
-    private static final int INDEX_DATE_ADDED = 6;
-    private static final int INDEX_DATE_MODIFIED = 7;
-    private static final int INDEX_DATA = 8;
-    private static final int INDEX_DURATION = 9;
-    private static final int INDEX_BUCKET_ID = 10;
-    private static final int INDEX_SIZE = 11;
-    private static final int INDEX_RESOLUTION = 12;
-
-    static final String[] PROJECTION = new String[] {
-            VideoColumns._ID,
-            VideoColumns.TITLE,
-            VideoColumns.MIME_TYPE,
-            VideoColumns.LATITUDE,
-            VideoColumns.LONGITUDE,
-            VideoColumns.DATE_TAKEN,
-            VideoColumns.DATE_ADDED,
-            VideoColumns.DATE_MODIFIED,
-            VideoColumns.DATA,
-            VideoColumns.DURATION,
-            VideoColumns.BUCKET_ID,
-            VideoColumns.SIZE,
-            VideoColumns.RESOLUTION,
-    };
-
-    private final GalleryApp mApplication;
-
-    public int durationInSec;
-
-    public LocalVideo(Path path, GalleryApp application, Cursor cursor) {
-        super(path, nextVersionNumber());
-        mApplication = application;
-        loadFromCursor(cursor);
-    }
-
-    public LocalVideo(Path path, GalleryApp context, int id) {
-        super(path, nextVersionNumber());
-        mApplication = context;
-        ContentResolver resolver = mApplication.getContentResolver();
-        Uri uri = Video.Media.EXTERNAL_CONTENT_URI;
-        Cursor cursor = LocalAlbum.getItemCursor(resolver, uri, PROJECTION, id);
-        if (cursor == null) {
-            throw new RuntimeException("cannot get cursor for: " + path);
-        }
-        try {
-            if (cursor.moveToNext()) {
-                loadFromCursor(cursor);
-            } else {
-                throw new RuntimeException("cannot find data for: " + path);
-            }
-        } finally {
-            cursor.close();
-        }
-    }
-
-    private void loadFromCursor(Cursor cursor) {
-        id = cursor.getInt(INDEX_ID);
-        caption = cursor.getString(INDEX_CAPTION);
-        mimeType = cursor.getString(INDEX_MIME_TYPE);
-        latitude = cursor.getDouble(INDEX_LATITUDE);
-        longitude = cursor.getDouble(INDEX_LONGITUDE);
-        dateTakenInMs = cursor.getLong(INDEX_DATE_TAKEN);
-        dateAddedInSec = cursor.getLong(INDEX_DATE_ADDED);
-        dateModifiedInSec = cursor.getLong(INDEX_DATE_MODIFIED);
-        filePath = cursor.getString(INDEX_DATA);
-        durationInSec = cursor.getInt(INDEX_DURATION) / 1000;
-        bucketId = cursor.getInt(INDEX_BUCKET_ID);
-        fileSize = cursor.getLong(INDEX_SIZE);
-        parseResolution(cursor.getString(INDEX_RESOLUTION));
-    }
-
-    private void parseResolution(String resolution) {
-        if (resolution == null) return;
-        int m = resolution.indexOf('x');
-        if (m == -1) return;
-        try {
-            int w = Integer.parseInt(resolution.substring(0, m));
-            int h = Integer.parseInt(resolution.substring(m + 1));
-            width = w;
-            height = h;
-        } catch (Throwable t) {
-            Log.w(TAG, t);
-        }
-    }
-
-    @Override
-    protected boolean updateFromCursor(Cursor cursor) {
-        UpdateHelper uh = new UpdateHelper();
-        id = uh.update(id, cursor.getInt(INDEX_ID));
-        caption = uh.update(caption, cursor.getString(INDEX_CAPTION));
-        mimeType = uh.update(mimeType, cursor.getString(INDEX_MIME_TYPE));
-        latitude = uh.update(latitude, cursor.getDouble(INDEX_LATITUDE));
-        longitude = uh.update(longitude, cursor.getDouble(INDEX_LONGITUDE));
-        dateTakenInMs = uh.update(
-                dateTakenInMs, cursor.getLong(INDEX_DATE_TAKEN));
-        dateAddedInSec = uh.update(
-                dateAddedInSec, cursor.getLong(INDEX_DATE_ADDED));
-        dateModifiedInSec = uh.update(
-                dateModifiedInSec, cursor.getLong(INDEX_DATE_MODIFIED));
-        filePath = uh.update(filePath, cursor.getString(INDEX_DATA));
-        durationInSec = uh.update(
-                durationInSec, cursor.getInt(INDEX_DURATION) / 1000);
-        bucketId = uh.update(bucketId, cursor.getInt(INDEX_BUCKET_ID));
-        fileSize = uh.update(fileSize, cursor.getLong(INDEX_SIZE));
-        return uh.isUpdated();
-    }
-
-    @Override
-    public Job<Bitmap> requestImage(int type) {
-        return new LocalVideoRequest(mApplication, getPath(), dateModifiedInSec,
-                type, filePath);
-    }
-
-    public static class LocalVideoRequest extends ImageCacheRequest {
-        private String mLocalFilePath;
-
-        LocalVideoRequest(GalleryApp application, Path path, long timeModified,
-                int type, String localFilePath) {
-            super(application, path, timeModified, type,
-                    MediaItem.getTargetSize(type));
-            mLocalFilePath = localFilePath;
-        }
-
-        @Override
-        public Bitmap onDecodeOriginal(JobContext jc, int type) {
-            Bitmap bitmap = BitmapUtils.createVideoThumbnail(mLocalFilePath);
-            if (bitmap == null || jc.isCancelled()) return null;
-            return bitmap;
-        }
-    }
-
-    @Override
-    public Job<BitmapRegionDecoder> requestLargeImage() {
-        throw new UnsupportedOperationException("Cannot regquest a large image"
-                + " to a local video!");
-    }
-
-    @Override
-    public int getSupportedOperations() {
-        return SUPPORT_DELETE | SUPPORT_SHARE | SUPPORT_PLAY | SUPPORT_INFO | SUPPORT_TRIM | SUPPORT_MUTE;
-    }
-
-    @Override
-    public void delete() {
-        GalleryUtils.assertNotInRenderThread();
-        Uri baseUri = Video.Media.EXTERNAL_CONTENT_URI;
-        mApplication.getContentResolver().delete(baseUri, "_id=?",
-                new String[]{String.valueOf(id)});
-    }
-
-    @Override
-    public void rotate(int degrees) {
-        // TODO
-    }
-
-    @Override
-    public Uri getContentUri() {
-        Uri baseUri = Video.Media.EXTERNAL_CONTENT_URI;
-        return baseUri.buildUpon().appendPath(String.valueOf(id)).build();
-    }
-
-    @Override
-    public Uri getPlayUri() {
-        return getContentUri();
-    }
-
-    @Override
-    public int getMediaType() {
-        return MEDIA_TYPE_VIDEO;
-    }
-
-    @Override
-    public MediaDetails getDetails() {
-        MediaDetails details = super.getDetails();
-        int s = durationInSec;
-        if (s > 0) {
-            details.addDetail(MediaDetails.INDEX_DURATION, GalleryUtils.formatDuration(
-                    mApplication.getAndroidContext(), durationInSec));
-        }
-        return details;
-    }
-
-    @Override
-    public int getWidth() {
-        return width;
-    }
-
-    @Override
-    public int getHeight() {
-        return height;
-    }
-
-    @Override
-    public String getFilePath() {
-        return filePath;
-    }
-}
diff --git a/src/com/android/gallery3d/data/LocationClustering.java b/src/com/android/gallery3d/data/LocationClustering.java
deleted file mode 100644
index 540322a..0000000
--- a/src/com/android/gallery3d/data/LocationClustering.java
+++ /dev/null
@@ -1,316 +0,0 @@
-/*
- * Copyright (C) 2010 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.gallery3d.data;
-
-import android.content.Context;
-import android.os.Handler;
-import android.os.Looper;
-import android.util.FloatMath;
-import android.widget.Toast;
-
-import com.android.gallery3d.R;
-import com.android.gallery3d.util.GalleryUtils;
-import com.android.gallery3d.util.ReverseGeocoder;
-
-import java.util.ArrayList;
-
-class LocationClustering extends Clustering {
-    @SuppressWarnings("unused")
-    private static final String TAG = "LocationClustering";
-
-    private static final int MIN_GROUPS = 1;
-    private static final int MAX_GROUPS = 20;
-    private static final int MAX_ITERATIONS = 30;
-
-    // If the total distance change is less than this ratio, stop iterating.
-    private static final float STOP_CHANGE_RATIO = 0.01f;
-    private Context mContext;
-    private ArrayList<ArrayList<SmallItem>> mClusters;
-    private ArrayList<String> mNames;
-    private String mNoLocationString;
-    private Handler mHandler;
-
-    private static class Point {
-        public Point(double lat, double lng) {
-            latRad = Math.toRadians(lat);
-            lngRad = Math.toRadians(lng);
-        }
-        public Point() {}
-        public double latRad, lngRad;
-    }
-
-    private static class SmallItem {
-        Path path;
-        double lat, lng;
-    }
-
-    public LocationClustering(Context context) {
-        mContext = context;
-        mNoLocationString = mContext.getResources().getString(R.string.no_location);
-        mHandler = new Handler(Looper.getMainLooper());
-    }
-
-    @Override
-    public void run(MediaSet baseSet) {
-        final int total = baseSet.getTotalMediaItemCount();
-        final SmallItem[] buf = new SmallItem[total];
-        // Separate items to two sets: with or without lat-long.
-        final double[] latLong = new double[2];
-        baseSet.enumerateTotalMediaItems(new MediaSet.ItemConsumer() {
-            @Override
-            public void consume(int index, MediaItem item) {
-                if (index < 0 || index >= total) return;
-                SmallItem s = new SmallItem();
-                s.path = item.getPath();
-                item.getLatLong(latLong);
-                s.lat = latLong[0];
-                s.lng = latLong[1];
-                buf[index] = s;
-            }
-        });
-
-        final ArrayList<SmallItem> withLatLong = new ArrayList<SmallItem>();
-        final ArrayList<SmallItem> withoutLatLong = new ArrayList<SmallItem>();
-        final ArrayList<Point> points = new ArrayList<Point>();
-        for (int i = 0; i < total; i++) {
-            SmallItem s = buf[i];
-            if (s == null) continue;
-            if (GalleryUtils.isValidLocation(s.lat, s.lng)) {
-                withLatLong.add(s);
-                points.add(new Point(s.lat, s.lng));
-            } else {
-                withoutLatLong.add(s);
-            }
-        }
-
-        ArrayList<ArrayList<SmallItem>> clusters = new ArrayList<ArrayList<SmallItem>>();
-
-        int m = withLatLong.size();
-        if (m > 0) {
-            // cluster the items with lat-long
-            Point[] pointsArray = new Point[m];
-            pointsArray = points.toArray(pointsArray);
-            int[] bestK = new int[1];
-            int[] index = kMeans(pointsArray, bestK);
-
-            for (int i = 0; i < bestK[0]; i++) {
-                clusters.add(new ArrayList<SmallItem>());
-            }
-
-            for (int i = 0; i < m; i++) {
-                clusters.get(index[i]).add(withLatLong.get(i));
-            }
-        }
-
-        ReverseGeocoder geocoder = new ReverseGeocoder(mContext);
-        mNames = new ArrayList<String>();
-        boolean hasUnresolvedAddress = false;
-        mClusters = new ArrayList<ArrayList<SmallItem>>();
-        for (ArrayList<SmallItem> cluster : clusters) {
-            String name = generateName(cluster, geocoder);
-            if (name != null) {
-                mNames.add(name);
-                mClusters.add(cluster);
-            } else {
-                // move cluster-i to no location cluster
-                withoutLatLong.addAll(cluster);
-                hasUnresolvedAddress = true;
-            }
-        }
-
-        if (withoutLatLong.size() > 0) {
-            mNames.add(mNoLocationString);
-            mClusters.add(withoutLatLong);
-        }
-
-        if (hasUnresolvedAddress) {
-            mHandler.post(new Runnable() {
-                @Override
-                public void run() {
-                    Toast.makeText(mContext, R.string.no_connectivity,
-                            Toast.LENGTH_LONG).show();
-                }
-            });
-        }
-    }
-
-    private static String generateName(ArrayList<SmallItem> items,
-            ReverseGeocoder geocoder) {
-        ReverseGeocoder.SetLatLong set = new ReverseGeocoder.SetLatLong();
-
-        int n = items.size();
-        for (int i = 0; i < n; i++) {
-            SmallItem item = items.get(i);
-            double itemLatitude = item.lat;
-            double itemLongitude = item.lng;
-
-            if (set.mMinLatLatitude > itemLatitude) {
-                set.mMinLatLatitude = itemLatitude;
-                set.mMinLatLongitude = itemLongitude;
-            }
-            if (set.mMaxLatLatitude < itemLatitude) {
-                set.mMaxLatLatitude = itemLatitude;
-                set.mMaxLatLongitude = itemLongitude;
-            }
-            if (set.mMinLonLongitude > itemLongitude) {
-                set.mMinLonLatitude = itemLatitude;
-                set.mMinLonLongitude = itemLongitude;
-            }
-            if (set.mMaxLonLongitude < itemLongitude) {
-                set.mMaxLonLatitude = itemLatitude;
-                set.mMaxLonLongitude = itemLongitude;
-            }
-        }
-
-        return geocoder.computeAddress(set);
-    }
-
-    @Override
-    public int getNumberOfClusters() {
-        return mClusters.size();
-    }
-
-    @Override
-    public ArrayList<Path> getCluster(int index) {
-        ArrayList<SmallItem> items = mClusters.get(index);
-        ArrayList<Path> result = new ArrayList<Path>(items.size());
-        for (int i = 0, n = items.size(); i < n; i++) {
-            result.add(items.get(i).path);
-        }
-        return result;
-    }
-
-    @Override
-    public String getClusterName(int index) {
-        return mNames.get(index);
-    }
-
-    // Input: n points
-    // Output: the best k is stored in bestK[0], and the return value is the
-    // an array which specifies the group that each point belongs (0 to k - 1).
-    private static int[] kMeans(Point points[], int[] bestK) {
-        int n = points.length;
-
-        // min and max number of groups wanted
-        int minK = Math.min(n, MIN_GROUPS);
-        int maxK = Math.min(n, MAX_GROUPS);
-
-        Point[] center = new Point[maxK];  // center of each group.
-        Point[] groupSum = new Point[maxK];  // sum of points in each group.
-        int[] groupCount = new int[maxK];  // number of points in each group.
-        int[] grouping = new int[n]; // The group assignment for each point.
-
-        for (int i = 0; i < maxK; i++) {
-            center[i] = new Point();
-            groupSum[i] = new Point();
-        }
-
-        // The score we want to minimize is:
-        //   (sum of distance from each point to its group center) * sqrt(k).
-        float bestScore = Float.MAX_VALUE;
-        // The best group assignment up to now.
-        int[] bestGrouping = new int[n];
-        // The best K up to now.
-        bestK[0] = 1;
-
-        float lastDistance = 0;
-        float totalDistance = 0;
-
-        for (int k = minK; k <= maxK; k++) {
-            // step 1: (arbitrarily) pick k points as the initial centers.
-            int delta = n / k;
-            for (int i = 0; i < k; i++) {
-                Point p = points[i * delta];
-                center[i].latRad = p.latRad;
-                center[i].lngRad = p.lngRad;
-            }
-
-            for (int iter = 0; iter < MAX_ITERATIONS; iter++) {
-                // step 2: assign each point to the nearest center.
-                for (int i = 0; i < k; i++) {
-                    groupSum[i].latRad = 0;
-                    groupSum[i].lngRad = 0;
-                    groupCount[i] = 0;
-                }
-                totalDistance = 0;
-
-                for (int i = 0; i < n; i++) {
-                    Point p = points[i];
-                    float bestDistance = Float.MAX_VALUE;
-                    int bestIndex = 0;
-                    for (int j = 0; j < k; j++) {
-                        float distance = (float) GalleryUtils.fastDistanceMeters(
-                                p.latRad, p.lngRad, center[j].latRad, center[j].lngRad);
-                        // We may have small non-zero distance introduced by
-                        // floating point calculation, so zero out small
-                        // distances less than 1 meter.
-                        if (distance < 1) {
-                            distance = 0;
-                        }
-                        if (distance < bestDistance) {
-                            bestDistance = distance;
-                            bestIndex = j;
-                        }
-                    }
-                    grouping[i] = bestIndex;
-                    groupCount[bestIndex]++;
-                    groupSum[bestIndex].latRad += p.latRad;
-                    groupSum[bestIndex].lngRad += p.lngRad;
-                    totalDistance += bestDistance;
-                }
-
-                // step 3: calculate new centers
-                for (int i = 0; i < k; i++) {
-                    if (groupCount[i] > 0) {
-                        center[i].latRad = groupSum[i].latRad / groupCount[i];
-                        center[i].lngRad = groupSum[i].lngRad / groupCount[i];
-                    }
-                }
-
-                if (totalDistance == 0 || (Math.abs(lastDistance - totalDistance)
-                        / totalDistance) < STOP_CHANGE_RATIO) {
-                    break;
-                }
-                lastDistance = totalDistance;
-            }
-
-            // step 4: remove empty groups and reassign group number
-            int reassign[] = new int[k];
-            int realK = 0;
-            for (int i = 0; i < k; i++) {
-                if (groupCount[i] > 0) {
-                    reassign[i] = realK++;
-                }
-            }
-
-            // step 5: calculate the final score
-            float score = totalDistance * FloatMath.sqrt(realK);
-
-            if (score < bestScore) {
-                bestScore = score;
-                bestK[0] = realK;
-                for (int i = 0; i < n; i++) {
-                    bestGrouping[i] = reassign[grouping[i]];
-                }
-                if (score == 0) {
-                    break;
-                }
-            }
-        }
-        return bestGrouping;
-    }
-}
diff --git a/src/com/android/gallery3d/data/Log.java b/src/com/android/gallery3d/data/Log.java
deleted file mode 100644
index 3384eb6..0000000
--- a/src/com/android/gallery3d/data/Log.java
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Copyright (C) 2010 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.gallery3d.data;
-
-public class Log {
-    public static int v(String tag, String msg) {
-        return android.util.Log.v(tag, msg);
-    }
-    public static int v(String tag, String msg, Throwable tr) {
-        return android.util.Log.v(tag, msg, tr);
-    }
-    public static int d(String tag, String msg) {
-        return android.util.Log.d(tag, msg);
-    }
-    public static int d(String tag, String msg, Throwable tr) {
-        return android.util.Log.d(tag, msg, tr);
-    }
-    public static int i(String tag, String msg) {
-        return android.util.Log.i(tag, msg);
-    }
-    public static int i(String tag, String msg, Throwable tr) {
-        return android.util.Log.i(tag, msg, tr);
-    }
-    public static int w(String tag, String msg) {
-        return android.util.Log.w(tag, msg);
-    }
-    public static int w(String tag, String msg, Throwable tr) {
-        return android.util.Log.w(tag, msg, tr);
-    }
-    public static int w(String tag, Throwable tr) {
-        return android.util.Log.w(tag, tr);
-    }
-    public static int e(String tag, String msg) {
-        return android.util.Log.e(tag, msg);
-    }
-    public static int e(String tag, String msg, Throwable tr) {
-        return android.util.Log.e(tag, msg, tr);
-    }
-}
diff --git a/src/com/android/gallery3d/data/MediaDetails.java b/src/com/android/gallery3d/data/MediaDetails.java
deleted file mode 100644
index cac524b..0000000
--- a/src/com/android/gallery3d/data/MediaDetails.java
+++ /dev/null
@@ -1,170 +0,0 @@
-/*
- * Copyright (C) 2010 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.gallery3d.data;
-
-import com.android.gallery3d.R;
-import com.android.gallery3d.common.Utils;
-import com.android.gallery3d.exif.ExifInterface;
-import com.android.gallery3d.exif.ExifTag;
-import com.android.gallery3d.exif.Rational;
-
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.Map.Entry;
-import java.util.TreeMap;
-
-public class MediaDetails implements Iterable<Entry<Integer, Object>> {
-    @SuppressWarnings("unused")
-    private static final String TAG = "MediaDetails";
-
-    private TreeMap<Integer, Object> mDetails = new TreeMap<Integer, Object>();
-    private HashMap<Integer, Integer> mUnits = new HashMap<Integer, Integer>();
-
-    public static final int INDEX_TITLE = 1;
-    public static final int INDEX_DESCRIPTION = 2;
-    public static final int INDEX_DATETIME = 3;
-    public static final int INDEX_LOCATION = 4;
-    public static final int INDEX_WIDTH = 5;
-    public static final int INDEX_HEIGHT = 6;
-    public static final int INDEX_ORIENTATION = 7;
-    public static final int INDEX_DURATION = 8;
-    public static final int INDEX_MIMETYPE = 9;
-    public static final int INDEX_SIZE = 10;
-
-    // for EXIF
-    public static final int INDEX_MAKE = 100;
-    public static final int INDEX_MODEL = 101;
-    public static final int INDEX_FLASH = 102;
-    public static final int INDEX_FOCAL_LENGTH = 103;
-    public static final int INDEX_WHITE_BALANCE = 104;
-    public static final int INDEX_APERTURE = 105;
-    public static final int INDEX_SHUTTER_SPEED = 106;
-    public static final int INDEX_EXPOSURE_TIME = 107;
-    public static final int INDEX_ISO = 108;
-
-    // Put this last because it may be long.
-    public static final int INDEX_PATH = 200;
-
-    public static class FlashState {
-        private static int FLASH_FIRED_MASK = 1;
-        private static int FLASH_RETURN_MASK = 2 | 4;
-        private static int FLASH_MODE_MASK = 8 | 16;
-        private static int FLASH_FUNCTION_MASK = 32;
-        private static int FLASH_RED_EYE_MASK = 64;
-        private int mState;
-
-        public FlashState(int state) {
-            mState = state;
-        }
-
-        public boolean isFlashFired() {
-            return (mState & FLASH_FIRED_MASK) != 0;
-        }
-    }
-
-    public void addDetail(int index, Object value) {
-        mDetails.put(index, value);
-    }
-
-    public Object getDetail(int index) {
-        return mDetails.get(index);
-    }
-
-    public int size() {
-        return mDetails.size();
-    }
-
-    @Override
-    public Iterator<Entry<Integer, Object>> iterator() {
-        return mDetails.entrySet().iterator();
-    }
-
-    public void setUnit(int index, int unit) {
-        mUnits.put(index, unit);
-    }
-
-    public boolean hasUnit(int index) {
-        return mUnits.containsKey(index);
-    }
-
-    public int getUnit(int index) {
-        return mUnits.get(index);
-    }
-
-    private static void setExifData(MediaDetails details, ExifTag tag,
-            int key) {
-        if (tag != null) {
-            String value = null;
-            int type = tag.getDataType();
-            if (type == ExifTag.TYPE_UNSIGNED_RATIONAL || type == ExifTag.TYPE_RATIONAL) {
-                value = String.valueOf(tag.getValueAsRational(0).toDouble());
-            } else if (type == ExifTag.TYPE_ASCII) {
-                value = tag.getValueAsString();
-            } else {
-                value = String.valueOf(tag.forceGetValueAsLong(0));
-            }
-            if (key == MediaDetails.INDEX_FLASH) {
-                MediaDetails.FlashState state = new MediaDetails.FlashState(
-                        Integer.valueOf(value.toString()));
-                details.addDetail(key, state);
-            } else {
-                details.addDetail(key, value);
-            }
-        }
-    }
-
-    public static void extractExifInfo(MediaDetails details, String filePath) {
-
-        ExifInterface exif = new ExifInterface();
-        try {
-            exif.readExif(filePath);
-        } catch (FileNotFoundException e) {
-            Log.w(TAG, "Could not find file to read exif: " + filePath, e);
-        } catch (IOException e) {
-            Log.w(TAG, "Could not read exif from file: " + filePath, e);
-        }
-
-        setExifData(details, exif.getTag(ExifInterface.TAG_FLASH),
-                MediaDetails.INDEX_FLASH);
-        setExifData(details, exif.getTag(ExifInterface.TAG_IMAGE_WIDTH),
-                MediaDetails.INDEX_WIDTH);
-        setExifData(details, exif.getTag(ExifInterface.TAG_IMAGE_LENGTH),
-                MediaDetails.INDEX_HEIGHT);
-        setExifData(details, exif.getTag(ExifInterface.TAG_MAKE),
-                MediaDetails.INDEX_MAKE);
-        setExifData(details, exif.getTag(ExifInterface.TAG_MODEL),
-                MediaDetails.INDEX_MODEL);
-        setExifData(details, exif.getTag(ExifInterface.TAG_APERTURE_VALUE),
-                MediaDetails.INDEX_APERTURE);
-        setExifData(details, exif.getTag(ExifInterface.TAG_ISO_SPEED_RATINGS),
-                MediaDetails.INDEX_ISO);
-        setExifData(details, exif.getTag(ExifInterface.TAG_WHITE_BALANCE),
-                MediaDetails.INDEX_WHITE_BALANCE);
-        setExifData(details, exif.getTag(ExifInterface.TAG_EXPOSURE_TIME),
-                MediaDetails.INDEX_EXPOSURE_TIME);
-        ExifTag focalTag = exif.getTag(ExifInterface.TAG_FOCAL_LENGTH);
-        if (focalTag != null) {
-            details.addDetail(MediaDetails.INDEX_FOCAL_LENGTH,
-                    focalTag.getValueAsRational(0).toDouble());
-            details.setUnit(MediaDetails.INDEX_FOCAL_LENGTH, R.string.unit_mm);
-        }
-    }
-}
diff --git a/src/com/android/gallery3d/data/MediaItem.java b/src/com/android/gallery3d/data/MediaItem.java
deleted file mode 100644
index 59ea865..0000000
--- a/src/com/android/gallery3d/data/MediaItem.java
+++ /dev/null
@@ -1,134 +0,0 @@
-/*
- * Copyright (C) 2010 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.gallery3d.data;
-
-import android.graphics.Bitmap;
-import android.graphics.BitmapRegionDecoder;
-
-import com.android.gallery3d.common.ApiHelper;
-import com.android.gallery3d.ui.ScreenNail;
-import com.android.gallery3d.util.ThreadPool.Job;
-
-// MediaItem represents an image or a video item.
-public abstract class MediaItem extends MediaObject {
-    // NOTE: These type numbers are stored in the image cache, so it should not
-    // not be changed without resetting the cache.
-    public static final int TYPE_THUMBNAIL = 1;
-    public static final int TYPE_MICROTHUMBNAIL = 2;
-
-    public static final int CACHED_IMAGE_QUALITY = 95;
-
-    public static final int IMAGE_READY = 0;
-    public static final int IMAGE_WAIT = 1;
-    public static final int IMAGE_ERROR = -1;
-
-    public static final String MIME_TYPE_JPEG = "image/jpeg";
-
-    private static final int BYTESBUFFE_POOL_SIZE = 4;
-    private static final int BYTESBUFFER_SIZE = 200 * 1024;
-
-    private static int sMicrothumbnailTargetSize = 200;
-    private static final BytesBufferPool sMicroThumbBufferPool =
-            new BytesBufferPool(BYTESBUFFE_POOL_SIZE, BYTESBUFFER_SIZE);
-
-    private static int sThumbnailTargetSize = 640;
-
-    // TODO: fix default value for latlng and change this.
-    public static final double INVALID_LATLNG = 0f;
-
-    public abstract Job<Bitmap> requestImage(int type);
-    public abstract Job<BitmapRegionDecoder> requestLargeImage();
-
-    public MediaItem(Path path, long version) {
-        super(path, version);
-    }
-
-    public long getDateInMs() {
-        return 0;
-    }
-
-    public String getName() {
-        return null;
-    }
-
-    public void getLatLong(double[] latLong) {
-        latLong[0] = INVALID_LATLNG;
-        latLong[1] = INVALID_LATLNG;
-    }
-
-    public String[] getTags() {
-        return null;
-    }
-
-    public Face[] getFaces() {
-        return null;
-    }
-
-    // The rotation of the full-resolution image. By default, it returns the value of
-    // getRotation().
-    public int getFullImageRotation() {
-        return getRotation();
-    }
-
-    public int getRotation() {
-        return 0;
-    }
-
-    public long getSize() {
-        return 0;
-    }
-
-    public abstract String getMimeType();
-
-    public String getFilePath() {
-        return "";
-    }
-
-    // Returns width and height of the media item.
-    // Returns 0, 0 if the information is not available.
-    public abstract int getWidth();
-    public abstract int getHeight();
-
-    // This is an alternative for requestImage() in PhotoPage. If this
-    // is implemented, you don't need to implement requestImage().
-    public ScreenNail getScreenNail() {
-        return null;
-    }
-
-    public static int getTargetSize(int type) {
-        switch (type) {
-            case TYPE_THUMBNAIL:
-                return sThumbnailTargetSize;
-            case TYPE_MICROTHUMBNAIL:
-                return sMicrothumbnailTargetSize;
-            default:
-                throw new RuntimeException(
-                    "should only request thumb/microthumb from cache");
-        }
-    }
-
-    public static BytesBufferPool getBytesBufferPool() {
-        return sMicroThumbBufferPool;
-    }
-
-    public static void setThumbnailSizes(int size, int microSize) {
-        sThumbnailTargetSize = size;
-        if (sMicrothumbnailTargetSize != microSize) {
-            sMicrothumbnailTargetSize = microSize;
-        }
-    }
-}
diff --git a/src/com/android/gallery3d/data/MediaObject.java b/src/com/android/gallery3d/data/MediaObject.java
deleted file mode 100644
index 270d4cf..0000000
--- a/src/com/android/gallery3d/data/MediaObject.java
+++ /dev/null
@@ -1,166 +0,0 @@
-/*
- * Copyright (C) 2010 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.gallery3d.data;
-
-import android.net.Uri;
-
-public abstract class MediaObject {
-    @SuppressWarnings("unused")
-    private static final String TAG = "MediaObject";
-    public static final long INVALID_DATA_VERSION = -1;
-
-    // These are the bits returned from getSupportedOperations():
-    public static final int SUPPORT_DELETE = 1 << 0;
-    public static final int SUPPORT_ROTATE = 1 << 1;
-    public static final int SUPPORT_SHARE = 1 << 2;
-    public static final int SUPPORT_CROP = 1 << 3;
-    public static final int SUPPORT_SHOW_ON_MAP = 1 << 4;
-    public static final int SUPPORT_SETAS = 1 << 5;
-    public static final int SUPPORT_FULL_IMAGE = 1 << 6;
-    public static final int SUPPORT_PLAY = 1 << 7;
-    public static final int SUPPORT_CACHE = 1 << 8;
-    public static final int SUPPORT_EDIT = 1 << 9;
-    public static final int SUPPORT_INFO = 1 << 10;
-    public static final int SUPPORT_TRIM = 1 << 11;
-    public static final int SUPPORT_UNLOCK = 1 << 12;
-    public static final int SUPPORT_BACK = 1 << 13;
-    public static final int SUPPORT_ACTION = 1 << 14;
-    public static final int SUPPORT_CAMERA_SHORTCUT = 1 << 15;
-    public static final int SUPPORT_MUTE = 1 << 16;
-    public static final int SUPPORT_ALL = 0xffffffff;
-
-    // These are the bits returned from getMediaType():
-    public static final int MEDIA_TYPE_UNKNOWN = 1;
-    public static final int MEDIA_TYPE_IMAGE = 2;
-    public static final int MEDIA_TYPE_VIDEO = 4;
-    public static final int MEDIA_TYPE_ALL = MEDIA_TYPE_IMAGE | MEDIA_TYPE_VIDEO;
-
-    public static final String MEDIA_TYPE_IMAGE_STRING = "image";
-    public static final String MEDIA_TYPE_VIDEO_STRING = "video";
-    public static final String MEDIA_TYPE_ALL_STRING = "all";
-
-    // These are flags for cache() and return values for getCacheFlag():
-    public static final int CACHE_FLAG_NO = 0;
-    public static final int CACHE_FLAG_SCREENNAIL = 1;
-    public static final int CACHE_FLAG_FULL = 2;
-
-    // These are return values for getCacheStatus():
-    public static final int CACHE_STATUS_NOT_CACHED = 0;
-    public static final int CACHE_STATUS_CACHING = 1;
-    public static final int CACHE_STATUS_CACHED_SCREENNAIL = 2;
-    public static final int CACHE_STATUS_CACHED_FULL = 3;
-
-    private static long sVersionSerial = 0;
-
-    protected long mDataVersion;
-
-    protected final Path mPath;
-
-    public interface PanoramaSupportCallback {
-        void panoramaInfoAvailable(MediaObject mediaObject, boolean isPanorama,
-                boolean isPanorama360);
-    }
-
-    public MediaObject(Path path, long version) {
-        path.setObject(this);
-        mPath = path;
-        mDataVersion = version;
-    }
-
-    public Path getPath() {
-        return mPath;
-    }
-
-    public int getSupportedOperations() {
-        return 0;
-    }
-
-    public void getPanoramaSupport(PanoramaSupportCallback callback) {
-        callback.panoramaInfoAvailable(this, false, false);
-    }
-
-    public void clearCachedPanoramaSupport() {
-    }
-
-    public void delete() {
-        throw new UnsupportedOperationException();
-    }
-
-    public void rotate(int degrees) {
-        throw new UnsupportedOperationException();
-    }
-
-    public Uri getContentUri() {
-        String className = getClass().getName();
-        Log.e(TAG, "Class " + className + "should implement getContentUri.");
-        Log.e(TAG, "The object was created from path: " + getPath());
-        throw new UnsupportedOperationException();
-    }
-
-    public Uri getPlayUri() {
-        throw new UnsupportedOperationException();
-    }
-
-    public int getMediaType() {
-        return MEDIA_TYPE_UNKNOWN;
-    }
-
-    public MediaDetails getDetails() {
-        MediaDetails details = new MediaDetails();
-        return details;
-    }
-
-    public long getDataVersion() {
-        return mDataVersion;
-    }
-
-    public int getCacheFlag() {
-        return CACHE_FLAG_NO;
-    }
-
-    public int getCacheStatus() {
-        throw new UnsupportedOperationException();
-    }
-
-    public long getCacheSize() {
-        throw new UnsupportedOperationException();
-    }
-
-    public void cache(int flag) {
-        throw new UnsupportedOperationException();
-    }
-
-    public static synchronized long nextVersionNumber() {
-        return ++MediaObject.sVersionSerial;
-    }
-
-    public static int getTypeFromString(String s) {
-        if (MEDIA_TYPE_ALL_STRING.equals(s)) return MediaObject.MEDIA_TYPE_ALL;
-        if (MEDIA_TYPE_IMAGE_STRING.equals(s)) return MediaObject.MEDIA_TYPE_IMAGE;
-        if (MEDIA_TYPE_VIDEO_STRING.equals(s)) return MediaObject.MEDIA_TYPE_VIDEO;
-        throw new IllegalArgumentException(s);
-    }
-
-    public static String getTypeString(int type) {
-        switch (type) {
-            case MEDIA_TYPE_IMAGE: return MEDIA_TYPE_IMAGE_STRING;
-            case MEDIA_TYPE_VIDEO: return MEDIA_TYPE_VIDEO_STRING;
-            case MEDIA_TYPE_ALL: return MEDIA_TYPE_ALL_STRING;
-        }
-        throw new IllegalArgumentException();
-    }
-}
diff --git a/src/com/android/gallery3d/data/MediaSet.java b/src/com/android/gallery3d/data/MediaSet.java
deleted file mode 100644
index 683aa6b..0000000
--- a/src/com/android/gallery3d/data/MediaSet.java
+++ /dev/null
@@ -1,348 +0,0 @@
-/*
- * Copyright (C) 2010 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.gallery3d.data;
-
-import com.android.gallery3d.common.Utils;
-import com.android.gallery3d.util.Future;
-
-import java.util.ArrayList;
-import java.util.WeakHashMap;
-
-// MediaSet is a directory-like data structure.
-// It contains MediaItems and sub-MediaSets.
-//
-// The primary interface are:
-// getMediaItemCount(), getMediaItem() and
-// getSubMediaSetCount(), getSubMediaSet().
-//
-// getTotalMediaItemCount() returns the number of all MediaItems, including
-// those in sub-MediaSets.
-public abstract class MediaSet extends MediaObject {
-    @SuppressWarnings("unused")
-    private static final String TAG = "MediaSet";
-
-    public static final int MEDIAITEM_BATCH_FETCH_COUNT = 500;
-    public static final int INDEX_NOT_FOUND = -1;
-
-    public static final int SYNC_RESULT_SUCCESS = 0;
-    public static final int SYNC_RESULT_CANCELLED = 1;
-    public static final int SYNC_RESULT_ERROR = 2;
-
-    /** Listener to be used with requestSync(SyncListener). */
-    public static interface SyncListener {
-        /**
-         * Called when the sync task completed. Completion may be due to normal termination,
-         * an exception, or cancellation.
-         *
-         * @param mediaSet the MediaSet that's done with sync
-         * @param resultCode one of the SYNC_RESULT_* constants
-         */
-        void onSyncDone(MediaSet mediaSet, int resultCode);
-    }
-
-    public MediaSet(Path path, long version) {
-        super(path, version);
-    }
-
-    public int getMediaItemCount() {
-        return 0;
-    }
-
-    // Returns the media items in the range [start, start + count).
-    //
-    // The number of media items returned may be less than the specified count
-    // if there are not enough media items available. The number of
-    // media items available may not be consistent with the return value of
-    // getMediaItemCount() because the contents of database may have already
-    // changed.
-    public ArrayList<MediaItem> getMediaItem(int start, int count) {
-        return new ArrayList<MediaItem>();
-    }
-
-    public MediaItem getCoverMediaItem() {
-        ArrayList<MediaItem> items = getMediaItem(0, 1);
-        if (items.size() > 0) return items.get(0);
-        for (int i = 0, n = getSubMediaSetCount(); i < n; i++) {
-            MediaItem cover = getSubMediaSet(i).getCoverMediaItem();
-            if (cover != null) return cover;
-        }
-        return null;
-    }
-
-    public int getSubMediaSetCount() {
-        return 0;
-    }
-
-    public MediaSet getSubMediaSet(int index) {
-        throw new IndexOutOfBoundsException();
-    }
-
-    public boolean isLeafAlbum() {
-        return false;
-    }
-
-    public boolean isCameraRoll() {
-        return false;
-    }
-
-    /**
-     * Method {@link #reload()} may process the loading task in background, this method tells
-     * its client whether the loading is still in process or not.
-     */
-    public boolean isLoading() {
-        return false;
-    }
-
-    public int getTotalMediaItemCount() {
-        int total = getMediaItemCount();
-        for (int i = 0, n = getSubMediaSetCount(); i < n; i++) {
-            total += getSubMediaSet(i).getTotalMediaItemCount();
-        }
-        return total;
-    }
-
-    // TODO: we should have better implementation of sub classes
-    public int getIndexOfItem(Path path, int hint) {
-        // hint < 0 is handled below
-        // first, try to find it around the hint
-        int start = Math.max(0,
-                hint - MEDIAITEM_BATCH_FETCH_COUNT / 2);
-        ArrayList<MediaItem> list = getMediaItem(
-                start, MEDIAITEM_BATCH_FETCH_COUNT);
-        int index = getIndexOf(path, list);
-        if (index != INDEX_NOT_FOUND) return start + index;
-
-        // try to find it globally
-        start = start == 0 ? MEDIAITEM_BATCH_FETCH_COUNT : 0;
-        list = getMediaItem(start, MEDIAITEM_BATCH_FETCH_COUNT);
-        while (true) {
-            index = getIndexOf(path, list);
-            if (index != INDEX_NOT_FOUND) return start + index;
-            if (list.size() < MEDIAITEM_BATCH_FETCH_COUNT) return INDEX_NOT_FOUND;
-            start += MEDIAITEM_BATCH_FETCH_COUNT;
-            list = getMediaItem(start, MEDIAITEM_BATCH_FETCH_COUNT);
-        }
-    }
-
-    protected int getIndexOf(Path path, ArrayList<MediaItem> list) {
-        for (int i = 0, n = list.size(); i < n; ++i) {
-            // item could be null only in ClusterAlbum
-            MediaObject item = list.get(i);
-            if (item != null && item.mPath == path) return i;
-        }
-        return INDEX_NOT_FOUND;
-    }
-
-    public abstract String getName();
-
-    private WeakHashMap<ContentListener, Object> mListeners =
-            new WeakHashMap<ContentListener, Object>();
-
-    // NOTE: The MediaSet only keeps a weak reference to the listener. The
-    // listener is automatically removed when there is no other reference to
-    // the listener.
-    public void addContentListener(ContentListener listener) {
-        mListeners.put(listener, null);
-    }
-
-    public void removeContentListener(ContentListener listener) {
-        mListeners.remove(listener);
-    }
-
-    // This should be called by subclasses when the content is changed.
-    public void notifyContentChanged() {
-        for (ContentListener listener : mListeners.keySet()) {
-            listener.onContentDirty();
-        }
-    }
-
-    // Reload the content. Return the current data version. reload() should be called
-    // in the same thread as getMediaItem(int, int) and getSubMediaSet(int).
-    public abstract long reload();
-
-    @Override
-    public MediaDetails getDetails() {
-        MediaDetails details = super.getDetails();
-        details.addDetail(MediaDetails.INDEX_TITLE, getName());
-        return details;
-    }
-
-    // Enumerate all media items in this media set (including the ones in sub
-    // media sets), in an efficient order. ItemConsumer.consumer() will be
-    // called for each media item with its index.
-    public void enumerateMediaItems(ItemConsumer consumer) {
-        enumerateMediaItems(consumer, 0);
-    }
-
-    public void enumerateTotalMediaItems(ItemConsumer consumer) {
-        enumerateTotalMediaItems(consumer, 0);
-    }
-
-    public static interface ItemConsumer {
-        void consume(int index, MediaItem item);
-    }
-
-    // The default implementation uses getMediaItem() for enumerateMediaItems().
-    // Subclasses may override this and use more efficient implementations.
-    // Returns the number of items enumerated.
-    protected int enumerateMediaItems(ItemConsumer consumer, int startIndex) {
-        int total = getMediaItemCount();
-        int start = 0;
-        while (start < total) {
-            int count = Math.min(MEDIAITEM_BATCH_FETCH_COUNT, total - start);
-            ArrayList<MediaItem> items = getMediaItem(start, count);
-            for (int i = 0, n = items.size(); i < n; i++) {
-                MediaItem item = items.get(i);
-                consumer.consume(startIndex + start + i, item);
-            }
-            start += count;
-        }
-        return total;
-    }
-
-    // Recursively enumerate all media items under this set.
-    // Returns the number of items enumerated.
-    protected int enumerateTotalMediaItems(
-            ItemConsumer consumer, int startIndex) {
-        int start = 0;
-        start += enumerateMediaItems(consumer, startIndex);
-        int m = getSubMediaSetCount();
-        for (int i = 0; i < m; i++) {
-            start += getSubMediaSet(i).enumerateTotalMediaItems(
-                    consumer, startIndex + start);
-        }
-        return start;
-    }
-
-    /**
-     * Requests sync on this MediaSet. It returns a Future object that can be used by the caller
-     * to query the status of the sync. The sync result code is one of the SYNC_RESULT_* constants
-     * defined in this class and can be obtained by Future.get().
-     *
-     * Subclasses should perform sync on a different thread.
-     *
-     * The default implementation here returns a Future stub that does nothing and returns
-     * SYNC_RESULT_SUCCESS by get().
-     */
-    public Future<Integer> requestSync(SyncListener listener) {
-        listener.onSyncDone(this, SYNC_RESULT_SUCCESS);
-        return FUTURE_STUB;
-    }
-
-    private static final Future<Integer> FUTURE_STUB = new Future<Integer>() {
-        @Override
-        public void cancel() {}
-
-        @Override
-        public boolean isCancelled() {
-            return false;
-        }
-
-        @Override
-        public boolean isDone() {
-            return true;
-        }
-
-        @Override
-        public Integer get() {
-            return SYNC_RESULT_SUCCESS;
-        }
-
-        @Override
-        public void waitDone() {}
-    };
-
-    protected Future<Integer> requestSyncOnMultipleSets(MediaSet[] sets, SyncListener listener) {
-        return new MultiSetSyncFuture(sets, listener);
-    }
-
-    private class MultiSetSyncFuture implements Future<Integer>, SyncListener {
-        @SuppressWarnings("hiding")
-        private static final String TAG = "Gallery.MultiSetSync";
-
-        private final SyncListener mListener;
-        private final Future<Integer> mFutures[];
-
-        private boolean mIsCancelled = false;
-        private int mResult = -1;
-        private int mPendingCount;
-
-        @SuppressWarnings("unchecked")
-        MultiSetSyncFuture(MediaSet[] sets, SyncListener listener) {
-            mListener = listener;
-            mPendingCount = sets.length;
-            mFutures = new Future[sets.length];
-
-            synchronized (this) {
-                for (int i = 0, n = sets.length; i < n; ++i) {
-                    mFutures[i] = sets[i].requestSync(this);
-                    Log.d(TAG, "  request sync: " + Utils.maskDebugInfo(sets[i].getName()));
-                }
-            }
-        }
-
-        @Override
-        public synchronized void cancel() {
-            if (mIsCancelled) return;
-            mIsCancelled = true;
-            for (Future<Integer> future : mFutures) future.cancel();
-            if (mResult < 0) mResult = SYNC_RESULT_CANCELLED;
-        }
-
-        @Override
-        public synchronized boolean isCancelled() {
-            return mIsCancelled;
-        }
-
-        @Override
-        public synchronized boolean isDone() {
-            return mPendingCount == 0;
-        }
-
-        @Override
-        public synchronized Integer get() {
-            waitDone();
-            return mResult;
-        }
-
-        @Override
-        public synchronized void waitDone() {
-            try {
-                while (!isDone()) wait();
-            } catch (InterruptedException e) {
-                Log.d(TAG, "waitDone() interrupted");
-            }
-        }
-
-        // SyncListener callback
-        @Override
-        public void onSyncDone(MediaSet mediaSet, int resultCode) {
-            SyncListener listener = null;
-            synchronized (this) {
-                if (resultCode == SYNC_RESULT_ERROR) mResult = SYNC_RESULT_ERROR;
-                --mPendingCount;
-                if (mPendingCount == 0) {
-                    listener = mListener;
-                    notifyAll();
-                }
-                Log.d(TAG, "onSyncDone: " + Utils.maskDebugInfo(mediaSet.getName())
-                        + " #pending=" + mPendingCount);
-            }
-            if (listener != null) listener.onSyncDone(MediaSet.this, mResult);
-        }
-    }
-}
diff --git a/src/com/android/gallery3d/data/MediaSource.java b/src/com/android/gallery3d/data/MediaSource.java
deleted file mode 100644
index 9590128..0000000
--- a/src/com/android/gallery3d/data/MediaSource.java
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- * Copyright (C) 2010 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.gallery3d.data;
-
-import android.net.Uri;
-
-import com.android.gallery3d.data.MediaSet.ItemConsumer;
-
-import java.util.ArrayList;
-
-public abstract class MediaSource {
-    private static final String TAG = "MediaSource";
-    private String mPrefix;
-
-    protected MediaSource(String prefix) {
-        mPrefix = prefix;
-    }
-
-    public String getPrefix() {
-        return mPrefix;
-    }
-
-    public Path findPathByUri(Uri uri, String type) {
-        return null;
-    }
-
-    public abstract MediaObject createMediaObject(Path path);
-
-    public void pause() {
-    }
-
-    public void resume() {
-    }
-
-    public Path getDefaultSetOf(Path item) {
-        return null;
-    }
-
-    public long getTotalUsedCacheSize() {
-        return 0;
-    }
-
-    public long getTotalTargetCacheSize() {
-        return 0;
-    }
-
-    public static class PathId {
-        public PathId(Path path, int id) {
-            this.path = path;
-            this.id = id;
-        }
-        public Path path;
-        public int id;
-    }
-
-    // Maps a list of Paths (all belong to this MediaSource) to MediaItems,
-    // and invoke consumer.consume() for each MediaItem with the given id.
-    //
-    // This default implementation uses getMediaObject for each Path. Subclasses
-    // may override this and provide more efficient implementation (like
-    // batching the database query).
-    public void mapMediaItems(ArrayList<PathId> list, ItemConsumer consumer) {
-        int n = list.size();
-        for (int i = 0; i < n; i++) {
-            PathId pid = list.get(i);
-            MediaObject obj;
-            synchronized (DataManager.LOCK) {
-                obj = pid.path.getObject();
-                if (obj == null) {
-                    try {
-                        obj = createMediaObject(pid.path);
-                    } catch (Throwable th) {
-                        Log.w(TAG, "cannot create media object: " + pid.path, th);
-                    }
-                }
-            }
-            if (obj != null) {
-                consumer.consume(pid.id, (MediaItem) obj);
-            }
-        }
-    }
-}
diff --git a/src/com/android/gallery3d/data/MtpClient.java b/src/com/android/gallery3d/data/MtpClient.java
deleted file mode 100644
index 737b5b6..0000000
--- a/src/com/android/gallery3d/data/MtpClient.java
+++ /dev/null
@@ -1,443 +0,0 @@
-/*
- * Copyright (C) 2010 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.gallery3d.data;
-
-import android.annotation.TargetApi;
-import android.app.PendingIntent;
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.hardware.usb.UsbConstants;
-import android.hardware.usb.UsbDevice;
-import android.hardware.usb.UsbDeviceConnection;
-import android.hardware.usb.UsbInterface;
-import android.hardware.usb.UsbManager;
-import android.mtp.MtpDevice;
-import android.mtp.MtpObjectInfo;
-import android.mtp.MtpStorageInfo;
-import android.util.Log;
-
-import com.android.gallery3d.common.ApiHelper;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-
-/**
- * This class helps an application manage a list of connected MTP or PTP devices.
- * It listens for MTP devices being attached and removed from the USB host bus
- * and notifies the application when the MTP device list changes.
- */
-@TargetApi(ApiHelper.VERSION_CODES.HONEYCOMB_MR1)
-public class MtpClient {
-
-    private static final String TAG = "MtpClient";
-
-    private static final String ACTION_USB_PERMISSION =
-            "android.mtp.MtpClient.action.USB_PERMISSION";
-
-    private final Context mContext;
-    private final UsbManager mUsbManager;
-    private final ArrayList<Listener> mListeners = new ArrayList<Listener>();
-    // mDevices contains all MtpDevices that have been seen by our client,
-    // so we can inform when the device has been detached.
-    // mDevices is also used for synchronization in this class.
-    private final HashMap<String, MtpDevice> mDevices = new HashMap<String, MtpDevice>();
-    // List of MTP devices we should not try to open for which we are currently
-    // asking for permission to open.
-    private final ArrayList<String> mRequestPermissionDevices = new ArrayList<String>();
-    // List of MTP devices we should not try to open.
-    // We add devices to this list if the user canceled a permission request or we were
-    // unable to open the device.
-    private final ArrayList<String> mIgnoredDevices = new ArrayList<String>();
-
-    private final PendingIntent mPermissionIntent;
-
-    private final BroadcastReceiver mUsbReceiver = new BroadcastReceiver() {
-        @Override
-        public void onReceive(Context context, Intent intent) {
-            String action = intent.getAction();
-            UsbDevice usbDevice = (UsbDevice)intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);
-            String deviceName = usbDevice.getDeviceName();
-
-            synchronized (mDevices) {
-                MtpDevice mtpDevice = mDevices.get(deviceName);
-
-                if (UsbManager.ACTION_USB_DEVICE_ATTACHED.equals(action)) {
-                    if (mtpDevice == null) {
-                        mtpDevice = openDeviceLocked(usbDevice);
-                    }
-                    if (mtpDevice != null) {
-                        for (Listener listener : mListeners) {
-                            listener.deviceAdded(mtpDevice);
-                        }
-                    }
-                } else if (UsbManager.ACTION_USB_DEVICE_DETACHED.equals(action)) {
-                    if (mtpDevice != null) {
-                        mDevices.remove(deviceName);
-                        mRequestPermissionDevices.remove(deviceName);
-                        mIgnoredDevices.remove(deviceName);
-                        for (Listener listener : mListeners) {
-                            listener.deviceRemoved(mtpDevice);
-                        }
-                    }
-                } else if (ACTION_USB_PERMISSION.equals(action)) {
-                    mRequestPermissionDevices.remove(deviceName);
-                    boolean permission = intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED,
-                            false);
-                    Log.d(TAG, "ACTION_USB_PERMISSION: " + permission);
-                    if (permission) {
-                        if (mtpDevice == null) {
-                            mtpDevice = openDeviceLocked(usbDevice);
-                        }
-                        if (mtpDevice != null) {
-                            for (Listener listener : mListeners) {
-                                listener.deviceAdded(mtpDevice);
-                            }
-                        }
-                    } else {
-                        // so we don't ask for permission again
-                        mIgnoredDevices.add(deviceName);
-                    }
-                }
-            }
-        }
-    };
-
-    /**
-     * An interface for being notified when MTP or PTP devices are attached
-     * or removed.  In the current implementation, only PTP devices are supported.
-     */
-    public interface Listener {
-        /**
-         * Called when a new device has been added
-         *
-         * @param device the new device that was added
-         */
-        public void deviceAdded(MtpDevice device);
-
-        /**
-         * Called when a new device has been removed
-         *
-         * @param device the device that was removed
-         */
-        public void deviceRemoved(MtpDevice device);
-    }
-
-    /**
-     * Tests to see if a {@link android.hardware.usb.UsbDevice}
-     * supports the PTP protocol (typically used by digital cameras)
-     *
-     * @param device the device to test
-     * @return true if the device is a PTP device.
-     */
-    static public boolean isCamera(UsbDevice device) {
-        int count = device.getInterfaceCount();
-        for (int i = 0; i < count; i++) {
-            UsbInterface intf = device.getInterface(i);
-            if (intf.getInterfaceClass() == UsbConstants.USB_CLASS_STILL_IMAGE &&
-                    intf.getInterfaceSubclass() == 1 &&
-                    intf.getInterfaceProtocol() == 1) {
-                return true;
-            }
-        }
-        return false;
-    }
-
-    /**
-     * MtpClient constructor
-     *
-     * @param context the {@link android.content.Context} to use for the MtpClient
-     */
-    public MtpClient(Context context) {
-        mContext = context;
-        mUsbManager = (UsbManager)context.getSystemService(Context.USB_SERVICE);
-        mPermissionIntent = PendingIntent.getBroadcast(mContext, 0, new Intent(ACTION_USB_PERMISSION), 0);
-        IntentFilter filter = new IntentFilter();
-        filter.addAction(UsbManager.ACTION_USB_DEVICE_ATTACHED);
-        filter.addAction(UsbManager.ACTION_USB_DEVICE_DETACHED);
-        filter.addAction(ACTION_USB_PERMISSION);
-        context.registerReceiver(mUsbReceiver, filter);
-    }
-
-    /**
-     * Opens the {@link android.hardware.usb.UsbDevice} for an MTP or PTP
-     * device and return an {@link android.mtp.MtpDevice} for it.
-     *
-     * @param usbDevice the device to open
-     * @return an MtpDevice for the device.
-     */
-    private MtpDevice openDeviceLocked(UsbDevice usbDevice) {
-        String deviceName = usbDevice.getDeviceName();
-
-        // don't try to open devices that we have decided to ignore
-        // or are currently asking permission for
-        if (isCamera(usbDevice) && !mIgnoredDevices.contains(deviceName)
-                && !mRequestPermissionDevices.contains(deviceName)) {
-            if (!mUsbManager.hasPermission(usbDevice)) {
-                mUsbManager.requestPermission(usbDevice, mPermissionIntent);
-                mRequestPermissionDevices.add(deviceName);
-            } else {
-                UsbDeviceConnection connection = mUsbManager.openDevice(usbDevice);
-                if (connection != null) {
-                    MtpDevice mtpDevice = new MtpDevice(usbDevice);
-                    if (mtpDevice.open(connection)) {
-                        mDevices.put(usbDevice.getDeviceName(), mtpDevice);
-                        return mtpDevice;
-                    } else {
-                        // so we don't try to open it again
-                        mIgnoredDevices.add(deviceName);
-                    }
-                } else {
-                    // so we don't try to open it again
-                    mIgnoredDevices.add(deviceName);
-                }
-            }
-        }
-        return null;
-    }
-
-    /**
-     * Closes all resources related to the MtpClient object
-     */
-    public void close() {
-        mContext.unregisterReceiver(mUsbReceiver);
-    }
-
-    /**
-     * Registers a {@link com.android.gallery3d.data.MtpClient.Listener} interface to receive
-     * notifications when MTP or PTP devices are added or removed.
-     *
-     * @param listener the listener to register
-     */
-    public void addListener(Listener listener) {
-        synchronized (mDevices) {
-            if (!mListeners.contains(listener)) {
-                mListeners.add(listener);
-            }
-        }
-    }
-
-    /**
-     * Unregisters a {@link com.android.gallery3d.data.MtpClient.Listener} interface.
-     *
-     * @param listener the listener to unregister
-     */
-    public void removeListener(Listener listener) {
-        synchronized (mDevices) {
-            mListeners.remove(listener);
-        }
-    }
-
-    /**
-     * Retrieves an {@link android.mtp.MtpDevice} object for the USB device
-     * with the given name.
-     *
-     * @param deviceName the name of the USB device
-     * @return the MtpDevice, or null if it does not exist
-     */
-    public MtpDevice getDevice(String deviceName) {
-        synchronized (mDevices) {
-            return mDevices.get(deviceName);
-        }
-    }
-
-    /**
-     * Retrieves an {@link android.mtp.MtpDevice} object for the USB device
-     * with the given ID.
-     *
-     * @param id the ID of the USB device
-     * @return the MtpDevice, or null if it does not exist
-     */
-    public MtpDevice getDevice(int id) {
-        synchronized (mDevices) {
-            return mDevices.get(UsbDevice.getDeviceName(id));
-        }
-    }
-
-    /**
-     * Retrieves a list of all currently connected {@link android.mtp.MtpDevice}.
-     *
-     * @return the list of MtpDevices
-     */
-    public List<MtpDevice> getDeviceList() {
-        synchronized (mDevices) {
-            // Query the USB manager since devices might have attached
-            // before we added our listener.
-            for (UsbDevice usbDevice : mUsbManager.getDeviceList().values()) {
-                if (mDevices.get(usbDevice.getDeviceName()) == null) {
-                    openDeviceLocked(usbDevice);
-                }
-            }
-
-            return new ArrayList<MtpDevice>(mDevices.values());
-        }
-    }
-
-    /**
-     * Retrieves a list of all {@link android.mtp.MtpStorageInfo}
-     * for the MTP or PTP device with the given USB device name
-     *
-     * @param deviceName the name of the USB device
-     * @return the list of MtpStorageInfo
-     */
-    public List<MtpStorageInfo> getStorageList(String deviceName) {
-        MtpDevice device = getDevice(deviceName);
-        if (device == null) {
-            return null;
-        }
-        int[] storageIds = device.getStorageIds();
-        if (storageIds == null) {
-            return null;
-        }
-
-        int length = storageIds.length;
-        ArrayList<MtpStorageInfo> storageList = new ArrayList<MtpStorageInfo>(length);
-        for (int i = 0; i < length; i++) {
-            MtpStorageInfo info = device.getStorageInfo(storageIds[i]);
-            if (info == null) {
-                Log.w(TAG, "getStorageInfo failed");
-            } else {
-                storageList.add(info);
-            }
-        }
-        return storageList;
-    }
-
-    /**
-     * Retrieves the {@link android.mtp.MtpObjectInfo} for an object on
-     * the MTP or PTP device with the given USB device name with the given
-     * object handle
-     *
-     * @param deviceName the name of the USB device
-     * @param objectHandle handle of the object to query
-     * @return the MtpObjectInfo
-     */
-    public MtpObjectInfo getObjectInfo(String deviceName, int objectHandle) {
-        MtpDevice device = getDevice(deviceName);
-        if (device == null) {
-            return null;
-        }
-        return device.getObjectInfo(objectHandle);
-    }
-
-    /**
-     * Deletes an object on the MTP or PTP device with the given USB device name.
-     *
-     * @param deviceName the name of the USB device
-     * @param objectHandle handle of the object to delete
-     * @return true if the deletion succeeds
-     */
-    public boolean deleteObject(String deviceName, int objectHandle) {
-        MtpDevice device = getDevice(deviceName);
-        if (device == null) {
-            return false;
-        }
-        return device.deleteObject(objectHandle);
-    }
-
-    /**
-     * Retrieves a list of {@link android.mtp.MtpObjectInfo} for all objects
-     * on the MTP or PTP device with the given USB device name and given storage ID
-     * and/or object handle.
-     * If the object handle is zero, then all objects in the root of the storage unit
-     * will be returned. Otherwise, all immediate children of the object will be returned.
-     * If the storage ID is also zero, then all objects on all storage units will be returned.
-     *
-     * @param deviceName the name of the USB device
-     * @param storageId the ID of the storage unit to query, or zero for all
-     * @param objectHandle the handle of the parent object to query, or zero for the storage root
-     * @return the list of MtpObjectInfo
-     */
-    public List<MtpObjectInfo> getObjectList(String deviceName, int storageId, int objectHandle) {
-        MtpDevice device = getDevice(deviceName);
-        if (device == null) {
-            return null;
-        }
-        if (objectHandle == 0) {
-            // all objects in root of storage
-            objectHandle = 0xFFFFFFFF;
-        }
-        int[] handles = device.getObjectHandles(storageId, 0, objectHandle);
-        if (handles == null) {
-            return null;
-        }
-
-        int length = handles.length;
-        ArrayList<MtpObjectInfo> objectList = new ArrayList<MtpObjectInfo>(length);
-        for (int i = 0; i < length; i++) {
-            MtpObjectInfo info = device.getObjectInfo(handles[i]);
-            if (info == null) {
-                Log.w(TAG, "getObjectInfo failed");
-            } else {
-                objectList.add(info);
-            }
-        }
-        return objectList;
-    }
-
-    /**
-     * Returns the data for an object as a byte array.
-     *
-     * @param deviceName the name of the USB device containing the object
-     * @param objectHandle handle of the object to read
-     * @param objectSize the size of the object (this should match
-     *      {@link android.mtp.MtpObjectInfo#getCompressedSize}
-     * @return the object's data, or null if reading fails
-     */
-    public byte[] getObject(String deviceName, int objectHandle, int objectSize) {
-        MtpDevice device = getDevice(deviceName);
-        if (device == null) {
-            return null;
-        }
-        return device.getObject(objectHandle, objectSize);
-    }
-
-    /**
-     * Returns the thumbnail data for an object as a byte array.
-     *
-     * @param deviceName the name of the USB device containing the object
-     * @param objectHandle handle of the object to read
-     * @return the object's thumbnail, or null if reading fails
-     */
-    public byte[] getThumbnail(String deviceName, int objectHandle) {
-        MtpDevice device = getDevice(deviceName);
-        if (device == null) {
-            return null;
-        }
-        return device.getThumbnail(objectHandle);
-    }
-
-    /**
-     * Copies the data for an object to a file in external storage.
-     *
-     * @param deviceName the name of the USB device containing the object
-     * @param objectHandle handle of the object to read
-     * @param destPath path to destination for the file transfer.
-     *      This path should be in the external storage as defined by
-     *      {@link android.os.Environment#getExternalStorageDirectory}
-     * @return true if the file transfer succeeds
-     */
-    public boolean importFile(String deviceName, int objectHandle, String destPath) {
-        MtpDevice device = getDevice(deviceName);
-        if (device == null) {
-            return false;
-        }
-        return device.importFile(objectHandle, destPath);
-    }
-}
diff --git a/src/com/android/gallery3d/data/PanoramaMetadataJob.java b/src/com/android/gallery3d/data/PanoramaMetadataJob.java
deleted file mode 100644
index ab99d6a..0000000
--- a/src/com/android/gallery3d/data/PanoramaMetadataJob.java
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * 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.gallery3d.data;
-
-import android.content.Context;
-import android.net.Uri;
-
-import com.android.gallery3d.util.LightCycleHelper;
-import com.android.gallery3d.util.LightCycleHelper.PanoramaMetadata;
-import com.android.gallery3d.util.ThreadPool.Job;
-import com.android.gallery3d.util.ThreadPool.JobContext;
-
-public class PanoramaMetadataJob implements Job<PanoramaMetadata> {
-    Context mContext;
-    Uri mUri;
-
-    public PanoramaMetadataJob(Context context, Uri uri) {
-        mContext = context;
-        mUri = uri;
-    }
-
-    @Override
-    public PanoramaMetadata run(JobContext jc) {
-        return LightCycleHelper.getPanoramaMetadata(mContext, mUri);
-    }
-}
diff --git a/src/com/android/gallery3d/data/Path.java b/src/com/android/gallery3d/data/Path.java
deleted file mode 100644
index fcae65e..0000000
--- a/src/com/android/gallery3d/data/Path.java
+++ /dev/null
@@ -1,241 +0,0 @@
-/*
- * Copyright (C) 2010 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.gallery3d.data;
-
-import com.android.gallery3d.common.Utils;
-import com.android.gallery3d.util.IdentityCache;
-
-import java.lang.ref.WeakReference;
-import java.util.ArrayList;
-
-public class Path {
-    private static final String TAG = "Path";
-    private static Path sRoot = new Path(null, "ROOT");
-
-    private final Path mParent;
-    private final String mSegment;
-    private WeakReference<MediaObject> mObject;
-    private IdentityCache<String, Path> mChildren;
-
-    private Path(Path parent, String segment) {
-        mParent = parent;
-        mSegment = segment;
-    }
-
-    public Path getChild(String segment) {
-        synchronized (Path.class) {
-            if (mChildren == null) {
-                mChildren = new IdentityCache<String, Path>();
-            } else {
-                Path p = mChildren.get(segment);
-                if (p != null) return p;
-            }
-
-            Path p = new Path(this, segment);
-            mChildren.put(segment, p);
-            return p;
-        }
-    }
-
-    public Path getParent() {
-        synchronized (Path.class) {
-            return mParent;
-        }
-    }
-
-    public Path getChild(int segment) {
-        return getChild(String.valueOf(segment));
-    }
-
-    public Path getChild(long segment) {
-        return getChild(String.valueOf(segment));
-    }
-
-    public void setObject(MediaObject object) {
-        synchronized (Path.class) {
-            Utils.assertTrue(mObject == null || mObject.get() == null);
-            mObject = new WeakReference<MediaObject>(object);
-        }
-    }
-
-    MediaObject getObject() {
-        synchronized (Path.class) {
-            return (mObject == null) ? null : mObject.get();
-        }
-    }
-
-    @Override
-    // TODO: toString() should be more efficient, will fix it later
-    public String toString() {
-        synchronized (Path.class) {
-            StringBuilder sb = new StringBuilder();
-            String[] segments = split();
-            for (int i = 0; i < segments.length; i++) {
-                sb.append("/");
-                sb.append(segments[i]);
-            }
-            return sb.toString();
-        }
-    }
-
-    public boolean equalsIgnoreCase (String p) {
-        String path = toString();
-        return path.equalsIgnoreCase(p);
-    }
-
-    public static Path fromString(String s) {
-        synchronized (Path.class) {
-            String[] segments = split(s);
-            Path current = sRoot;
-            for (int i = 0; i < segments.length; i++) {
-                current = current.getChild(segments[i]);
-            }
-            return current;
-        }
-    }
-
-    public String[] split() {
-        synchronized (Path.class) {
-            int n = 0;
-            for (Path p = this; p != sRoot; p = p.mParent) {
-                n++;
-            }
-            String[] segments = new String[n];
-            int i = n - 1;
-            for (Path p = this; p != sRoot; p = p.mParent) {
-                segments[i--] = p.mSegment;
-            }
-            return segments;
-        }
-    }
-
-    public static String[] split(String s) {
-        int n = s.length();
-        if (n == 0) return new String[0];
-        if (s.charAt(0) != '/') {
-            throw new RuntimeException("malformed path:" + s);
-        }
-        ArrayList<String> segments = new ArrayList<String>();
-        int i = 1;
-        while (i < n) {
-            int brace = 0;
-            int j;
-            for (j = i; j < n; j++) {
-                char c = s.charAt(j);
-                if (c == '{') ++brace;
-                else if (c == '}') --brace;
-                else if (brace == 0 && c == '/') break;
-            }
-            if (brace != 0) {
-                throw new RuntimeException("unbalanced brace in path:" + s);
-            }
-            segments.add(s.substring(i, j));
-            i = j + 1;
-        }
-        String[] result = new String[segments.size()];
-        segments.toArray(result);
-        return result;
-    }
-
-    // Splits a string to an array of strings.
-    // For example, "{foo,bar,baz}" -> {"foo","bar","baz"}.
-    public static String[] splitSequence(String s) {
-        int n = s.length();
-        if (s.charAt(0) != '{' || s.charAt(n-1) != '}') {
-            throw new RuntimeException("bad sequence: " + s);
-        }
-        ArrayList<String> segments = new ArrayList<String>();
-        int i = 1;
-        while (i < n - 1) {
-            int brace = 0;
-            int j;
-            for (j = i; j < n - 1; j++) {
-                char c = s.charAt(j);
-                if (c == '{') ++brace;
-                else if (c == '}') --brace;
-                else if (brace == 0 && c == ',') break;
-            }
-            if (brace != 0) {
-                throw new RuntimeException("unbalanced brace in path:" + s);
-            }
-            segments.add(s.substring(i, j));
-            i = j + 1;
-        }
-        String[] result = new String[segments.size()];
-        segments.toArray(result);
-        return result;
-    }
-
-    public String getPrefix() {
-        if (this == sRoot) return "";
-        return getPrefixPath().mSegment;
-    }
-
-    public Path getPrefixPath() {
-        synchronized (Path.class) {
-            Path current = this;
-            if (current == sRoot) {
-                throw new IllegalStateException();
-            }
-            while (current.mParent != sRoot) {
-                current = current.mParent;
-            }
-            return current;
-        }
-    }
-
-    public String getSuffix() {
-        // We don't need lock because mSegment is final.
-        return mSegment;
-    }
-
-    // Below are for testing/debugging only
-    static void clearAll() {
-        synchronized (Path.class) {
-            sRoot = new Path(null, "");
-        }
-    }
-
-    static void dumpAll() {
-        dumpAll(sRoot, "", "");
-    }
-
-    static void dumpAll(Path p, String prefix1, String prefix2) {
-        synchronized (Path.class) {
-            MediaObject obj = p.getObject();
-            Log.d(TAG, prefix1 + p.mSegment + ":"
-                    + (obj == null ? "null" : obj.getClass().getSimpleName()));
-            if (p.mChildren != null) {
-                ArrayList<String> childrenKeys = p.mChildren.keys();
-                int i = 0, n = childrenKeys.size();
-                for (String key : childrenKeys) {
-                    Path child = p.mChildren.get(key);
-                    if (child == null) {
-                        ++i;
-                        continue;
-                    }
-                    Log.d(TAG, prefix2 + "|");
-                    if (++i < n) {
-                        dumpAll(child, prefix2 + "+-- ", prefix2 + "|   ");
-                    } else {
-                        dumpAll(child, prefix2 + "+-- ", prefix2 + "    ");
-                    }
-                }
-            }
-        }
-    }
-}
diff --git a/src/com/android/gallery3d/data/PathMatcher.java b/src/com/android/gallery3d/data/PathMatcher.java
deleted file mode 100644
index 9c6b840..0000000
--- a/src/com/android/gallery3d/data/PathMatcher.java
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- * Copyright (C) 2010 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.gallery3d.data;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-
-public class PathMatcher {
-    public static final int NOT_FOUND = -1;
-
-    private ArrayList<String> mVariables = new ArrayList<String>();
-    private Node mRoot = new Node();
-
-    public PathMatcher() {
-        mRoot = new Node();
-    }
-
-    public void add(String pattern, int kind) {
-        String[] segments = Path.split(pattern);
-        Node current = mRoot;
-        for (int i = 0; i < segments.length; i++) {
-            current = current.addChild(segments[i]);
-        }
-        current.setKind(kind);
-    }
-
-    public int match(Path path) {
-        String[] segments = path.split();
-        mVariables.clear();
-        Node current = mRoot;
-        for (int i = 0; i < segments.length; i++) {
-            Node next = current.getChild(segments[i]);
-            if (next == null) {
-                next = current.getChild("*");
-                if (next != null) {
-                    mVariables.add(segments[i]);
-                } else {
-                    return NOT_FOUND;
-                }
-            }
-            current = next;
-        }
-        return current.getKind();
-    }
-
-    public String getVar(int index) {
-        return mVariables.get(index);
-    }
-
-    public int getIntVar(int index) {
-        return Integer.parseInt(mVariables.get(index));
-    }
-
-    public long getLongVar(int index) {
-        return Long.parseLong(mVariables.get(index));
-    }
-
-    private static class Node {
-        private HashMap<String, Node> mMap;
-        private int mKind = NOT_FOUND;
-
-        Node addChild(String segment) {
-            if (mMap == null) {
-                mMap = new HashMap<String, Node>();
-            } else {
-                Node node = mMap.get(segment);
-                if (node != null) return node;
-            }
-
-            Node n = new Node();
-            mMap.put(segment, n);
-            return n;
-        }
-
-        Node getChild(String segment) {
-            if (mMap == null) return null;
-            return mMap.get(segment);
-        }
-
-        void setKind(int kind) {
-            mKind = kind;
-        }
-
-        int getKind() {
-            return mKind;
-        }
-    }
-}
diff --git a/src/com/android/gallery3d/data/SecureAlbum.java b/src/com/android/gallery3d/data/SecureAlbum.java
deleted file mode 100644
index 204f848..0000000
--- a/src/com/android/gallery3d/data/SecureAlbum.java
+++ /dev/null
@@ -1,206 +0,0 @@
-/*
- * 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.gallery3d.data;
-
-import android.content.Context;
-import android.database.Cursor;
-import android.net.Uri;
-import android.provider.MediaStore.Images;
-import android.provider.MediaStore.MediaColumns;
-import android.provider.MediaStore.Video;
-
-import com.android.gallery3d.app.GalleryApp;
-import com.android.gallery3d.app.StitchingChangeListener;
-import com.android.gallery3d.util.MediaSetUtils;
-
-import java.util.ArrayList;
-
-// This class lists all media items added by the client.
-public class SecureAlbum extends MediaSet implements StitchingChangeListener {
-    @SuppressWarnings("unused")
-    private static final String TAG = "SecureAlbum";
-    private static final String[] PROJECTION = {MediaColumns._ID};
-    private int mMinImageId = Integer.MAX_VALUE; // the smallest id of images
-    private int mMaxImageId = Integer.MIN_VALUE; // the biggest id in images
-    private int mMinVideoId = Integer.MAX_VALUE; // the smallest id of videos
-    private int mMaxVideoId = Integer.MIN_VALUE; // the biggest id of videos
-    // All the media items added by the client.
-    private ArrayList<Path> mAllItems = new ArrayList<Path>();
-    // The types of items in mAllItems. True is video and false is image.
-    private ArrayList<Boolean> mAllItemTypes = new ArrayList<Boolean>();
-    private ArrayList<Path> mExistingItems = new ArrayList<Path>();
-    private Context mContext;
-    private DataManager mDataManager;
-    private static final Uri[] mWatchUris =
-        {Images.Media.EXTERNAL_CONTENT_URI, Video.Media.EXTERNAL_CONTENT_URI};
-    private final ChangeNotifier mNotifier;
-    // A placeholder image in the end of secure album. When it is tapped, it
-    // will take the user to the lock screen.
-    private MediaItem mUnlockItem;
-    private boolean mShowUnlockItem;
-
-    public SecureAlbum(Path path, GalleryApp application, MediaItem unlock) {
-        super(path, nextVersionNumber());
-        mContext = application.getAndroidContext();
-        mDataManager = application.getDataManager();
-        mNotifier = new ChangeNotifier(this, mWatchUris, application);
-        mUnlockItem = unlock;
-        mShowUnlockItem = (!isCameraBucketEmpty(Images.Media.EXTERNAL_CONTENT_URI)
-                || !isCameraBucketEmpty(Video.Media.EXTERNAL_CONTENT_URI));
-    }
-
-    public void addMediaItem(boolean isVideo, int id) {
-        Path pathBase;
-        if (isVideo) {
-            pathBase = LocalVideo.ITEM_PATH;
-            mMinVideoId = Math.min(mMinVideoId, id);
-            mMaxVideoId = Math.max(mMaxVideoId, id);
-        } else {
-            pathBase = LocalImage.ITEM_PATH;
-            mMinImageId = Math.min(mMinImageId, id);
-            mMaxImageId = Math.max(mMaxImageId, id);
-        }
-        Path path = pathBase.getChild(id);
-        if (!mAllItems.contains(path)) {
-            mAllItems.add(path);
-            mAllItemTypes.add(isVideo);
-            mNotifier.fakeChange();
-        }
-    }
-
-    // The sequence is stitching items, local media items, and unlock image.
-    @Override
-    public ArrayList<MediaItem> getMediaItem(int start, int count) {
-        int existingCount = mExistingItems.size();
-        if (start >= existingCount + 1) {
-            return new ArrayList<MediaItem>();
-        }
-
-        // Add paths of requested stitching items.
-        int end = Math.min(start + count, existingCount);
-        ArrayList<Path> subset = new ArrayList<Path>(mExistingItems.subList(start, end));
-
-        // Convert paths to media items.
-        final MediaItem[] buf = new MediaItem[end - start];
-        ItemConsumer consumer = new ItemConsumer() {
-            @Override
-            public void consume(int index, MediaItem item) {
-                buf[index] = item;
-            }
-        };
-        mDataManager.mapMediaItems(subset, consumer, 0);
-        ArrayList<MediaItem> result = new ArrayList<MediaItem>(end - start);
-        for (int i = 0; i < buf.length; i++) {
-            result.add(buf[i]);
-        }
-        if (mShowUnlockItem) result.add(mUnlockItem);
-        return result;
-    }
-
-    @Override
-    public int getMediaItemCount() {
-        return (mExistingItems.size() + (mShowUnlockItem ? 1 : 0));
-    }
-
-    @Override
-    public String getName() {
-        return "secure";
-    }
-
-    @Override
-    public long reload() {
-        if (mNotifier.isDirty()) {
-            mDataVersion = nextVersionNumber();
-            updateExistingItems();
-        }
-        return mDataVersion;
-    }
-
-    private ArrayList<Integer> queryExistingIds(Uri uri, int minId, int maxId) {
-        ArrayList<Integer> ids = new ArrayList<Integer>();
-        if (minId == Integer.MAX_VALUE || maxId == Integer.MIN_VALUE) return ids;
-
-        String[] selectionArgs = {String.valueOf(minId), String.valueOf(maxId)};
-        Cursor cursor = mContext.getContentResolver().query(uri, PROJECTION,
-                "_id BETWEEN ? AND ?", selectionArgs, null);
-        if (cursor == null) return ids;
-        try {
-            while (cursor.moveToNext()) {
-                ids.add(cursor.getInt(0));
-            }
-        } finally {
-            cursor.close();
-        }
-        return ids;
-    }
-
-    private boolean isCameraBucketEmpty(Uri baseUri) {
-        Uri uri = baseUri.buildUpon()
-                .appendQueryParameter("limit", "1").build();
-        String[] selection = {String.valueOf(MediaSetUtils.CAMERA_BUCKET_ID)};
-        Cursor cursor = mContext.getContentResolver().query(uri, PROJECTION,
-                "bucket_id = ?", selection, null);
-        if (cursor == null) return true;
-        try {
-            return (cursor.getCount() == 0);
-        } finally {
-            cursor.close();
-        }
-    }
-
-    private void updateExistingItems() {
-        if (mAllItems.size() == 0) return;
-
-        // Query existing ids.
-        ArrayList<Integer> imageIds = queryExistingIds(
-                Images.Media.EXTERNAL_CONTENT_URI, mMinImageId, mMaxImageId);
-        ArrayList<Integer> videoIds = queryExistingIds(
-                Video.Media.EXTERNAL_CONTENT_URI, mMinVideoId, mMaxVideoId);
-
-        // Construct the existing items list.
-        mExistingItems.clear();
-        for (int i = mAllItems.size() - 1; i >= 0; i--) {
-            Path path = mAllItems.get(i);
-            boolean isVideo = mAllItemTypes.get(i);
-            int id = Integer.parseInt(path.getSuffix());
-            if (isVideo) {
-                if (videoIds.contains(id)) mExistingItems.add(path);
-            } else {
-                if (imageIds.contains(id)) mExistingItems.add(path);
-            }
-        }
-    }
-
-    @Override
-    public boolean isLeafAlbum() {
-        return true;
-    }
-
-    @Override
-    public void onStitchingQueued(Uri uri) {
-        int id = Integer.parseInt(uri.getLastPathSegment());
-        addMediaItem(false, id);
-    }
-
-    @Override
-    public void onStitchingResult(Uri uri) {
-    }
-
-    @Override
-    public void onStitchingProgress(Uri uri, final int progress) {
-    }
-}
diff --git a/src/com/android/gallery3d/data/SecureSource.java b/src/com/android/gallery3d/data/SecureSource.java
deleted file mode 100644
index 6bc8cc2..0000000
--- a/src/com/android/gallery3d/data/SecureSource.java
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * 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.gallery3d.data;
-
-import com.android.gallery3d.app.GalleryApp;
-
-public class SecureSource extends MediaSource {
-    private GalleryApp mApplication;
-    private static PathMatcher mMatcher = new PathMatcher();
-    private static final int SECURE_ALBUM = 0;
-    private static final int SECURE_UNLOCK = 1;
-
-    static {
-        mMatcher.add("/secure/all/*", SECURE_ALBUM);
-        mMatcher.add("/secure/unlock", SECURE_UNLOCK);
-    }
-
-    public SecureSource(GalleryApp context) {
-        super("secure");
-        mApplication = context;
-    }
-
-    public static boolean isSecurePath(String path) {
-        return (SECURE_ALBUM == mMatcher.match(Path.fromString(path)));
-    }
-
-    @Override
-    public MediaObject createMediaObject(Path path) {
-        switch (mMatcher.match(path)) {
-            case SECURE_ALBUM: {
-                DataManager dataManager = mApplication.getDataManager();
-                MediaItem unlock = (MediaItem) dataManager.getMediaObject(
-                        "/secure/unlock");
-                return new SecureAlbum(path, mApplication, unlock);
-            }
-            case SECURE_UNLOCK:
-                return new UnlockImage(path, mApplication);
-            default:
-                throw new RuntimeException("bad path: " + path);
-        }
-    }
-}
diff --git a/src/com/android/gallery3d/data/SingleItemAlbum.java b/src/com/android/gallery3d/data/SingleItemAlbum.java
deleted file mode 100644
index a0093e0..0000000
--- a/src/com/android/gallery3d/data/SingleItemAlbum.java
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * 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.gallery3d.data;
-
-import java.util.ArrayList;
-
-public class SingleItemAlbum extends MediaSet {
-    @SuppressWarnings("unused")
-    private static final String TAG = "SingleItemAlbum";
-    private final MediaItem mItem;
-    private final String mName;
-
-    public SingleItemAlbum(Path path, MediaItem item) {
-        super(path, nextVersionNumber());
-        mItem =  item;
-        mName = "SingleItemAlbum("+mItem.getClass().getSimpleName()+")";
-    }
-
-    @Override
-    public int getMediaItemCount() {
-        return 1;
-    }
-
-    @Override
-    public ArrayList<MediaItem> getMediaItem(int start, int count) {
-        ArrayList<MediaItem> result = new ArrayList<MediaItem>();
-
-        // If [start, start+count) contains the index 0, return the item.
-        if (start <= 0 && start + count > 0) {
-            result.add(mItem);
-        }
-
-        return result;
-    }
-
-    public MediaItem getItem() {
-        return mItem;
-    }
-
-    @Override
-    public boolean isLeafAlbum() {
-        return true;
-    }
-
-    @Override
-    public String getName() {
-        return mName;
-    }
-
-    @Override
-    public long reload() {
-        return mDataVersion;
-    }
-}
diff --git a/src/com/android/gallery3d/data/SizeClustering.java b/src/com/android/gallery3d/data/SizeClustering.java
deleted file mode 100644
index b809c84..0000000
--- a/src/com/android/gallery3d/data/SizeClustering.java
+++ /dev/null
@@ -1,141 +0,0 @@
-/*
- * Copyright (C) 2010 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.gallery3d.data;
-
-import android.content.Context;
-import android.content.res.Resources;
-
-import com.android.gallery3d.R;
-
-import java.util.ArrayList;
-
-public class SizeClustering extends Clustering {
-    @SuppressWarnings("unused")
-    private static final String TAG = "SizeClustering";
-
-    private Context mContext;
-    private ArrayList<Path>[] mClusters;
-    private String[] mNames;
-    private long mMinSizes[];
-
-    private static final long MEGA_BYTES = 1024L*1024;
-    private static final long GIGA_BYTES = 1024L*1024*1024;
-
-    private static final long[] SIZE_LEVELS = {
-        0,
-        1 * MEGA_BYTES,
-        10 * MEGA_BYTES,
-        100 * MEGA_BYTES,
-        1 * GIGA_BYTES,
-        2 * GIGA_BYTES,
-        4 * GIGA_BYTES,
-    };
-
-    public SizeClustering(Context context) {
-        mContext = context;
-    }
-
-    @SuppressWarnings("unchecked")
-    @Override
-    public void run(MediaSet baseSet) {
-        @SuppressWarnings("unchecked")
-        final ArrayList<Path>[] group = new ArrayList[SIZE_LEVELS.length];
-        baseSet.enumerateTotalMediaItems(new MediaSet.ItemConsumer() {
-            @Override
-            public void consume(int index, MediaItem item) {
-                // Find the cluster this item belongs to.
-                long size = item.getSize();
-                int i;
-                for (i = 0; i < SIZE_LEVELS.length - 1; i++) {
-                    if (size < SIZE_LEVELS[i + 1]) {
-                        break;
-                    }
-                }
-
-                ArrayList<Path> list = group[i];
-                if (list == null) {
-                    list = new ArrayList<Path>();
-                    group[i] = list;
-                }
-                list.add(item.getPath());
-            }
-        });
-
-        int count = 0;
-        for (int i = 0; i < group.length; i++) {
-            if (group[i] != null) {
-                count++;
-            }
-        }
-
-        mClusters = new ArrayList[count];
-        mNames = new String[count];
-        mMinSizes = new long[count];
-
-        Resources res = mContext.getResources();
-        int k = 0;
-        // Go through group in the reverse order, so the group with the largest
-        // size will show first.
-        for (int i = group.length - 1; i >= 0; i--) {
-            if (group[i] == null) continue;
-
-            mClusters[k] = group[i];
-            if (i == 0) {
-                mNames[k] = String.format(
-                        res.getString(R.string.size_below), getSizeString(i + 1));
-            } else if (i == group.length - 1) {
-                mNames[k] = String.format(
-                        res.getString(R.string.size_above), getSizeString(i));
-            } else {
-                String minSize = getSizeString(i);
-                String maxSize = getSizeString(i + 1);
-                mNames[k] = String.format(
-                        res.getString(R.string.size_between), minSize, maxSize);
-            }
-            mMinSizes[k] = SIZE_LEVELS[i];
-            k++;
-        }
-    }
-
-    private String getSizeString(int index) {
-        long bytes = SIZE_LEVELS[index];
-        if (bytes >= GIGA_BYTES) {
-            return (bytes / GIGA_BYTES) + "GB";
-        } else {
-            return (bytes / MEGA_BYTES) + "MB";
-        }
-    }
-
-    @Override
-    public int getNumberOfClusters() {
-        return mClusters.length;
-    }
-
-    @Override
-    public ArrayList<Path> getCluster(int index) {
-        return mClusters[index];
-    }
-
-    @Override
-    public String getClusterName(int index) {
-        return mNames[index];
-    }
-
-    public long getMinSize(int index) {
-        return mMinSizes[index];
-    }
-}
diff --git a/src/com/android/gallery3d/data/SnailAlbum.java b/src/com/android/gallery3d/data/SnailAlbum.java
deleted file mode 100644
index 7bce7a6..0000000
--- a/src/com/android/gallery3d/data/SnailAlbum.java
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * 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.gallery3d.data;
-
-import java.util.concurrent.atomic.AtomicBoolean;
-
-// This is a simple MediaSet which contains only one MediaItem -- a SnailItem.
-public class SnailAlbum extends SingleItemAlbum {
-    @SuppressWarnings("unused")
-    private static final String TAG = "SnailAlbum";
-    private AtomicBoolean mDirty = new AtomicBoolean(false);
-
-    public SnailAlbum(Path path, SnailItem item) {
-        super(path, item);
-    }
-
-    @Override
-    public long reload() {
-        if (mDirty.compareAndSet(true, false)) {
-            ((SnailItem) getItem()).updateVersion();
-            mDataVersion = nextVersionNumber();
-        }
-        return mDataVersion;
-    }
-
-    public void notifyChange() {
-        mDirty.set(true);
-        notifyContentChanged();
-    }
-}
diff --git a/src/com/android/gallery3d/data/SnailItem.java b/src/com/android/gallery3d/data/SnailItem.java
deleted file mode 100644
index 3586d2c..0000000
--- a/src/com/android/gallery3d/data/SnailItem.java
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- * 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.gallery3d.data;
-
-import android.graphics.Bitmap;
-import android.graphics.BitmapRegionDecoder;
-
-import com.android.gallery3d.ui.ScreenNail;
-import com.android.gallery3d.util.ThreadPool.Job;
-import com.android.gallery3d.util.ThreadPool.JobContext;
-
-// SnailItem is a MediaItem which can provide a ScreenNail. This is
-// used so we can show an foreign component (like an
-// android.view.View) instead of a Bitmap.
-public class SnailItem extends MediaItem {
-    @SuppressWarnings("unused")
-    private static final String TAG = "SnailItem";
-    private ScreenNail mScreenNail;
-
-    public SnailItem(Path path) {
-        super(path, nextVersionNumber());
-    }
-
-    @Override
-    public Job<Bitmap> requestImage(int type) {
-        // nothing to return
-        return new Job<Bitmap>() {
-            @Override
-            public Bitmap run(JobContext jc) {
-                return null;
-            }
-        };
-    }
-
-    @Override
-    public Job<BitmapRegionDecoder> requestLargeImage() {
-        // nothing to return
-        return new Job<BitmapRegionDecoder>() {
-            @Override
-            public BitmapRegionDecoder run(JobContext jc) {
-                return null;
-            }
-        };
-    }
-
-    // We do not provide requestImage or requestLargeImage, instead we
-    // provide a ScreenNail.
-    @Override
-    public ScreenNail getScreenNail() {
-        return mScreenNail;
-    }
-
-    @Override
-    public String getMimeType() {
-        return "";
-    }
-
-    // Returns width and height of the media item.
-    // Returns 0, 0 if the information is not available.
-    @Override
-    public int getWidth() {
-        return 0;
-    }
-
-    @Override
-    public int getHeight() {
-        return 0;
-    }
-
-    //////////////////////////////////////////////////////////////////////////
-    //  Extra methods for SnailItem
-    //////////////////////////////////////////////////////////////////////////
-
-    public void setScreenNail(ScreenNail screenNail) {
-        mScreenNail = screenNail;
-    }
-
-    public void updateVersion() {
-        mDataVersion = nextVersionNumber();
-    }
-}
diff --git a/src/com/android/gallery3d/data/SnailSource.java b/src/com/android/gallery3d/data/SnailSource.java
deleted file mode 100644
index 5c690cc..0000000
--- a/src/com/android/gallery3d/data/SnailSource.java
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * 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.gallery3d.data;
-
-import com.android.gallery3d.app.GalleryApp;
-
-public class SnailSource extends MediaSource {
-    @SuppressWarnings("unused")
-    private static final String TAG = "SnailSource";
-    private static final int SNAIL_ALBUM = 0;
-    private static final int SNAIL_ITEM = 1;
-
-    private GalleryApp mApplication;
-    private PathMatcher mMatcher;
-    private static int sNextId;
-
-    public SnailSource(GalleryApp application) {
-        super("snail");
-        mApplication = application;
-        mMatcher = new PathMatcher();
-        mMatcher.add("/snail/set/*", SNAIL_ALBUM);
-        mMatcher.add("/snail/item/*", SNAIL_ITEM);
-    }
-
-    // The only path we accept is "/snail/set/id" and "/snail/item/id"
-    @Override
-    public MediaObject createMediaObject(Path path) {
-        DataManager dataManager = mApplication.getDataManager();
-        switch (mMatcher.match(path)) {
-            case SNAIL_ALBUM:
-                String itemPath = "/snail/item/" + mMatcher.getVar(0);
-                SnailItem item =
-                        (SnailItem) dataManager.getMediaObject(itemPath);
-                return new SnailAlbum(path, item);
-            case SNAIL_ITEM: {
-                int id = mMatcher.getIntVar(0);
-                return new SnailItem(path);
-            }
-        }
-        return null;
-    }
-
-    // Registers a new SnailAlbum containing a SnailItem and returns the id of
-    // them. You can obtain the Path of the SnailAlbum and SnailItem associated
-    // with the id by getSetPath and getItemPath().
-    public static synchronized int newId() {
-        return sNextId++;
-    }
-
-    public static Path getSetPath(int id) {
-        return Path.fromString("/snail/set").getChild(id);
-    }
-
-    public static Path getItemPath(int id) {
-        return Path.fromString("/snail/item").getChild(id);
-    }
-}
diff --git a/src/com/android/gallery3d/data/TagClustering.java b/src/com/android/gallery3d/data/TagClustering.java
deleted file mode 100644
index 407ca84..0000000
--- a/src/com/android/gallery3d/data/TagClustering.java
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- * Copyright (C) 2010 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.gallery3d.data;
-
-import android.content.Context;
-
-import com.android.gallery3d.R;
-
-import java.util.ArrayList;
-import java.util.Map;
-import java.util.TreeMap;
-
-public class TagClustering extends Clustering {
-    @SuppressWarnings("unused")
-    private static final String TAG = "TagClustering";
-
-    private ArrayList<ArrayList<Path>> mClusters;
-    private String[] mNames;
-    private String mUntaggedString;
-
-    public TagClustering(Context context) {
-        mUntaggedString = context.getResources().getString(R.string.untagged);
-    }
-
-    @Override
-    public void run(MediaSet baseSet) {
-        final TreeMap<String, ArrayList<Path>> map =
-                new TreeMap<String, ArrayList<Path>>();
-        final ArrayList<Path> untagged = new ArrayList<Path>();
-
-        baseSet.enumerateTotalMediaItems(new MediaSet.ItemConsumer() {
-            @Override
-            public void consume(int index, MediaItem item) {
-                Path path = item.getPath();
-
-                String[] tags = item.getTags();
-                if (tags == null || tags.length == 0) {
-                    untagged.add(path);
-                    return;
-                }
-                for (int j = 0; j < tags.length; j++) {
-                    String key = tags[j];
-                    ArrayList<Path> list = map.get(key);
-                    if (list == null) {
-                        list = new ArrayList<Path>();
-                        map.put(key, list);
-                    }
-                    list.add(path);
-                }
-            }
-        });
-
-        int m = map.size();
-        mClusters = new ArrayList<ArrayList<Path>>();
-        mNames = new String[m + ((untagged.size() > 0) ? 1 : 0)];
-        int i = 0;
-        for (Map.Entry<String, ArrayList<Path>> entry : map.entrySet()) {
-            mNames[i++] = entry.getKey();
-            mClusters.add(entry.getValue());
-        }
-        if (untagged.size() > 0) {
-            mNames[i++] = mUntaggedString;
-            mClusters.add(untagged);
-        }
-    }
-
-    @Override
-    public int getNumberOfClusters() {
-        return mClusters.size();
-    }
-
-    @Override
-    public ArrayList<Path> getCluster(int index) {
-        return mClusters.get(index);
-    }
-
-    @Override
-    public String getClusterName(int index) {
-        return mNames[index];
-    }
-}
diff --git a/src/com/android/gallery3d/data/TimeClustering.java b/src/com/android/gallery3d/data/TimeClustering.java
deleted file mode 100644
index 35cbab1..0000000
--- a/src/com/android/gallery3d/data/TimeClustering.java
+++ /dev/null
@@ -1,439 +0,0 @@
-/*
- * Copyright (C) 2010 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.gallery3d.data;
-
-import android.content.Context;
-import android.text.format.DateFormat;
-import android.text.format.DateUtils;
-
-import com.android.gallery3d.common.Utils;
-import com.android.gallery3d.util.GalleryUtils;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Comparator;
-
-public class TimeClustering extends Clustering {
-    @SuppressWarnings("unused")
-    private static final String TAG = "TimeClustering";
-
-    // If 2 items are greater than 25 miles apart, they will be in different
-    // clusters.
-    private static final int GEOGRAPHIC_DISTANCE_CUTOFF_IN_MILES = 20;
-
-    // Do not want to split based on anything under 1 min.
-    private static final long MIN_CLUSTER_SPLIT_TIME_IN_MS = 60000L;
-
-    // Disregard a cluster split time of anything over 2 hours.
-    private static final long MAX_CLUSTER_SPLIT_TIME_IN_MS = 7200000L;
-
-    // Try and get around 9 clusters (best-effort for the common case).
-    private static final int NUM_CLUSTERS_TARGETED = 9;
-
-    // Try and merge 2 clusters if they are both smaller than min cluster size.
-    // The min cluster size can range from 8 to 15.
-    private static final int MIN_MIN_CLUSTER_SIZE = 8;
-    private static final int MAX_MIN_CLUSTER_SIZE = 15;
-
-    // Try and split a cluster if it is bigger than max cluster size.
-    // The max cluster size can range from 20 to 50.
-    private static final int MIN_MAX_CLUSTER_SIZE = 20;
-    private static final int MAX_MAX_CLUSTER_SIZE = 50;
-
-    // Initially put 2 items in the same cluster as long as they are within
-    // 3 cluster frequencies of each other.
-    private static int CLUSTER_SPLIT_MULTIPLIER = 3;
-
-    // The minimum change factor in the time between items to consider a
-    // partition.
-    // Example: (Item 3 - Item 2) / (Item 2 - Item 1).
-    private static final int MIN_PARTITION_CHANGE_FACTOR = 2;
-
-    // Make the cluster split time of a large cluster half that of a regular
-    // cluster.
-    private static final int PARTITION_CLUSTER_SPLIT_TIME_FACTOR = 2;
-
-    private Context mContext;
-    private ArrayList<Cluster> mClusters;
-    private String[] mNames;
-    private Cluster mCurrCluster;
-
-    private long mClusterSplitTime =
-            (MIN_CLUSTER_SPLIT_TIME_IN_MS + MAX_CLUSTER_SPLIT_TIME_IN_MS) / 2;
-    private long mLargeClusterSplitTime =
-            mClusterSplitTime / PARTITION_CLUSTER_SPLIT_TIME_FACTOR;
-    private int mMinClusterSize = (MIN_MIN_CLUSTER_SIZE + MAX_MIN_CLUSTER_SIZE) / 2;
-    private int mMaxClusterSize = (MIN_MAX_CLUSTER_SIZE + MAX_MAX_CLUSTER_SIZE) / 2;
-
-
-    private static final Comparator<SmallItem> sDateComparator =
-            new DateComparator();
-
-    private static class DateComparator implements Comparator<SmallItem> {
-        @Override
-        public int compare(SmallItem item1, SmallItem item2) {
-            return -Utils.compare(item1.dateInMs, item2.dateInMs);
-        }
-    }
-
-    public TimeClustering(Context context) {
-        mContext = context;
-        mClusters = new ArrayList<Cluster>();
-        mCurrCluster = new Cluster();
-    }
-
-    @Override
-    public void run(MediaSet baseSet) {
-        final int total = baseSet.getTotalMediaItemCount();
-        final SmallItem[] buf = new SmallItem[total];
-        final double[] latLng = new double[2];
-
-        baseSet.enumerateTotalMediaItems(new MediaSet.ItemConsumer() {
-            @Override
-            public void consume(int index, MediaItem item) {
-                if (index < 0 || index >= total) return;
-                SmallItem s = new SmallItem();
-                s.path = item.getPath();
-                s.dateInMs = item.getDateInMs();
-                item.getLatLong(latLng);
-                s.lat = latLng[0];
-                s.lng = latLng[1];
-                buf[index] = s;
-            }
-        });
-
-        ArrayList<SmallItem> items = new ArrayList<SmallItem>(total);
-        for (int i = 0; i < total; i++) {
-            if (buf[i] != null) {
-                items.add(buf[i]);
-            }
-        }
-
-        Collections.sort(items, sDateComparator);
-
-        int n = items.size();
-        long minTime = 0;
-        long maxTime = 0;
-        for (int i = 0; i < n; i++) {
-            long t = items.get(i).dateInMs;
-            if (t == 0) continue;
-            if (minTime == 0) {
-                minTime = maxTime = t;
-            } else {
-                minTime = Math.min(minTime, t);
-                maxTime = Math.max(maxTime, t);
-            }
-        }
-
-        setTimeRange(maxTime - minTime, n);
-
-        for (int i = 0; i < n; i++) {
-            compute(items.get(i));
-        }
-
-        compute(null);
-
-        int m = mClusters.size();
-        mNames = new String[m];
-        for (int i = 0; i < m; i++) {
-            mNames[i] = mClusters.get(i).generateCaption(mContext);
-        }
-    }
-
-    @Override
-    public int getNumberOfClusters() {
-        return mClusters.size();
-    }
-
-    @Override
-    public ArrayList<Path> getCluster(int index) {
-        ArrayList<SmallItem> items = mClusters.get(index).getItems();
-        ArrayList<Path> result = new ArrayList<Path>(items.size());
-        for (int i = 0, n = items.size(); i < n; i++) {
-            result.add(items.get(i).path);
-        }
-        return result;
-    }
-
-    @Override
-    public String getClusterName(int index) {
-        return mNames[index];
-    }
-
-    private void setTimeRange(long timeRange, int numItems) {
-        if (numItems != 0) {
-            int meanItemsPerCluster = numItems / NUM_CLUSTERS_TARGETED;
-            // Heuristic to get min and max cluster size - half and double the
-            // desired items per cluster.
-            mMinClusterSize = meanItemsPerCluster / 2;
-            mMaxClusterSize = meanItemsPerCluster * 2;
-            mClusterSplitTime = timeRange / numItems * CLUSTER_SPLIT_MULTIPLIER;
-        }
-        mClusterSplitTime = Utils.clamp(mClusterSplitTime, MIN_CLUSTER_SPLIT_TIME_IN_MS, MAX_CLUSTER_SPLIT_TIME_IN_MS);
-        mLargeClusterSplitTime = mClusterSplitTime / PARTITION_CLUSTER_SPLIT_TIME_FACTOR;
-        mMinClusterSize = Utils.clamp(mMinClusterSize, MIN_MIN_CLUSTER_SIZE, MAX_MIN_CLUSTER_SIZE);
-        mMaxClusterSize = Utils.clamp(mMaxClusterSize, MIN_MAX_CLUSTER_SIZE, MAX_MAX_CLUSTER_SIZE);
-    }
-
-    private void compute(SmallItem currentItem) {
-        if (currentItem != null) {
-            int numClusters = mClusters.size();
-            int numCurrClusterItems = mCurrCluster.size();
-            boolean geographicallySeparateItem = false;
-            boolean itemAddedToCurrentCluster = false;
-
-            // Determine if this item should go in the current cluster or be the
-            // start of a new cluster.
-            if (numCurrClusterItems == 0) {
-                mCurrCluster.addItem(currentItem);
-            } else {
-                SmallItem prevItem = mCurrCluster.getLastItem();
-                if (isGeographicallySeparated(prevItem, currentItem)) {
-                    mClusters.add(mCurrCluster);
-                    geographicallySeparateItem = true;
-                } else if (numCurrClusterItems > mMaxClusterSize) {
-                    splitAndAddCurrentCluster();
-                } else if (timeDistance(prevItem, currentItem) < mClusterSplitTime) {
-                    mCurrCluster.addItem(currentItem);
-                    itemAddedToCurrentCluster = true;
-                } else if (numClusters > 0 && numCurrClusterItems < mMinClusterSize
-                        && !mCurrCluster.mGeographicallySeparatedFromPrevCluster) {
-                    mergeAndAddCurrentCluster();
-                } else {
-                    mClusters.add(mCurrCluster);
-                }
-
-                // Creating a new cluster and adding the current item to it.
-                if (!itemAddedToCurrentCluster) {
-                    mCurrCluster = new Cluster();
-                    if (geographicallySeparateItem) {
-                        mCurrCluster.mGeographicallySeparatedFromPrevCluster = true;
-                    }
-                    mCurrCluster.addItem(currentItem);
-                }
-            }
-        } else {
-            if (mCurrCluster.size() > 0) {
-                int numClusters = mClusters.size();
-                int numCurrClusterItems = mCurrCluster.size();
-
-                // The last cluster may potentially be too big or too small.
-                if (numCurrClusterItems > mMaxClusterSize) {
-                    splitAndAddCurrentCluster();
-                } else if (numClusters > 0 && numCurrClusterItems < mMinClusterSize
-                        && !mCurrCluster.mGeographicallySeparatedFromPrevCluster) {
-                    mergeAndAddCurrentCluster();
-                } else {
-                    mClusters.add(mCurrCluster);
-                }
-                mCurrCluster = new Cluster();
-            }
-        }
-    }
-
-    private void splitAndAddCurrentCluster() {
-        ArrayList<SmallItem> currClusterItems = mCurrCluster.getItems();
-        int numCurrClusterItems = mCurrCluster.size();
-        int secondPartitionStartIndex = getPartitionIndexForCurrentCluster();
-        if (secondPartitionStartIndex != -1) {
-            Cluster partitionedCluster = new Cluster();
-            for (int j = 0; j < secondPartitionStartIndex; j++) {
-                partitionedCluster.addItem(currClusterItems.get(j));
-            }
-            mClusters.add(partitionedCluster);
-            partitionedCluster = new Cluster();
-            for (int j = secondPartitionStartIndex; j < numCurrClusterItems; j++) {
-                partitionedCluster.addItem(currClusterItems.get(j));
-            }
-            mClusters.add(partitionedCluster);
-        } else {
-            mClusters.add(mCurrCluster);
-        }
-    }
-
-    private int getPartitionIndexForCurrentCluster() {
-        int partitionIndex = -1;
-        float largestChange = MIN_PARTITION_CHANGE_FACTOR;
-        ArrayList<SmallItem> currClusterItems = mCurrCluster.getItems();
-        int numCurrClusterItems = mCurrCluster.size();
-        int minClusterSize = mMinClusterSize;
-
-        // Could be slightly more efficient here but this code seems cleaner.
-        if (numCurrClusterItems > minClusterSize + 1) {
-            for (int i = minClusterSize; i < numCurrClusterItems - minClusterSize; i++) {
-                SmallItem prevItem = currClusterItems.get(i - 1);
-                SmallItem currItem = currClusterItems.get(i);
-                SmallItem nextItem = currClusterItems.get(i + 1);
-
-                long timeNext = nextItem.dateInMs;
-                long timeCurr = currItem.dateInMs;
-                long timePrev = prevItem.dateInMs;
-
-                if (timeNext == 0 || timeCurr == 0 || timePrev == 0) continue;
-
-                long diff1 = Math.abs(timeNext - timeCurr);
-                long diff2 = Math.abs(timeCurr - timePrev);
-
-                float change = Math.max(diff1 / (diff2 + 0.01f), diff2 / (diff1 + 0.01f));
-                if (change > largestChange) {
-                    if (timeDistance(currItem, prevItem) > mLargeClusterSplitTime) {
-                        partitionIndex = i;
-                        largestChange = change;
-                    } else if (timeDistance(nextItem, currItem) > mLargeClusterSplitTime) {
-                        partitionIndex = i + 1;
-                        largestChange = change;
-                    }
-                }
-            }
-        }
-        return partitionIndex;
-    }
-
-    private void mergeAndAddCurrentCluster() {
-        int numClusters = mClusters.size();
-        Cluster prevCluster = mClusters.get(numClusters - 1);
-        ArrayList<SmallItem> currClusterItems = mCurrCluster.getItems();
-        int numCurrClusterItems = mCurrCluster.size();
-        if (prevCluster.size() < mMinClusterSize) {
-            for (int i = 0; i < numCurrClusterItems; i++) {
-                prevCluster.addItem(currClusterItems.get(i));
-            }
-            mClusters.set(numClusters - 1, prevCluster);
-        } else {
-            mClusters.add(mCurrCluster);
-        }
-    }
-
-    // Returns true if a, b are sufficiently geographically separated.
-    private static boolean isGeographicallySeparated(SmallItem itemA, SmallItem itemB) {
-        if (!GalleryUtils.isValidLocation(itemA.lat, itemA.lng)
-                || !GalleryUtils.isValidLocation(itemB.lat, itemB.lng)) {
-            return false;
-        }
-
-        double distance = GalleryUtils.fastDistanceMeters(
-            Math.toRadians(itemA.lat),
-            Math.toRadians(itemA.lng),
-            Math.toRadians(itemB.lat),
-            Math.toRadians(itemB.lng));
-        return (GalleryUtils.toMile(distance) > GEOGRAPHIC_DISTANCE_CUTOFF_IN_MILES);
-    }
-
-    // Returns the time interval between the two items in milliseconds.
-    private static long timeDistance(SmallItem a, SmallItem b) {
-        return Math.abs(a.dateInMs - b.dateInMs);
-    }
-}
-
-class SmallItem {
-    Path path;
-    long dateInMs;
-    double lat, lng;
-}
-
-class Cluster {
-    @SuppressWarnings("unused")
-    private static final String TAG = "Cluster";
-    private static final String MMDDYY_FORMAT = "MMddyy";
-
-    // This is for TimeClustering only.
-    public boolean mGeographicallySeparatedFromPrevCluster = false;
-
-    private ArrayList<SmallItem> mItems = new ArrayList<SmallItem>();
-
-    public Cluster() {
-    }
-
-    public void addItem(SmallItem item) {
-        mItems.add(item);
-    }
-
-    public int size() {
-        return mItems.size();
-    }
-
-    public SmallItem getLastItem() {
-        int n = mItems.size();
-        return (n == 0) ? null : mItems.get(n - 1);
-    }
-
-    public ArrayList<SmallItem> getItems() {
-        return mItems;
-    }
-
-    public String generateCaption(Context context) {
-        int n = mItems.size();
-        long minTimestamp = 0;
-        long maxTimestamp = 0;
-
-        for (int i = 0; i < n; i++) {
-            long t = mItems.get(i).dateInMs;
-            if (t == 0) continue;
-            if (minTimestamp == 0) {
-                minTimestamp = maxTimestamp = t;
-            } else {
-                minTimestamp = Math.min(minTimestamp, t);
-                maxTimestamp = Math.max(maxTimestamp, t);
-            }
-        }
-        if (minTimestamp == 0) return "";
-
-        String caption;
-        String minDay = DateFormat.format(MMDDYY_FORMAT, minTimestamp)
-                .toString();
-        String maxDay = DateFormat.format(MMDDYY_FORMAT, maxTimestamp)
-                .toString();
-
-        if (minDay.substring(4).equals(maxDay.substring(4))) {
-            // The items are from the same year - show at least as
-            // much granularity as abbrev_all allows.
-            caption = DateUtils.formatDateRange(context, minTimestamp,
-                    maxTimestamp, DateUtils.FORMAT_ABBREV_ALL);
-
-            // Get a more granular date range string if the min and
-            // max timestamp are on the same day and from the
-            // current year.
-            if (minDay.equals(maxDay)) {
-                int flags = DateUtils.FORMAT_ABBREV_MONTH | DateUtils.FORMAT_SHOW_DATE;
-                // Contains the year only if the date does not
-                // correspond to the current year.
-                String dateRangeWithOptionalYear = DateUtils.formatDateTime(
-                        context, minTimestamp, flags);
-                String dateRangeWithYear = DateUtils.formatDateTime(
-                        context, minTimestamp, flags | DateUtils.FORMAT_SHOW_YEAR);
-                if (!dateRangeWithOptionalYear.equals(dateRangeWithYear)) {
-                    // This means both dates are from the same year
-                    // - show the time.
-                    // Not enough room to display the time range.
-                    // Pick the mid-point.
-                    long midTimestamp = (minTimestamp + maxTimestamp) / 2;
-                    caption = DateUtils.formatDateRange(context, midTimestamp,
-                            midTimestamp, DateUtils.FORMAT_SHOW_TIME | flags);
-                }
-            }
-        } else {
-            // The items are not from the same year - only show
-            // month and year.
-            int flags = DateUtils.FORMAT_NO_MONTH_DAY
-                    | DateUtils.FORMAT_ABBREV_MONTH | DateUtils.FORMAT_SHOW_DATE;
-            caption = DateUtils.formatDateRange(context, minTimestamp,
-                    maxTimestamp, flags);
-        }
-
-        return caption;
-    }
-}
diff --git a/src/com/android/gallery3d/data/UnlockImage.java b/src/com/android/gallery3d/data/UnlockImage.java
deleted file mode 100644
index ed3b485..0000000
--- a/src/com/android/gallery3d/data/UnlockImage.java
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * 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.gallery3d.data;
-
-import com.android.gallery3d.R;
-import com.android.gallery3d.app.GalleryApp;
-
-public class UnlockImage extends ActionImage {
-    @SuppressWarnings("unused")
-    private static final String TAG = "UnlockImage";
-
-    public UnlockImage(Path path, GalleryApp application) {
-        super(path, application, R.drawable.placeholder_locked);
-    }
-
-    @Override
-    public int getSupportedOperations() {
-        return super.getSupportedOperations() | SUPPORT_UNLOCK;
-    }
-}
diff --git a/src/com/android/gallery3d/data/UriImage.java b/src/com/android/gallery3d/data/UriImage.java
deleted file mode 100644
index e8875b5..0000000
--- a/src/com/android/gallery3d/data/UriImage.java
+++ /dev/null
@@ -1,298 +0,0 @@
-/*
- * Copyright (C) 2010 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.gallery3d.data;
-
-import android.content.ContentResolver;
-import android.graphics.Bitmap;
-import android.graphics.Bitmap.Config;
-import android.graphics.BitmapFactory.Options;
-import android.graphics.BitmapRegionDecoder;
-import android.net.Uri;
-import android.os.ParcelFileDescriptor;
-
-import com.android.gallery3d.app.GalleryApp;
-import com.android.gallery3d.app.PanoramaMetadataSupport;
-import com.android.gallery3d.common.BitmapUtils;
-import com.android.gallery3d.common.Utils;
-import com.android.gallery3d.util.ThreadPool.CancelListener;
-import com.android.gallery3d.util.ThreadPool.Job;
-import com.android.gallery3d.util.ThreadPool.JobContext;
-
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-import java.io.InputStream;
-import java.net.URI;
-import java.net.URL;
-
-public class UriImage extends MediaItem {
-    private static final String TAG = "UriImage";
-
-    private static final int STATE_INIT = 0;
-    private static final int STATE_DOWNLOADING = 1;
-    private static final int STATE_DOWNLOADED = 2;
-    private static final int STATE_ERROR = -1;
-
-    private final Uri mUri;
-    private final String mContentType;
-
-    private DownloadCache.Entry mCacheEntry;
-    private ParcelFileDescriptor mFileDescriptor;
-    private int mState = STATE_INIT;
-    private int mWidth;
-    private int mHeight;
-    private int mRotation;
-    private PanoramaMetadataSupport mPanoramaMetadata = new PanoramaMetadataSupport(this);
-
-    private GalleryApp mApplication;
-
-    public UriImage(GalleryApp application, Path path, Uri uri, String contentType) {
-        super(path, nextVersionNumber());
-        mUri = uri;
-        mApplication = Utils.checkNotNull(application);
-        mContentType = contentType;
-    }
-
-    @Override
-    public Job<Bitmap> requestImage(int type) {
-        return new BitmapJob(type);
-    }
-
-    @Override
-    public Job<BitmapRegionDecoder> requestLargeImage() {
-        return new RegionDecoderJob();
-    }
-
-    private void openFileOrDownloadTempFile(JobContext jc) {
-        int state = openOrDownloadInner(jc);
-        synchronized (this) {
-            mState = state;
-            if (mState != STATE_DOWNLOADED) {
-                if (mFileDescriptor != null) {
-                    Utils.closeSilently(mFileDescriptor);
-                    mFileDescriptor = null;
-                }
-            }
-            notifyAll();
-        }
-    }
-
-    private int openOrDownloadInner(JobContext jc) {
-        String scheme = mUri.getScheme();
-        if (ContentResolver.SCHEME_CONTENT.equals(scheme)
-                || ContentResolver.SCHEME_ANDROID_RESOURCE.equals(scheme)
-                || ContentResolver.SCHEME_FILE.equals(scheme)) {
-            try {
-                if (MIME_TYPE_JPEG.equalsIgnoreCase(mContentType)) {
-                    InputStream is = mApplication.getContentResolver()
-                            .openInputStream(mUri);
-                    mRotation = Exif.getOrientation(is);
-                    Utils.closeSilently(is);
-                }
-                mFileDescriptor = mApplication.getContentResolver()
-                        .openFileDescriptor(mUri, "r");
-                if (jc.isCancelled()) return STATE_INIT;
-                return STATE_DOWNLOADED;
-            } catch (FileNotFoundException e) {
-                Log.w(TAG, "fail to open: " + mUri, e);
-                return STATE_ERROR;
-            }
-        } else {
-            try {
-                URL url = new URI(mUri.toString()).toURL();
-                mCacheEntry = mApplication.getDownloadCache().download(jc, url);
-                if (jc.isCancelled()) return STATE_INIT;
-                if (mCacheEntry == null) {
-                    Log.w(TAG, "download failed " + url);
-                    return STATE_ERROR;
-                }
-                if (MIME_TYPE_JPEG.equalsIgnoreCase(mContentType)) {
-                    InputStream is = new FileInputStream(mCacheEntry.cacheFile);
-                    mRotation = Exif.getOrientation(is);
-                    Utils.closeSilently(is);
-                }
-                mFileDescriptor = ParcelFileDescriptor.open(
-                        mCacheEntry.cacheFile, ParcelFileDescriptor.MODE_READ_ONLY);
-                return STATE_DOWNLOADED;
-            } catch (Throwable t) {
-                Log.w(TAG, "download error", t);
-                return STATE_ERROR;
-            }
-        }
-    }
-
-    private boolean prepareInputFile(JobContext jc) {
-        jc.setCancelListener(new CancelListener() {
-            @Override
-            public void onCancel() {
-                synchronized (this) {
-                    notifyAll();
-                }
-            }
-        });
-
-        while (true) {
-            synchronized (this) {
-                if (jc.isCancelled()) return false;
-                if (mState == STATE_INIT) {
-                    mState = STATE_DOWNLOADING;
-                    // Then leave the synchronized block and continue.
-                } else if (mState == STATE_ERROR) {
-                    return false;
-                } else if (mState == STATE_DOWNLOADED) {
-                    return true;
-                } else /* if (mState == STATE_DOWNLOADING) */ {
-                    try {
-                        wait();
-                    } catch (InterruptedException ex) {
-                        // ignored.
-                    }
-                    continue;
-                }
-            }
-            // This is only reached for STATE_INIT->STATE_DOWNLOADING
-            openFileOrDownloadTempFile(jc);
-        }
-    }
-
-    private class RegionDecoderJob implements Job<BitmapRegionDecoder> {
-        @Override
-        public BitmapRegionDecoder run(JobContext jc) {
-            if (!prepareInputFile(jc)) return null;
-            BitmapRegionDecoder decoder = DecodeUtils.createBitmapRegionDecoder(
-                    jc, mFileDescriptor.getFileDescriptor(), false);
-            mWidth = decoder.getWidth();
-            mHeight = decoder.getHeight();
-            return decoder;
-        }
-    }
-
-    private class BitmapJob implements Job<Bitmap> {
-        private int mType;
-
-        protected BitmapJob(int type) {
-            mType = type;
-        }
-
-        @Override
-        public Bitmap run(JobContext jc) {
-            if (!prepareInputFile(jc)) return null;
-            int targetSize = MediaItem.getTargetSize(mType);
-            Options options = new Options();
-            options.inPreferredConfig = Config.ARGB_8888;
-            Bitmap bitmap = DecodeUtils.decodeThumbnail(jc,
-                    mFileDescriptor.getFileDescriptor(), options, targetSize, mType);
-
-            if (jc.isCancelled() || bitmap == null) {
-                return null;
-            }
-
-            if (mType == MediaItem.TYPE_MICROTHUMBNAIL) {
-                bitmap = BitmapUtils.resizeAndCropCenter(bitmap, targetSize, true);
-            } else {
-                bitmap = BitmapUtils.resizeDownBySideLength(bitmap, targetSize, true);
-            }
-            return bitmap;
-        }
-    }
-
-    @Override
-    public int getSupportedOperations() {
-        int supported = SUPPORT_EDIT | SUPPORT_SETAS;
-        if (isSharable()) supported |= SUPPORT_SHARE;
-        if (BitmapUtils.isSupportedByRegionDecoder(mContentType)) {
-            supported |= SUPPORT_FULL_IMAGE;
-        }
-        return supported;
-    }
-
-    @Override
-    public void getPanoramaSupport(PanoramaSupportCallback callback) {
-        mPanoramaMetadata.getPanoramaSupport(mApplication, callback);
-    }
-
-    @Override
-    public void clearCachedPanoramaSupport() {
-        mPanoramaMetadata.clearCachedValues();
-    }
-
-    private boolean isSharable() {
-        // We cannot grant read permission to the receiver since we put
-        // the data URI in EXTRA_STREAM instead of the data part of an intent
-        // And there are issues in MediaUploader and Bluetooth file sender to
-        // share a general image data. So, we only share for local file.
-        return ContentResolver.SCHEME_FILE.equals(mUri.getScheme());
-    }
-
-    @Override
-    public int getMediaType() {
-        return MEDIA_TYPE_IMAGE;
-    }
-
-    @Override
-    public Uri getContentUri() {
-        return mUri;
-    }
-
-    @Override
-    public MediaDetails getDetails() {
-        MediaDetails details = super.getDetails();
-        if (mWidth != 0 && mHeight != 0) {
-            details.addDetail(MediaDetails.INDEX_WIDTH, mWidth);
-            details.addDetail(MediaDetails.INDEX_HEIGHT, mHeight);
-        }
-        if (mContentType != null) {
-            details.addDetail(MediaDetails.INDEX_MIMETYPE, mContentType);
-        }
-        if (ContentResolver.SCHEME_FILE.equals(mUri.getScheme())) {
-            String filePath = mUri.getPath();
-            details.addDetail(MediaDetails.INDEX_PATH, filePath);
-            MediaDetails.extractExifInfo(details, filePath);
-        }
-        return details;
-    }
-
-    @Override
-    public String getMimeType() {
-        return mContentType;
-    }
-
-    @Override
-    protected void finalize() throws Throwable {
-        try {
-            if (mFileDescriptor != null) {
-                Utils.closeSilently(mFileDescriptor);
-            }
-        } finally {
-            super.finalize();
-        }
-    }
-
-    @Override
-    public int getWidth() {
-        return 0;
-    }
-
-    @Override
-    public int getHeight() {
-        return 0;
-    }
-
-    @Override
-    public int getRotation() {
-        return mRotation;
-    }
-}
diff --git a/src/com/android/gallery3d/data/UriSource.java b/src/com/android/gallery3d/data/UriSource.java
deleted file mode 100644
index f66bacd..0000000
--- a/src/com/android/gallery3d/data/UriSource.java
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- * Copyright (C) 2010 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.gallery3d.data;
-
-import android.content.ContentResolver;
-import android.net.Uri;
-import android.webkit.MimeTypeMap;
-
-import com.android.gallery3d.app.GalleryApp;
-
-import java.io.UnsupportedEncodingException;
-import java.net.URLDecoder;
-import java.net.URLEncoder;
-
-class UriSource extends MediaSource {
-    @SuppressWarnings("unused")
-    private static final String TAG = "UriSource";
-    private static final String IMAGE_TYPE_PREFIX = "image/";
-    private static final String IMAGE_TYPE_ANY = "image/*";
-    private static final String CHARSET_UTF_8 = "utf-8";
-
-    private GalleryApp mApplication;
-
-    public UriSource(GalleryApp context) {
-        super("uri");
-        mApplication = context;
-    }
-
-    @Override
-    public MediaObject createMediaObject(Path path) {
-        String segment[] = path.split();
-        if (segment.length != 3) {
-            throw new RuntimeException("bad path: " + path);
-        }
-        try {
-            String uri = URLDecoder.decode(segment[1], CHARSET_UTF_8);
-            String type = URLDecoder.decode(segment[2], CHARSET_UTF_8);
-            return new UriImage(mApplication, path, Uri.parse(uri), type);
-        } catch (UnsupportedEncodingException e) {
-            throw new AssertionError(e);
-        }
-    }
-
-    private String getMimeType(Uri uri) {
-        if (ContentResolver.SCHEME_FILE.equals(uri.getScheme())) {
-            String extension =
-                    MimeTypeMap.getFileExtensionFromUrl(uri.toString());
-            String type = MimeTypeMap.getSingleton()
-                    .getMimeTypeFromExtension(extension.toLowerCase());
-            if (type != null) return type;
-        }
-        // Assume the type is image if the type cannot be resolved
-        // This could happen for "http" URI.
-        String type = mApplication.getContentResolver().getType(uri);
-        if (type == null) type = "image/*";
-        return type;
-    }
-
-    @Override
-    public Path findPathByUri(Uri uri, String type) {
-        String mimeType = getMimeType(uri);
-
-        // Try to find a most specific type but it has to be started with "image/"
-        if ((type == null) || (IMAGE_TYPE_ANY.equals(type)
-                && mimeType.startsWith(IMAGE_TYPE_PREFIX))) {
-            type = mimeType;
-        }
-
-        if (type.startsWith(IMAGE_TYPE_PREFIX)) {
-            try {
-                return Path.fromString("/uri/"
-                        + URLEncoder.encode(uri.toString(), CHARSET_UTF_8)
-                        + "/" +URLEncoder.encode(type, CHARSET_UTF_8));
-            } catch (UnsupportedEncodingException e) {
-                throw new AssertionError(e);
-            }
-        }
-        // We have no clues that it is an image
-        return null;
-    }
-}
diff --git a/src/com/android/gallery3d/filtershow/CenteredLinearLayout.java b/src/com/android/gallery3d/filtershow/CenteredLinearLayout.java
deleted file mode 100644
index bc9342d..0000000
--- a/src/com/android/gallery3d/filtershow/CenteredLinearLayout.java
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * 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.gallery3d.filtershow;
-
-import android.content.Context;
-import android.content.res.Resources;
-import android.content.res.TypedArray;
-import android.util.AttributeSet;
-import android.util.TypedValue;
-import android.widget.LinearLayout;
-
-import com.android.gallery3d.R;
-
-public class CenteredLinearLayout extends LinearLayout {
-    private final int mMaxWidth;
-
-    public CenteredLinearLayout(Context context, AttributeSet attrs) {
-        super(context, attrs);
-        TypedArray a = getContext().obtainStyledAttributes(attrs, R.styleable.CenteredLinearLayout);
-        mMaxWidth = a.getDimensionPixelSize(R.styleable.CenteredLinearLayout_max_width, 0);
-    }
-
-    @Override
-    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
-        int parentWidth = MeasureSpec.getSize(widthMeasureSpec);
-        int parentHeight = MeasureSpec.getSize(heightMeasureSpec);
-        Resources r = getContext().getResources();
-        float value = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, parentWidth,
-                r.getDisplayMetrics());
-        if (mMaxWidth > 0 && parentWidth > mMaxWidth) {
-            int measureMode = MeasureSpec.getMode(widthMeasureSpec);
-            widthMeasureSpec = MeasureSpec.makeMeasureSpec(mMaxWidth, measureMode);
-        }
-        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
-    }
-
-}
diff --git a/src/com/android/gallery3d/filtershow/EditorPlaceHolder.java b/src/com/android/gallery3d/filtershow/EditorPlaceHolder.java
deleted file mode 100644
index 95abce1..0000000
--- a/src/com/android/gallery3d/filtershow/EditorPlaceHolder.java
+++ /dev/null
@@ -1,82 +0,0 @@
-package com.android.gallery3d.filtershow;
-
-import android.view.View;
-import android.view.ViewParent;
-import android.widget.FrameLayout;
-
-import com.android.gallery3d.filtershow.cache.ImageLoader;
-import com.android.gallery3d.filtershow.editors.Editor;
-import com.android.gallery3d.filtershow.imageshow.ImageShow;
-
-import java.util.HashMap;
-import java.util.Vector;
-
-public class EditorPlaceHolder {
-    private static final String LOGTAG = "EditorPlaceHolder";
-
-    private FilterShowActivity mActivity = null;
-    private FrameLayout mContainer = null;
-    private HashMap<Integer, Editor> mEditors = new HashMap<Integer, Editor>();
-    private Vector<ImageShow> mOldViews = new Vector<ImageShow>();
-
-    public EditorPlaceHolder(FilterShowActivity activity) {
-        mActivity = activity;
-    }
-
-    public void setContainer(FrameLayout container) {
-        mContainer = container;
-    }
-
-    public void addEditor(Editor c) {
-        mEditors.put(c.getID(), c);
-    }
-
-    public boolean contains(int type) {
-        if (mEditors.get(type) != null) {
-            return true;
-        }
-        return false;
-    }
-
-    public Editor showEditor(int type) {
-        Editor editor = mEditors.get(type);
-        if (editor == null) {
-            return null;
-        }
-
-        editor.createEditor(mActivity, mContainer);
-        editor.getImageShow().bindAsImageLoadListener();
-        mContainer.setVisibility(View.VISIBLE);
-        mContainer.removeAllViews();
-        View eview = editor.getTopLevelView();
-        ViewParent parent = eview.getParent();
-
-        if (parent != null && parent instanceof FrameLayout) {
-            ((FrameLayout) parent).removeAllViews();
-        }
-
-        mContainer.addView(eview);
-        hideOldViews();
-        editor.setVisibility(View.VISIBLE);
-        return editor;
-    }
-
-    public void setOldViews(Vector<ImageShow> views) {
-        mOldViews = views;
-    }
-
-    public void hide() {
-        mContainer.setVisibility(View.GONE);
-    }
-
-    public void hideOldViews() {
-        for (View view : mOldViews) {
-            view.setVisibility(View.GONE);
-        }
-    }
-
-    public Editor getEditor(int editorId) {
-        return mEditors.get(editorId);
-    }
-
-}
diff --git a/src/com/android/gallery3d/filtershow/FilterShowActivity.java b/src/com/android/gallery3d/filtershow/FilterShowActivity.java
deleted file mode 100644
index 4700fcc..0000000
--- a/src/com/android/gallery3d/filtershow/FilterShowActivity.java
+++ /dev/null
@@ -1,1121 +0,0 @@
-/*
- * 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.gallery3d.filtershow;
-
-import android.app.ActionBar;
-import android.app.AlertDialog;
-import android.app.ProgressDialog;
-import android.content.ComponentName;
-import android.content.ContentValues;
-import android.content.Context;
-import android.content.DialogInterface;
-import android.content.Intent;
-import android.content.ServiceConnection;
-import android.content.pm.ActivityInfo;
-import android.content.res.Configuration;
-import android.content.res.Resources;
-import android.graphics.Bitmap;
-import android.graphics.Rect;
-import android.graphics.drawable.Drawable;
-import android.net.Uri;
-import android.os.AsyncTask;
-import android.os.Bundle;
-import android.os.Handler;
-import android.os.IBinder;
-import android.support.v4.app.DialogFragment;
-import android.support.v4.app.Fragment;
-import android.support.v4.app.FragmentActivity;
-import android.support.v4.app.FragmentTransaction;
-import android.util.DisplayMetrics;
-import android.util.Log;
-import android.util.TypedValue;
-import android.view.Menu;
-import android.view.MenuItem;
-import android.view.View;
-import android.view.View.OnClickListener;
-import android.view.ViewPropertyAnimator;
-import android.view.WindowManager;
-import android.widget.AdapterView;
-import android.widget.AdapterView.OnItemClickListener;
-import android.widget.FrameLayout;
-import android.widget.ShareActionProvider;
-import android.widget.ShareActionProvider.OnShareTargetSelectedListener;
-import android.widget.Toast;
-
-import com.android.gallery3d.R;
-import com.android.gallery3d.app.PhotoPage;
-import com.android.gallery3d.data.LocalAlbum;
-import com.android.gallery3d.filtershow.cache.ImageLoader;
-import com.android.gallery3d.filtershow.category.Action;
-import com.android.gallery3d.filtershow.category.CategoryAdapter;
-import com.android.gallery3d.filtershow.category.MainPanel;
-import com.android.gallery3d.filtershow.data.UserPresetsManager;
-import com.android.gallery3d.filtershow.editors.BasicEditor;
-import com.android.gallery3d.filtershow.editors.Editor;
-import com.android.gallery3d.filtershow.editors.EditorChanSat;
-import com.android.gallery3d.filtershow.editors.EditorCrop;
-import com.android.gallery3d.filtershow.editors.EditorDraw;
-import com.android.gallery3d.filtershow.editors.EditorGrad;
-import com.android.gallery3d.filtershow.editors.EditorManager;
-import com.android.gallery3d.filtershow.editors.EditorMirror;
-import com.android.gallery3d.filtershow.editors.EditorPanel;
-import com.android.gallery3d.filtershow.editors.EditorRedEye;
-import com.android.gallery3d.filtershow.editors.EditorRotate;
-import com.android.gallery3d.filtershow.editors.EditorStraighten;
-import com.android.gallery3d.filtershow.editors.EditorTinyPlanet;
-import com.android.gallery3d.filtershow.editors.ImageOnlyEditor;
-import com.android.gallery3d.filtershow.filters.FilterRepresentation;
-import com.android.gallery3d.filtershow.filters.FilterUserPresetRepresentation;
-import com.android.gallery3d.filtershow.filters.FiltersManager;
-import com.android.gallery3d.filtershow.filters.ImageFilter;
-import com.android.gallery3d.filtershow.history.HistoryItem;
-import com.android.gallery3d.filtershow.history.HistoryManager;
-import com.android.gallery3d.filtershow.imageshow.ImageShow;
-import com.android.gallery3d.filtershow.imageshow.MasterImage;
-import com.android.gallery3d.filtershow.imageshow.Spline;
-import com.android.gallery3d.filtershow.pipeline.CachingPipeline;
-import com.android.gallery3d.filtershow.pipeline.ImagePreset;
-import com.android.gallery3d.filtershow.pipeline.ProcessingService;
-import com.android.gallery3d.filtershow.presets.PresetManagementDialog;
-import com.android.gallery3d.filtershow.presets.UserPresetsAdapter;
-import com.android.gallery3d.filtershow.provider.SharedImageProvider;
-import com.android.gallery3d.filtershow.state.StateAdapter;
-import com.android.gallery3d.filtershow.tools.SaveImage;
-import com.android.gallery3d.filtershow.tools.XmpPresets;
-import com.android.gallery3d.filtershow.tools.XmpPresets.XMresults;
-import com.android.gallery3d.filtershow.ui.ExportDialog;
-import com.android.gallery3d.filtershow.ui.FramedTextButton;
-import com.android.gallery3d.util.GalleryUtils;
-import com.android.gallery3d.util.UsageStatistics;
-import com.android.photos.data.GalleryBitmapPool;
-
-import java.io.File;
-import java.lang.ref.WeakReference;
-import java.util.ArrayList;
-import java.util.Vector;
-
-public class FilterShowActivity extends FragmentActivity implements OnItemClickListener,
-        OnShareTargetSelectedListener {
-
-    private String mAction = "";
-    MasterImage mMasterImage = null;
-
-    private static final long LIMIT_SUPPORTS_HIGHRES = 134217728; // 128Mb
-
-    public static final String TINY_PLANET_ACTION = "com.android.camera.action.TINY_PLANET";
-    public static final String LAUNCH_FULLSCREEN = "launch-fullscreen";
-    private ImageShow mImageShow = null;
-
-    private View mSaveButton = null;
-
-    private EditorPlaceHolder mEditorPlaceHolder = new EditorPlaceHolder(this);
-
-    private static final int SELECT_PICTURE = 1;
-    private static final String LOGTAG = "FilterShowActivity";
-
-    private boolean mShowingTinyPlanet = false;
-    private boolean mShowingImageStatePanel = false;
-
-    private final Vector<ImageShow> mImageViews = new Vector<ImageShow>();
-
-    private ShareActionProvider mShareActionProvider;
-    private File mSharedOutputFile = null;
-
-    private boolean mSharingImage = false;
-
-    private WeakReference<ProgressDialog> mSavingProgressDialog;
-
-    private LoadBitmapTask mLoadBitmapTask;
-
-    private Uri mOriginalImageUri = null;
-    private ImagePreset mOriginalPreset = null;
-
-    private Uri mSelectedImageUri = null;
-
-    private UserPresetsManager mUserPresetsManager = null;
-    private UserPresetsAdapter mUserPresetsAdapter = null;
-    private CategoryAdapter mCategoryLooksAdapter = null;
-    private CategoryAdapter mCategoryBordersAdapter = null;
-    private CategoryAdapter mCategoryGeometryAdapter = null;
-    private CategoryAdapter mCategoryFiltersAdapter = null;
-    private int mCurrentPanel = MainPanel.LOOKS;
-
-    private ProcessingService mBoundService;
-    private boolean mIsBound = false;
-
-    public ProcessingService getProcessingService() {
-        return mBoundService;
-    }
-
-    public boolean isSimpleEditAction() {
-        return !PhotoPage.ACTION_NEXTGEN_EDIT.equalsIgnoreCase(mAction);
-    }
-
-    private ServiceConnection mConnection = new ServiceConnection() {
-        public void onServiceConnected(ComponentName className, IBinder service) {
-            /*
-             * This is called when the connection with the service has been
-             * established, giving us the service object we can use to
-             * interact with the service.  Because we have bound to a explicit
-             * service that we know is running in our own process, we can
-             * cast its IBinder to a concrete class and directly access it.
-             */
-            mBoundService = ((ProcessingService.LocalBinder)service).getService();
-            mBoundService.setFiltershowActivity(FilterShowActivity.this);
-            mBoundService.onStart();
-        }
-
-        public void onServiceDisconnected(ComponentName className) {
-            /*
-             * This is called when the connection with the service has been
-             * unexpectedly disconnected -- that is, its process crashed.
-             * Because it is running in our same process, we should never
-             * see this happen.
-             */
-            mBoundService = null;
-        }
-    };
-
-    void doBindService() {
-        /*
-         * Establish a connection with the service.  We use an explicit
-         * class name because we want a specific service implementation that
-         * we know will be running in our own process (and thus won't be
-         * supporting component replacement by other applications).
-         */
-        bindService(new Intent(FilterShowActivity.this, ProcessingService.class),
-                mConnection, Context.BIND_AUTO_CREATE);
-        mIsBound = true;
-    }
-
-    void doUnbindService() {
-        if (mIsBound) {
-            // Detach our existing connection.
-            unbindService(mConnection);
-            mIsBound = false;
-        }
-    }
-
-    private void setupPipeline() {
-        doBindService();
-        ImageFilter.setActivityForMemoryToasts(this);
-        mUserPresetsManager = new UserPresetsManager(this);
-        mUserPresetsAdapter = new UserPresetsAdapter(this);
-        mCategoryLooksAdapter = new CategoryAdapter(this);
-    }
-
-    public void updateUIAfterServiceStarted() {
-        fillCategories();
-        loadMainPanel();
-        setDefaultPreset();
-        extractXMPData();
-        processIntent();
-    }
-
-    @Override
-    public void onCreate(Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-
-        boolean onlyUsePortrait = getResources().getBoolean(R.bool.only_use_portrait);
-        if (onlyUsePortrait) {
-            setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
-        }
-        MasterImage.setMaster(mMasterImage);
-
-        clearGalleryBitmapPool();
-        setupPipeline();
-
-        setupMasterImage();
-        setDefaultValues();
-        fillEditors();
-
-        loadXML();
-        UsageStatistics.onContentViewChanged(UsageStatistics.COMPONENT_EDITOR, "Main");
-        UsageStatistics.onEvent(UsageStatistics.COMPONENT_EDITOR,
-                UsageStatistics.CATEGORY_LIFECYCLE, UsageStatistics.LIFECYCLE_START);
-    }
-
-    public boolean isShowingImageStatePanel() {
-        return mShowingImageStatePanel;
-    }
-
-    public void loadMainPanel() {
-        if (findViewById(R.id.main_panel_container) == null) {
-            return;
-        }
-        MainPanel panel = new MainPanel();
-        FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
-        transaction.replace(R.id.main_panel_container, panel, MainPanel.FRAGMENT_TAG);
-        transaction.commit();
-    }
-
-    public void loadEditorPanel(FilterRepresentation representation,
-                                final Editor currentEditor) {
-        if (representation.getEditorId() == ImageOnlyEditor.ID) {
-            currentEditor.reflectCurrentFilter();
-            return;
-        }
-        final int currentId = currentEditor.getID();
-        Runnable showEditor = new Runnable() {
-            @Override
-            public void run() {
-                EditorPanel panel = new EditorPanel();
-                panel.setEditor(currentId);
-                FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
-                transaction.remove(getSupportFragmentManager().findFragmentByTag(MainPanel.FRAGMENT_TAG));
-                transaction.replace(R.id.main_panel_container, panel, MainPanel.FRAGMENT_TAG);
-                transaction.commit();
-            }
-        };
-        Fragment main = getSupportFragmentManager().findFragmentByTag(MainPanel.FRAGMENT_TAG);
-        boolean doAnimation = false;
-        if (mShowingImageStatePanel
-                && getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) {
-            doAnimation = true;
-        }
-        if (doAnimation && main != null && main instanceof MainPanel) {
-            MainPanel mainPanel = (MainPanel) main;
-            View container = mainPanel.getView().findViewById(R.id.category_panel_container);
-            View bottom = mainPanel.getView().findViewById(R.id.bottom_panel);
-            int panelHeight = container.getHeight() + bottom.getHeight();
-            ViewPropertyAnimator anim = mainPanel.getView().animate();
-            anim.translationY(panelHeight).start();
-            final Handler handler = new Handler();
-            handler.postDelayed(showEditor, anim.getDuration());
-        } else {
-            showEditor.run();
-        }
-    }
-
-    private void loadXML() {
-        setContentView(R.layout.filtershow_activity);
-
-        ActionBar actionBar = getActionBar();
-        actionBar.setDisplayOptions(ActionBar.DISPLAY_SHOW_CUSTOM);
-        actionBar.setCustomView(R.layout.filtershow_actionbar);
-
-        mSaveButton = actionBar.getCustomView();
-        mSaveButton.setOnClickListener(new OnClickListener() {
-            @Override
-            public void onClick(View view) {
-                saveImage();
-            }
-        });
-
-        mImageShow = (ImageShow) findViewById(R.id.imageShow);
-        mImageViews.add(mImageShow);
-
-        setupEditors();
-
-        mEditorPlaceHolder.hide();
-        mImageShow.bindAsImageLoadListener();
-
-        setupStatePanel();
-    }
-
-    public void fillCategories() {
-        fillLooks();
-        loadUserPresets();
-        fillBorders();
-        fillTools();
-        fillEffects();
-    }
-
-    public void setupStatePanel() {
-        MasterImage.getImage().setHistoryManager(mMasterImage.getHistory());
-    }
-
-    private void fillEffects() {
-        FiltersManager filtersManager = FiltersManager.getManager();
-        ArrayList<FilterRepresentation> filtersRepresentations = filtersManager.getEffects();
-        mCategoryFiltersAdapter = new CategoryAdapter(this);
-        for (FilterRepresentation representation : filtersRepresentations) {
-            if (representation.getTextId() != 0) {
-                representation.setName(getString(representation.getTextId()));
-            }
-            mCategoryFiltersAdapter.add(new Action(this, representation));
-        }
-    }
-
-    private void fillTools() {
-        FiltersManager filtersManager = FiltersManager.getManager();
-        ArrayList<FilterRepresentation> filtersRepresentations = filtersManager.getTools();
-        mCategoryGeometryAdapter = new CategoryAdapter(this);
-        for (FilterRepresentation representation : filtersRepresentations) {
-            mCategoryGeometryAdapter.add(new Action(this, representation));
-        }
-    }
-
-    private void processIntent() {
-        Intent intent = getIntent();
-        if (intent.getBooleanExtra(LAUNCH_FULLSCREEN, false)) {
-            getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
-        }
-
-        mAction = intent.getAction();
-        mSelectedImageUri = intent.getData();
-        Uri loadUri = mSelectedImageUri;
-        if (mOriginalImageUri != null) {
-            loadUri = mOriginalImageUri;
-        }
-        if (loadUri != null) {
-            startLoadBitmap(loadUri);
-        } else {
-            pickImage();
-        }
-    }
-
-    private void setupEditors() {
-        mEditorPlaceHolder.setContainer((FrameLayout) findViewById(R.id.editorContainer));
-        EditorManager.addEditors(mEditorPlaceHolder);
-        mEditorPlaceHolder.setOldViews(mImageViews);
-    }
-
-    private void fillEditors() {
-        mEditorPlaceHolder.addEditor(new EditorChanSat());
-        mEditorPlaceHolder.addEditor(new EditorGrad());
-        mEditorPlaceHolder.addEditor(new EditorDraw());
-        mEditorPlaceHolder.addEditor(new BasicEditor());
-        mEditorPlaceHolder.addEditor(new ImageOnlyEditor());
-        mEditorPlaceHolder.addEditor(new EditorTinyPlanet());
-        mEditorPlaceHolder.addEditor(new EditorRedEye());
-        mEditorPlaceHolder.addEditor(new EditorCrop());
-        mEditorPlaceHolder.addEditor(new EditorMirror());
-        mEditorPlaceHolder.addEditor(new EditorRotate());
-        mEditorPlaceHolder.addEditor(new EditorStraighten());
-    }
-
-    private void setDefaultValues() {
-        Resources res = getResources();
-
-        // TODO: get those values from XML.
-        FramedTextButton.setTextSize((int) getPixelsFromDip(14));
-        FramedTextButton.setTrianglePadding((int) getPixelsFromDip(4));
-        FramedTextButton.setTriangleSize((int) getPixelsFromDip(10));
-
-        Drawable curveHandle = res.getDrawable(R.drawable.camera_crop);
-        int curveHandleSize = (int) res.getDimension(R.dimen.crop_indicator_size);
-        Spline.setCurveHandle(curveHandle, curveHandleSize);
-        Spline.setCurveWidth((int) getPixelsFromDip(3));
-    }
-
-    private void startLoadBitmap(Uri uri) {
-        final View loading = findViewById(R.id.loading);
-        final View imageShow = findViewById(R.id.imageShow);
-        imageShow.setVisibility(View.INVISIBLE);
-        loading.setVisibility(View.VISIBLE);
-        mShowingTinyPlanet = false;
-        mLoadBitmapTask = new LoadBitmapTask();
-        mLoadBitmapTask.execute(uri);
-    }
-
-    private void fillBorders() {
-        FiltersManager filtersManager = FiltersManager.getManager();
-        ArrayList<FilterRepresentation> borders = filtersManager.getBorders();
-
-        for (int i = 0; i < borders.size(); i++) {
-            FilterRepresentation filter = borders.get(i);
-            filter.setName(getString(R.string.borders));
-            if (i == 0) {
-                filter.setName(getString(R.string.none));
-            }
-        }
-
-        mCategoryBordersAdapter = new CategoryAdapter(this);
-        for (FilterRepresentation representation : borders) {
-            if (representation.getTextId() != 0) {
-                representation.setName(getString(representation.getTextId()));
-            }
-            mCategoryBordersAdapter.add(new Action(this, representation, Action.FULL_VIEW));
-        }
-    }
-
-    public UserPresetsAdapter getUserPresetsAdapter() {
-        return mUserPresetsAdapter;
-    }
-
-    public CategoryAdapter getCategoryLooksAdapter() {
-        return mCategoryLooksAdapter;
-    }
-
-    public CategoryAdapter getCategoryBordersAdapter() {
-        return mCategoryBordersAdapter;
-    }
-
-    public CategoryAdapter getCategoryGeometryAdapter() {
-        return mCategoryGeometryAdapter;
-    }
-
-    public CategoryAdapter getCategoryFiltersAdapter() {
-        return mCategoryFiltersAdapter;
-    }
-
-    public void removeFilterRepresentation(FilterRepresentation filterRepresentation) {
-        if (filterRepresentation == null) {
-            return;
-        }
-        ImagePreset oldPreset = MasterImage.getImage().getPreset();
-        ImagePreset copy = new ImagePreset(oldPreset);
-        copy.removeFilter(filterRepresentation);
-        MasterImage.getImage().setPreset(copy, copy.getLastRepresentation(), true);
-        if (MasterImage.getImage().getCurrentFilterRepresentation() == filterRepresentation) {
-            FilterRepresentation lastRepresentation = copy.getLastRepresentation();
-            MasterImage.getImage().setCurrentFilterRepresentation(lastRepresentation);
-        }
-    }
-
-    public void useFilterRepresentation(FilterRepresentation filterRepresentation) {
-        if (filterRepresentation == null) {
-            return;
-        }
-        if (MasterImage.getImage().getCurrentFilterRepresentation() == filterRepresentation) {
-            return;
-        }
-        ImagePreset oldPreset = MasterImage.getImage().getPreset();
-        ImagePreset copy = new ImagePreset(oldPreset);
-        FilterRepresentation representation = copy.getRepresentation(filterRepresentation);
-        if (representation == null) {
-            copy.addFilter(filterRepresentation);
-        } else if (filterRepresentation.getFilterType() == FilterRepresentation.TYPE_GEOMETRY) {
-            filterRepresentation = representation;
-        } else {
-            if (filterRepresentation.allowsSingleInstanceOnly()) {
-                // Don't just update the filter representation. Centralize the
-                // logic in the addFilter(), such that we can keep "None" as
-                // null.
-                copy.removeFilter(representation);
-                copy.addFilter(filterRepresentation);
-            }
-        }
-        MasterImage.getImage().setPreset(copy, filterRepresentation, true);
-        MasterImage.getImage().setCurrentFilterRepresentation(filterRepresentation);
-    }
-
-    public void showRepresentation(FilterRepresentation representation) {
-        if (representation == null) {
-            return;
-        }
-
-        useFilterRepresentation(representation);
-
-        // show representation
-        Editor mCurrentEditor = mEditorPlaceHolder.showEditor(representation.getEditorId());
-        loadEditorPanel(representation, mCurrentEditor);
-    }
-
-    public Editor getEditor(int editorID) {
-        return mEditorPlaceHolder.getEditor(editorID);
-    }
-
-    public void setCurrentPanel(int currentPanel) {
-        mCurrentPanel = currentPanel;
-    }
-
-    public int getCurrentPanel() {
-        return mCurrentPanel;
-    }
-
-    public void updateCategories() {
-        ImagePreset preset = mMasterImage.getPreset();
-        mCategoryLooksAdapter.reflectImagePreset(preset);
-        mCategoryBordersAdapter.reflectImagePreset(preset);
-    }
-
-    private class LoadHighresBitmapTask extends AsyncTask<Void, Void, Boolean> {
-        @Override
-        protected Boolean doInBackground(Void... params) {
-            MasterImage master = MasterImage.getImage();
-            Rect originalBounds = master.getOriginalBounds();
-            if (master.supportsHighRes()) {
-                int highresPreviewSize = master.getOriginalBitmapLarge().getWidth() * 2;
-                if (highresPreviewSize > originalBounds.width()) {
-                    highresPreviewSize = originalBounds.width();
-                }
-                Rect bounds = new Rect();
-                Bitmap originalHires = ImageLoader.loadOrientedConstrainedBitmap(master.getUri(),
-                        master.getActivity(), highresPreviewSize,
-                        master.getOrientation(), bounds);
-                master.setOriginalBounds(bounds);
-                master.setOriginalBitmapHighres(originalHires);
-                mBoundService.setOriginalBitmapHighres(originalHires);
-                master.warnListeners();
-            }
-            return true;
-        }
-
-        @Override
-        protected void onPostExecute(Boolean result) {
-            Bitmap highresBitmap = MasterImage.getImage().getOriginalBitmapHighres();
-            if (highresBitmap != null) {
-                float highResPreviewScale = (float) highresBitmap.getWidth()
-                        / (float) MasterImage.getImage().getOriginalBounds().width();
-                mBoundService.setHighresPreviewScaleFactor(highResPreviewScale);
-            }
-        }
-    }
-
-    private class LoadBitmapTask extends AsyncTask<Uri, Boolean, Boolean> {
-        int mBitmapSize;
-
-        public LoadBitmapTask() {
-            mBitmapSize = getScreenImageSize();
-        }
-
-        @Override
-        protected Boolean doInBackground(Uri... params) {
-            if (!MasterImage.getImage().loadBitmap(params[0], mBitmapSize)) {
-                return false;
-            }
-            publishProgress(ImageLoader.queryLightCycle360(MasterImage.getImage().getActivity()));
-            return true;
-        }
-
-        @Override
-        protected void onProgressUpdate(Boolean... values) {
-            super.onProgressUpdate(values);
-            if (isCancelled()) {
-                return;
-            }
-            if (values[0]) {
-                mShowingTinyPlanet = true;
-            }
-        }
-
-        @Override
-        protected void onPostExecute(Boolean result) {
-            MasterImage.setMaster(mMasterImage);
-            if (isCancelled()) {
-                return;
-            }
-
-            if (!result) {
-                cannotLoadImage();
-            }
-
-            if (null == CachingPipeline.getRenderScriptContext()){
-                Log.v(LOGTAG,"RenderScript context destroyed during load");
-                return;
-            }
-            final View loading = findViewById(R.id.loading);
-            loading.setVisibility(View.GONE);
-            final View imageShow = findViewById(R.id.imageShow);
-            imageShow.setVisibility(View.VISIBLE);
-
-            Bitmap largeBitmap = MasterImage.getImage().getOriginalBitmapLarge();
-            mBoundService.setOriginalBitmap(largeBitmap);
-
-            float previewScale = (float) largeBitmap.getWidth()
-                    / (float) MasterImage.getImage().getOriginalBounds().width();
-            mBoundService.setPreviewScaleFactor(previewScale);
-            if (!mShowingTinyPlanet) {
-                mCategoryFiltersAdapter.removeTinyPlanet();
-            }
-            mCategoryLooksAdapter.imageLoaded();
-            mCategoryBordersAdapter.imageLoaded();
-            mCategoryGeometryAdapter.imageLoaded();
-            mCategoryFiltersAdapter.imageLoaded();
-            mLoadBitmapTask = null;
-
-            if (mOriginalPreset != null) {
-                MasterImage.getImage().setLoadedPreset(mOriginalPreset);
-                MasterImage.getImage().setPreset(mOriginalPreset,
-                        mOriginalPreset.getLastRepresentation(), true);
-                mOriginalPreset = null;
-            }
-
-            if (mAction == TINY_PLANET_ACTION) {
-                showRepresentation(mCategoryFiltersAdapter.getTinyPlanet());
-            }
-            LoadHighresBitmapTask highresLoad = new LoadHighresBitmapTask();
-            highresLoad.execute();
-            super.onPostExecute(result);
-        }
-
-    }
-
-    private void clearGalleryBitmapPool() {
-        (new AsyncTask<Void, Void, Void>() {
-            @Override
-            protected Void doInBackground(Void... params) {
-                // Free memory held in Gallery's Bitmap pool.  May be O(n) for n bitmaps.
-                GalleryBitmapPool.getInstance().clear();
-                return null;
-            }
-        }).execute();
-    }
-
-    @Override
-    protected void onDestroy() {
-        if (mLoadBitmapTask != null) {
-            mLoadBitmapTask.cancel(false);
-        }
-        mUserPresetsManager.close();
-        doUnbindService();
-        super.onDestroy();
-    }
-
-    // TODO: find a more robust way of handling image size selection
-    // for high screen densities.
-    private int getScreenImageSize() {
-        DisplayMetrics outMetrics = new DisplayMetrics();
-        getWindowManager().getDefaultDisplay().getMetrics(outMetrics);
-        return (int) Math.max(outMetrics.heightPixels, outMetrics.widthPixels);
-    }
-
-    private void showSavingProgress(String albumName) {
-        ProgressDialog progress;
-        if (mSavingProgressDialog != null) {
-            progress = mSavingProgressDialog.get();
-            if (progress != null) {
-                progress.show();
-                return;
-            }
-        }
-        // TODO: Allow cancellation of the saving process
-        String progressText;
-        if (albumName == null) {
-            progressText = getString(R.string.saving_image);
-        } else {
-            progressText = getString(R.string.filtershow_saving_image, albumName);
-        }
-        progress = ProgressDialog.show(this, "", progressText, true, false);
-        mSavingProgressDialog = new WeakReference<ProgressDialog>(progress);
-    }
-
-    private void hideSavingProgress() {
-        if (mSavingProgressDialog != null) {
-            ProgressDialog progress = mSavingProgressDialog.get();
-            if (progress != null)
-                progress.dismiss();
-        }
-    }
-
-    public void completeSaveImage(Uri saveUri) {
-        if (mSharingImage && mSharedOutputFile != null) {
-            // Image saved, we unblock the content provider
-            Uri uri = Uri.withAppendedPath(SharedImageProvider.CONTENT_URI,
-                    Uri.encode(mSharedOutputFile.getAbsolutePath()));
-            ContentValues values = new ContentValues();
-            values.put(SharedImageProvider.PREPARE, false);
-            getContentResolver().insert(uri, values);
-        }
-        setResult(RESULT_OK, new Intent().setData(saveUri));
-        hideSavingProgress();
-        finish();
-    }
-
-    @Override
-    public boolean onShareTargetSelected(ShareActionProvider arg0, Intent arg1) {
-        // First, let's tell the SharedImageProvider that it will need to wait
-        // for the image
-        Uri uri = Uri.withAppendedPath(SharedImageProvider.CONTENT_URI,
-                Uri.encode(mSharedOutputFile.getAbsolutePath()));
-        ContentValues values = new ContentValues();
-        values.put(SharedImageProvider.PREPARE, true);
-        getContentResolver().insert(uri, values);
-        mSharingImage = true;
-
-        // Process and save the image in the background.
-        showSavingProgress(null);
-        mImageShow.saveImage(this, mSharedOutputFile);
-        return true;
-    }
-
-    private Intent getDefaultShareIntent() {
-        Intent intent = new Intent(Intent.ACTION_SEND);
-        intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);
-        intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
-        intent.setType(SharedImageProvider.MIME_TYPE);
-        mSharedOutputFile = SaveImage.getNewFile(this, MasterImage.getImage().getUri());
-        Uri uri = Uri.withAppendedPath(SharedImageProvider.CONTENT_URI,
-                Uri.encode(mSharedOutputFile.getAbsolutePath()));
-        intent.putExtra(Intent.EXTRA_STREAM, uri);
-        return intent;
-    }
-
-    @Override
-    public boolean onCreateOptionsMenu(Menu menu) {
-        getMenuInflater().inflate(R.menu.filtershow_activity_menu, menu);
-        MenuItem showState = menu.findItem(R.id.showImageStateButton);
-        if (mShowingImageStatePanel) {
-            showState.setTitle(R.string.hide_imagestate_panel);
-        } else {
-            showState.setTitle(R.string.show_imagestate_panel);
-        }
-        mShareActionProvider = (ShareActionProvider) menu.findItem(R.id.menu_share)
-                .getActionProvider();
-        mShareActionProvider.setShareIntent(getDefaultShareIntent());
-        mShareActionProvider.setOnShareTargetSelectedListener(this);
-
-        MenuItem undoItem = menu.findItem(R.id.undoButton);
-        MenuItem redoItem = menu.findItem(R.id.redoButton);
-        MenuItem resetItem = menu.findItem(R.id.resetHistoryButton);
-        mMasterImage.getHistory().setMenuItems(undoItem, redoItem, resetItem);
-        return true;
-    }
-
-    @Override
-    public void onPause() {
-        super.onPause();
-        if (mShareActionProvider != null) {
-            mShareActionProvider.setOnShareTargetSelectedListener(null);
-        }
-    }
-
-    @Override
-    public void onResume() {
-        super.onResume();
-        if (mShareActionProvider != null) {
-            mShareActionProvider.setOnShareTargetSelectedListener(this);
-        }
-    }
-
-    @Override
-    public boolean onOptionsItemSelected(MenuItem item) {
-        switch (item.getItemId()) {
-            case R.id.undoButton: {
-                HistoryManager adapter = mMasterImage.getHistory();
-                int position = adapter.undo();
-                mMasterImage.onHistoryItemClick(position);
-                backToMain();
-                invalidateViews();
-                UsageStatistics.onEvent(UsageStatistics.COMPONENT_EDITOR,
-                        UsageStatistics.CATEGORY_BUTTON_PRESS, "Undo");
-                return true;
-            }
-            case R.id.redoButton: {
-                HistoryManager adapter = mMasterImage.getHistory();
-                int position = adapter.redo();
-                mMasterImage.onHistoryItemClick(position);
-                invalidateViews();
-                UsageStatistics.onEvent(UsageStatistics.COMPONENT_EDITOR,
-                        UsageStatistics.CATEGORY_BUTTON_PRESS, "Redo");
-                return true;
-            }
-            case R.id.resetHistoryButton: {
-                resetHistory();
-                UsageStatistics.onEvent(UsageStatistics.COMPONENT_EDITOR,
-                        UsageStatistics.CATEGORY_BUTTON_PRESS, "ResetHistory");
-                return true;
-            }
-            case R.id.showImageStateButton: {
-                toggleImageStatePanel();
-                UsageStatistics.onEvent(UsageStatistics.COMPONENT_EDITOR,
-                        UsageStatistics.CATEGORY_BUTTON_PRESS,
-                        mShowingImageStatePanel ? "ShowPanel" : "HidePanel");
-                return true;
-            }
-            case R.id.exportFlattenButton: {
-                showExportOptionsDialog();
-                return true;
-            }
-            case android.R.id.home: {
-                saveImage();
-                return true;
-            }
-            case R.id.manageUserPresets: {
-                manageUserPresets();
-                return true;
-            }
-        }
-        return false;
-    }
-
-    private void manageUserPresets() {
-        DialogFragment dialog = new PresetManagementDialog();
-        dialog.show(getSupportFragmentManager(), "NoticeDialogFragment");
-    }
-
-    private void showExportOptionsDialog() {
-        DialogFragment dialog = new ExportDialog();
-        dialog.show(getSupportFragmentManager(), "ExportDialogFragment");
-    }
-
-    public void updateUserPresetsFromAdapter(UserPresetsAdapter adapter) {
-        ArrayList<FilterUserPresetRepresentation> representations =
-                adapter.getDeletedRepresentations();
-        for (FilterUserPresetRepresentation representation : representations) {
-            deletePreset(representation.getId());
-        }
-        ArrayList<FilterUserPresetRepresentation> changedRepresentations =
-                adapter.getChangedRepresentations();
-        for (FilterUserPresetRepresentation representation : changedRepresentations) {
-            updatePreset(representation);
-        }
-        adapter.clearDeletedRepresentations();
-        adapter.clearChangedRepresentations();
-        loadUserPresets();
-    }
-
-    public void loadUserPresets() {
-        mUserPresetsManager.load();
-    }
-
-    public void updateUserPresetsFromManager() {
-        ArrayList<FilterUserPresetRepresentation> presets = mUserPresetsManager.getRepresentations();
-        if (presets == null) {
-            return;
-        }
-        if (mCategoryLooksAdapter != null) {
-            fillLooks();
-        }
-        mUserPresetsAdapter.clear();
-        for (int i = 0; i < presets.size(); i++) {
-            FilterUserPresetRepresentation representation = presets.get(i);
-            mCategoryLooksAdapter.add(
-                    new Action(this, representation, Action.FULL_VIEW));
-            mUserPresetsAdapter.add(new Action(this, representation, Action.FULL_VIEW));
-        }
-        mCategoryLooksAdapter.notifyDataSetInvalidated();
-
-    }
-
-    public void saveCurrentImagePreset() {
-        mUserPresetsManager.save(MasterImage.getImage().getPreset());
-    }
-
-    private void deletePreset(int id) {
-        mUserPresetsManager.delete(id);
-    }
-
-    private void updatePreset(FilterUserPresetRepresentation representation) {
-        mUserPresetsManager.update(representation);
-    }
-
-    public void enableSave(boolean enable) {
-        if (mSaveButton != null) {
-            mSaveButton.setEnabled(enable);
-        }
-    }
-
-    private void fillLooks() {
-        FiltersManager filtersManager = FiltersManager.getManager();
-        ArrayList<FilterRepresentation> filtersRepresentations = filtersManager.getLooks();
-
-        mCategoryLooksAdapter.clear();
-        int verticalItemHeight = (int) getResources().getDimension(R.dimen.action_item_height);
-        mCategoryLooksAdapter.setItemHeight(verticalItemHeight);
-        for (FilterRepresentation representation : filtersRepresentations) {
-            mCategoryLooksAdapter.add(new Action(this, representation, Action.FULL_VIEW));
-        }
-    }
-
-    public void setDefaultPreset() {
-        // Default preset (original)
-        ImagePreset preset = new ImagePreset(); // empty
-        mMasterImage.setPreset(preset, preset.getLastRepresentation(), true);
-    }
-
-    // //////////////////////////////////////////////////////////////////////////////
-    // Some utility functions
-    // TODO: finish the cleanup.
-
-    public void invalidateViews() {
-        for (ImageShow views : mImageViews) {
-            views.updateImage();
-        }
-    }
-
-    public void hideImageViews() {
-        for (View view : mImageViews) {
-            view.setVisibility(View.GONE);
-        }
-        mEditorPlaceHolder.hide();
-    }
-
-    // //////////////////////////////////////////////////////////////////////////////
-    // imageState panel...
-
-    public void toggleImageStatePanel() {
-        invalidateOptionsMenu();
-        mShowingImageStatePanel = !mShowingImageStatePanel;
-        Fragment panel = getSupportFragmentManager().findFragmentByTag(MainPanel.FRAGMENT_TAG);
-        if (panel != null) {
-            if (panel instanceof EditorPanel) {
-                EditorPanel editorPanel = (EditorPanel) panel;
-                editorPanel.showImageStatePanel(mShowingImageStatePanel);
-            } else if (panel instanceof MainPanel) {
-                MainPanel mainPanel = (MainPanel) panel;
-                mainPanel.showImageStatePanel(mShowingImageStatePanel);
-            }
-        }
-    }
-
-    @Override
-    public void onConfigurationChanged(Configuration newConfig)
-    {
-        super.onConfigurationChanged(newConfig);
-        setDefaultValues();
-        loadXML();
-        fillCategories();
-        loadMainPanel();
-
-        // mLoadBitmapTask==null implies you have looked at the intent
-        if (!mShowingTinyPlanet && (mLoadBitmapTask == null)) {
-            mCategoryFiltersAdapter.removeTinyPlanet();
-        }
-        final View loading = findViewById(R.id.loading);
-        loading.setVisibility(View.GONE);
-    }
-
-    public void setupMasterImage() {
-
-        HistoryManager historyManager = new HistoryManager();
-        StateAdapter imageStateAdapter = new StateAdapter(this, 0);
-        MasterImage.reset();
-        mMasterImage = MasterImage.getImage();
-        mMasterImage.setHistoryManager(historyManager);
-        mMasterImage.setStateAdapter(imageStateAdapter);
-        mMasterImage.setActivity(this);
-
-        if (Runtime.getRuntime().maxMemory() > LIMIT_SUPPORTS_HIGHRES) {
-            mMasterImage.setSupportsHighRes(true);
-        } else {
-            mMasterImage.setSupportsHighRes(false);
-        }
-    }
-
-    void resetHistory() {
-        HistoryManager adapter = mMasterImage.getHistory();
-        adapter.reset();
-        HistoryItem historyItem = adapter.getItem(0);
-        ImagePreset original = new ImagePreset(historyItem.getImagePreset());
-        mMasterImage.setPreset(original, historyItem.getFilterRepresentation(), true);
-        invalidateViews();
-        backToMain();
-    }
-
-    public void showDefaultImageView() {
-        mEditorPlaceHolder.hide();
-        mImageShow.setVisibility(View.VISIBLE);
-        MasterImage.getImage().setCurrentFilter(null);
-        MasterImage.getImage().setCurrentFilterRepresentation(null);
-    }
-
-    public void backToMain() {
-        Fragment currentPanel = getSupportFragmentManager().findFragmentByTag(MainPanel.FRAGMENT_TAG);
-        if (currentPanel instanceof MainPanel) {
-            return;
-        }
-        loadMainPanel();
-        showDefaultImageView();
-    }
-
-    @Override
-    public void onBackPressed() {
-        Fragment currentPanel = getSupportFragmentManager().findFragmentByTag(MainPanel.FRAGMENT_TAG);
-        if (currentPanel instanceof MainPanel) {
-            if (!mImageShow.hasModifications()) {
-                done();
-            } else {
-                AlertDialog.Builder builder = new AlertDialog.Builder(this);
-                builder.setMessage(R.string.unsaved).setTitle(R.string.save_before_exit);
-                builder.setPositiveButton(R.string.save_and_exit, new DialogInterface.OnClickListener() {
-                    @Override
-                    public void onClick(DialogInterface dialog, int id) {
-                        saveImage();
-                    }
-                });
-                builder.setNegativeButton(R.string.exit, new DialogInterface.OnClickListener() {
-                    @Override
-                    public void onClick(DialogInterface dialog, int id) {
-                        done();
-                    }
-                });
-                builder.show();
-            }
-        } else {
-            backToMain();
-        }
-    }
-
-    public void cannotLoadImage() {
-        Toast.makeText(this, R.string.cannot_load_image, Toast.LENGTH_SHORT).show();
-        finish();
-    }
-
-    // //////////////////////////////////////////////////////////////////////////////
-
-    public float getPixelsFromDip(float value) {
-        Resources r = getResources();
-        return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, value,
-                r.getDisplayMetrics());
-    }
-
-    @Override
-    public void onItemClick(AdapterView<?> parent, View view, int position,
-            long id) {
-        mMasterImage.onHistoryItemClick(position);
-        invalidateViews();
-    }
-
-    public void pickImage() {
-        Intent intent = new Intent();
-        intent.setType("image/*");
-        intent.setAction(Intent.ACTION_GET_CONTENT);
-        startActivityForResult(Intent.createChooser(intent, getString(R.string.select_image)),
-                SELECT_PICTURE);
-    }
-
-    @Override
-    public void onActivityResult(int requestCode, int resultCode, Intent data) {
-        if (resultCode == RESULT_OK) {
-            if (requestCode == SELECT_PICTURE) {
-                Uri selectedImageUri = data.getData();
-                startLoadBitmap(selectedImageUri);
-            }
-        }
-    }
-
-
-    public void saveImage() {
-        if (mImageShow.hasModifications()) {
-            // Get the name of the album, to which the image will be saved
-            File saveDir = SaveImage.getFinalSaveDirectory(this, mSelectedImageUri);
-            int bucketId = GalleryUtils.getBucketId(saveDir.getPath());
-            String albumName = LocalAlbum.getLocalizedName(getResources(), bucketId, null);
-            showSavingProgress(albumName);
-            mImageShow.saveImage(this, null);
-        } else {
-            done();
-        }
-    }
-
-
-    public void done() {
-        hideSavingProgress();
-        if (mLoadBitmapTask != null) {
-            mLoadBitmapTask.cancel(false);
-        }
-        finish();
-    }
-
-    private void extractXMPData() {
-        XMresults res = XmpPresets.extractXMPData(
-                getBaseContext(), mMasterImage, getIntent().getData());
-        if (res == null)
-            return;
-
-        mOriginalImageUri = res.originalimage;
-        mOriginalPreset = res.preset;
-    }
-
-    public Uri getSelectedImageUri() {
-        return mSelectedImageUri;
-    }
-
-}
diff --git a/src/com/android/gallery3d/filtershow/cache/ImageLoader.java b/src/com/android/gallery3d/filtershow/cache/ImageLoader.java
deleted file mode 100644
index b6c72fd..0000000
--- a/src/com/android/gallery3d/filtershow/cache/ImageLoader.java
+++ /dev/null
@@ -1,502 +0,0 @@
-/*
- * 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.gallery3d.filtershow.cache;
-
-import android.content.ContentResolver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.res.Resources;
-import android.database.Cursor;
-import android.database.sqlite.SQLiteException;
-import android.graphics.Bitmap;
-import android.graphics.BitmapFactory;
-import android.graphics.BitmapRegionDecoder;
-import android.graphics.Matrix;
-import android.graphics.Rect;
-import android.net.Uri;
-import android.provider.MediaStore;
-import android.util.Log;
-import android.webkit.MimeTypeMap;
-
-import com.adobe.xmp.XMPException;
-import com.adobe.xmp.XMPMeta;
-import com.android.gallery3d.R;
-import com.android.gallery3d.common.Utils;
-import com.android.gallery3d.exif.ExifInterface;
-import com.android.gallery3d.filtershow.imageshow.MasterImage;
-import com.android.gallery3d.util.XmpUtilHelper;
-
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.io.InputStream;
-
-public final class ImageLoader {
-
-    private static final String LOGTAG = "ImageLoader";
-
-    public static final String JPEG_MIME_TYPE = "image/jpeg";
-    public static final int DEFAULT_COMPRESS_QUALITY = 95;
-
-    public static final int ORI_NORMAL = ExifInterface.Orientation.TOP_LEFT;
-    public static final int ORI_ROTATE_90 = ExifInterface.Orientation.RIGHT_TOP;
-    public static final int ORI_ROTATE_180 = ExifInterface.Orientation.BOTTOM_LEFT;
-    public static final int ORI_ROTATE_270 = ExifInterface.Orientation.RIGHT_BOTTOM;
-    public static final int ORI_FLIP_HOR = ExifInterface.Orientation.TOP_RIGHT;
-    public static final int ORI_FLIP_VERT = ExifInterface.Orientation.BOTTOM_RIGHT;
-    public static final int ORI_TRANSPOSE = ExifInterface.Orientation.LEFT_TOP;
-    public static final int ORI_TRANSVERSE = ExifInterface.Orientation.LEFT_BOTTOM;
-
-    private static final int BITMAP_LOAD_BACKOUT_ATTEMPTS = 5;
-
-    private ImageLoader() {}
-
-    /**
-     * Returns the Mime type for a Url.  Safe to use with Urls that do not
-     * come from Gallery's content provider.
-     */
-    public static String getMimeType(Uri src) {
-        String postfix = MimeTypeMap.getFileExtensionFromUrl(src.toString());
-        String ret = null;
-        if (postfix != null) {
-            ret = MimeTypeMap.getSingleton().getMimeTypeFromExtension(postfix);
-        }
-        return ret;
-    }
-
-    /**
-     * Returns the image's orientation flag.  Defaults to ORI_NORMAL if no valid
-     * orientation was found.
-     */
-    public static int getMetadataOrientation(Context context, Uri uri) {
-        if (uri == null || context == null) {
-            throw new IllegalArgumentException("bad argument to getOrientation");
-        }
-
-        // First try to find orientation data in Gallery's ContentProvider.
-        Cursor cursor = null;
-        try {
-            cursor = context.getContentResolver().query(uri,
-                    new String[] { MediaStore.Images.ImageColumns.ORIENTATION },
-                    null, null, null);
-            if (cursor != null && cursor.moveToNext()) {
-                int ori = cursor.getInt(0);
-                switch (ori) {
-                    case 90:
-                        return ORI_ROTATE_90;
-                    case 270:
-                        return ORI_ROTATE_270;
-                    case 180:
-                        return ORI_ROTATE_180;
-                    default:
-                        return ORI_NORMAL;
-                }
-            }
-        } catch (SQLiteException e) {
-            // Do nothing
-        } catch (IllegalArgumentException e) {
-            // Do nothing
-        } finally {
-            Utils.closeSilently(cursor);
-        }
-
-        // Fall back to checking EXIF tags in file.
-        if (ContentResolver.SCHEME_FILE.equals(uri.getScheme())) {
-            String mimeType = getMimeType(uri);
-            if (!JPEG_MIME_TYPE.equals(mimeType)) {
-                return ORI_NORMAL;
-            }
-            String path = uri.getPath();
-            ExifInterface exif = new ExifInterface();
-            try {
-                exif.readExif(path);
-                Integer tagval = exif.getTagIntValue(ExifInterface.TAG_ORIENTATION);
-                if (tagval != null) {
-                    int orientation = tagval;
-                    switch(orientation) {
-                        case ORI_NORMAL:
-                        case ORI_ROTATE_90:
-                        case ORI_ROTATE_180:
-                        case ORI_ROTATE_270:
-                        case ORI_FLIP_HOR:
-                        case ORI_FLIP_VERT:
-                        case ORI_TRANSPOSE:
-                        case ORI_TRANSVERSE:
-                            return orientation;
-                        default:
-                            return ORI_NORMAL;
-                    }
-                }
-            } catch (IOException e) {
-                Log.w(LOGTAG, "Failed to read EXIF orientation", e);
-            }
-        }
-        return ORI_NORMAL;
-    }
-
-    /**
-     * Returns the rotation of image at the given URI as one of 0, 90, 180,
-     * 270.  Defaults to 0.
-     */
-    public static int getMetadataRotation(Context context, Uri uri) {
-        int orientation = getMetadataOrientation(context, uri);
-        switch(orientation) {
-            case ORI_ROTATE_90:
-                return 90;
-            case ORI_ROTATE_180:
-                return 180;
-            case ORI_ROTATE_270:
-                return 270;
-            default:
-                return 0;
-        }
-    }
-
-    /**
-     * Takes an orientation and a bitmap, and returns the bitmap transformed
-     * to that orientation.
-     */
-    public static Bitmap orientBitmap(Bitmap bitmap, int ori) {
-        Matrix matrix = new Matrix();
-        int w = bitmap.getWidth();
-        int h = bitmap.getHeight();
-        if (ori == ORI_ROTATE_90 ||
-                ori == ORI_ROTATE_270 ||
-                ori == ORI_TRANSPOSE ||
-                ori == ORI_TRANSVERSE) {
-            int tmp = w;
-            w = h;
-            h = tmp;
-        }
-        switch (ori) {
-            case ORI_ROTATE_90:
-                matrix.setRotate(90, w / 2f, h / 2f);
-                break;
-            case ORI_ROTATE_180:
-                matrix.setRotate(180, w / 2f, h / 2f);
-                break;
-            case ORI_ROTATE_270:
-                matrix.setRotate(270, w / 2f, h / 2f);
-                break;
-            case ORI_FLIP_HOR:
-                matrix.preScale(-1, 1);
-                break;
-            case ORI_FLIP_VERT:
-                matrix.preScale(1, -1);
-                break;
-            case ORI_TRANSPOSE:
-                matrix.setRotate(90, w / 2f, h / 2f);
-                matrix.preScale(1, -1);
-                break;
-            case ORI_TRANSVERSE:
-                matrix.setRotate(270, w / 2f, h / 2f);
-                matrix.preScale(1, -1);
-                break;
-            case ORI_NORMAL:
-            default:
-                return bitmap;
-        }
-        return Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(),
-                bitmap.getHeight(), matrix, true);
-    }
-
-    /**
-     * Returns the bitmap for the rectangular region given by "bounds"
-     * if it is a subset of the bitmap stored at uri.  Otherwise returns
-     * null.
-     */
-    public static Bitmap loadRegionBitmap(Context context, Uri uri, BitmapFactory.Options options,
-            Rect bounds) {
-        InputStream is = null;
-        try {
-            is = context.getContentResolver().openInputStream(uri);
-            BitmapRegionDecoder decoder = BitmapRegionDecoder.newInstance(is, false);
-            Rect r = new Rect(0, 0, decoder.getWidth(), decoder.getHeight());
-            // return null if bounds are not entirely within the bitmap
-            if (!r.contains(bounds)) {
-                return null;
-            }
-            return decoder.decodeRegion(bounds, options);
-        } catch (FileNotFoundException e) {
-            Log.e(LOGTAG, "FileNotFoundException for " + uri, e);
-        } catch (IOException e) {
-            Log.e(LOGTAG, "FileNotFoundException for " + uri, e);
-        } finally {
-            Utils.closeSilently(is);
-        }
-        return null;
-    }
-
-    /**
-     * Returns the bounds of the bitmap stored at a given Url.
-     */
-    public static Rect loadBitmapBounds(Context context, Uri uri) {
-        BitmapFactory.Options o = new BitmapFactory.Options();
-        loadBitmap(context, uri, o);
-        return new Rect(0, 0, o.outWidth, o.outHeight);
-    }
-
-    /**
-     * Loads a bitmap that has been downsampled using sampleSize from a given url.
-     */
-    public static Bitmap loadDownsampledBitmap(Context context, Uri uri, int sampleSize) {
-        BitmapFactory.Options options = new BitmapFactory.Options();
-        options.inMutable = true;
-        options.inSampleSize = sampleSize;
-        return loadBitmap(context, uri, options);
-    }
-
-
-    /**
-     * Returns the bitmap from the given uri loaded using the given options.
-     * Returns null on failure.
-     */
-    public static Bitmap loadBitmap(Context context, Uri uri, BitmapFactory.Options o) {
-        if (uri == null || context == null) {
-            throw new IllegalArgumentException("bad argument to loadBitmap");
-        }
-        InputStream is = null;
-        try {
-            is = context.getContentResolver().openInputStream(uri);
-            return BitmapFactory.decodeStream(is, null, o);
-        } catch (FileNotFoundException e) {
-            Log.e(LOGTAG, "FileNotFoundException for " + uri, e);
-        } finally {
-            Utils.closeSilently(is);
-        }
-        return null;
-    }
-
-    /**
-     * Loads a bitmap at a given URI that is downsampled so that both sides are
-     * smaller than maxSideLength. The Bitmap's original dimensions are stored
-     * in the rect originalBounds.
-     *
-     * @param uri URI of image to open.
-     * @param context context whose ContentResolver to use.
-     * @param maxSideLength max side length of returned bitmap.
-     * @param originalBounds If not null, set to the actual bounds of the stored bitmap.
-     * @param useMin use min or max side of the original image
-     * @return downsampled bitmap or null if this operation failed.
-     */
-    public static Bitmap loadConstrainedBitmap(Uri uri, Context context, int maxSideLength,
-            Rect originalBounds, boolean useMin) {
-        if (maxSideLength <= 0 || uri == null || context == null) {
-            throw new IllegalArgumentException("bad argument to getScaledBitmap");
-        }
-        // Get width and height of stored bitmap
-        Rect storedBounds = loadBitmapBounds(context, uri);
-        if (originalBounds != null) {
-            originalBounds.set(storedBounds);
-        }
-        int w = storedBounds.width();
-        int h = storedBounds.height();
-
-        // If bitmap cannot be decoded, return null
-        if (w <= 0 || h <= 0) {
-            return null;
-        }
-
-        // Find best downsampling size
-        int imageSide = 0;
-        if (useMin) {
-            imageSide = Math.min(w, h);
-        } else {
-            imageSide = Math.max(w, h);
-        }
-        int sampleSize = 1;
-        while (imageSide > maxSideLength) {
-            imageSide >>>= 1;
-            sampleSize <<= 1;
-        }
-
-        // Make sure sample size is reasonable
-        if (sampleSize <= 0 ||
-                0 >= (int) (Math.min(w, h) / sampleSize)) {
-            return null;
-        }
-        return loadDownsampledBitmap(context, uri, sampleSize);
-    }
-
-    /**
-     * Loads a bitmap at a given URI that is downsampled so that both sides are
-     * smaller than maxSideLength. The Bitmap's original dimensions are stored
-     * in the rect originalBounds.  The output is also transformed to the given
-     * orientation.
-     *
-     * @param uri URI of image to open.
-     * @param context context whose ContentResolver to use.
-     * @param maxSideLength max side length of returned bitmap.
-     * @param orientation  the orientation to transform the bitmap to.
-     * @param originalBounds set to the actual bounds of the stored bitmap.
-     * @return downsampled bitmap or null if this operation failed.
-     */
-    public static Bitmap loadOrientedConstrainedBitmap(Uri uri, Context context, int maxSideLength,
-            int orientation, Rect originalBounds) {
-        Bitmap bmap = loadConstrainedBitmap(uri, context, maxSideLength, originalBounds, false);
-        if (bmap != null) {
-            bmap = orientBitmap(bmap, orientation);
-        }
-        return bmap;
-    }
-
-    public static Bitmap getScaleOneImageForPreset(Context context, Uri uri, Rect bounds,
-            Rect destination) {
-        BitmapFactory.Options options = new BitmapFactory.Options();
-        options.inMutable = true;
-        if (destination != null) {
-            if (bounds.width() > destination.width()) {
-                int sampleSize = 1;
-                int w = bounds.width();
-                while (w > destination.width()) {
-                    sampleSize *= 2;
-                    w /= sampleSize;
-                }
-                options.inSampleSize = sampleSize;
-            }
-        }
-        Bitmap bmp = loadRegionBitmap(context, uri, options, bounds);
-        return bmp;
-    }
-
-    /**
-     * Loads a bitmap that is downsampled by at least the input sample size. In
-     * low-memory situations, the bitmap may be downsampled further.
-     */
-    public static Bitmap loadBitmapWithBackouts(Context context, Uri sourceUri, int sampleSize) {
-        boolean noBitmap = true;
-        int num_tries = 0;
-        if (sampleSize <= 0) {
-            sampleSize = 1;
-        }
-        Bitmap bmap = null;
-        while (noBitmap) {
-            try {
-                // Try to decode, downsample if low-memory.
-                bmap = loadDownsampledBitmap(context, sourceUri, sampleSize);
-                noBitmap = false;
-            } catch (java.lang.OutOfMemoryError e) {
-                // Try with more downsampling before failing for good.
-                if (++num_tries >= BITMAP_LOAD_BACKOUT_ATTEMPTS) {
-                    throw e;
-                }
-                bmap = null;
-                System.gc();
-                sampleSize *= 2;
-            }
-        }
-        return bmap;
-    }
-
-    /**
-     * Loads an oriented bitmap that is downsampled by at least the input sample
-     * size. In low-memory situations, the bitmap may be downsampled further.
-     */
-    public static Bitmap loadOrientedBitmapWithBackouts(Context context, Uri sourceUri,
-            int sampleSize) {
-        Bitmap bitmap = loadBitmapWithBackouts(context, sourceUri, sampleSize);
-        if (bitmap == null) {
-            return null;
-        }
-        int orientation = getMetadataOrientation(context, sourceUri);
-        bitmap = orientBitmap(bitmap, orientation);
-        return bitmap;
-    }
-
-    /**
-     * Loads bitmap from a resource that may be downsampled in low-memory situations.
-     */
-    public static Bitmap decodeResourceWithBackouts(Resources res, BitmapFactory.Options options,
-            int id) {
-        boolean noBitmap = true;
-        int num_tries = 0;
-        if (options.inSampleSize < 1) {
-            options.inSampleSize = 1;
-        }
-        // Stopgap fix for low-memory devices.
-        Bitmap bmap = null;
-        while (noBitmap) {
-            try {
-                // Try to decode, downsample if low-memory.
-                bmap = BitmapFactory.decodeResource(
-                        res, id, options);
-                noBitmap = false;
-            } catch (java.lang.OutOfMemoryError e) {
-                // Retry before failing for good.
-                if (++num_tries >= BITMAP_LOAD_BACKOUT_ATTEMPTS) {
-                    throw e;
-                }
-                bmap = null;
-                System.gc();
-                options.inSampleSize *= 2;
-            }
-        }
-        return bmap;
-    }
-
-    public static XMPMeta getXmpObject(Context context) {
-        try {
-            InputStream is = context.getContentResolver().openInputStream(
-                    MasterImage.getImage().getUri());
-            return XmpUtilHelper.extractXMPMeta(is);
-        } catch (FileNotFoundException e) {
-            return null;
-        }
-    }
-
-    /**
-     * Determine if this is a light cycle 360 image
-     *
-     * @return true if it is a light Cycle image that is full 360
-     */
-    public static boolean queryLightCycle360(Context context) {
-        InputStream is = null;
-        try {
-            is = context.getContentResolver().openInputStream(MasterImage.getImage().getUri());
-            XMPMeta meta = XmpUtilHelper.extractXMPMeta(is);
-            if (meta == null) {
-                return false;
-            }
-            String namespace = "http://ns.google.com/photos/1.0/panorama/";
-            String cropWidthName = "GPano:CroppedAreaImageWidthPixels";
-            String fullWidthName = "GPano:FullPanoWidthPixels";
-
-            if (!meta.doesPropertyExist(namespace, cropWidthName)) {
-                return false;
-            }
-            if (!meta.doesPropertyExist(namespace, fullWidthName)) {
-                return false;
-            }
-
-            Integer cropValue = meta.getPropertyInteger(namespace, cropWidthName);
-            Integer fullValue = meta.getPropertyInteger(namespace, fullWidthName);
-
-            // Definition of a 360:
-            // GFullPanoWidthPixels == CroppedAreaImageWidthPixels
-            if (cropValue != null && fullValue != null) {
-                return cropValue.equals(fullValue);
-            }
-
-            return false;
-        } catch (FileNotFoundException e) {
-            return false;
-        } catch (XMPException e) {
-            return false;
-        } finally {
-            Utils.closeSilently(is);
-        }
-    }
-}
diff --git a/src/com/android/gallery3d/filtershow/category/Action.java b/src/com/android/gallery3d/filtershow/category/Action.java
deleted file mode 100644
index 332ca18..0000000
--- a/src/com/android/gallery3d/filtershow/category/Action.java
+++ /dev/null
@@ -1,186 +0,0 @@
-/*
- * Copyright (C) 2013 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.gallery3d.filtershow.category;
-
-import android.content.Context;
-import android.graphics.Bitmap;
-import android.graphics.BitmapFactory;
-import android.graphics.Canvas;
-import android.graphics.Matrix;
-import android.graphics.Paint;
-import android.graphics.Rect;
-import android.graphics.RectF;
-import android.widget.ArrayAdapter;
-import android.widget.ListAdapter;
-import com.android.gallery3d.filtershow.filters.FilterUserPresetRepresentation;
-import com.android.gallery3d.filtershow.pipeline.RenderingRequest;
-import com.android.gallery3d.filtershow.pipeline.RenderingRequestCaller;
-import com.android.gallery3d.filtershow.filters.FilterRepresentation;
-import com.android.gallery3d.filtershow.imageshow.MasterImage;
-import com.android.gallery3d.filtershow.pipeline.ImagePreset;
-
-public class Action implements RenderingRequestCaller {
-
-    private static final String LOGTAG = "Action";
-    private FilterRepresentation mRepresentation;
-    private String mName;
-    private Rect mImageFrame;
-    private Bitmap mImage;
-    private ArrayAdapter mAdapter;
-    public static final int FULL_VIEW = 0;
-    public static final int CROP_VIEW = 1;
-    private int mType = CROP_VIEW;
-    private Bitmap mPortraitImage;
-    private Bitmap mOverlayBitmap;
-    private Context mContext;
-
-    public Action(Context context, FilterRepresentation representation, int type) {
-        mContext = context;
-        setRepresentation(representation);
-        setType(type);
-    }
-
-    public Action(Context context, FilterRepresentation representation) {
-        this(context, representation, CROP_VIEW);
-    }
-
-    public FilterRepresentation getRepresentation() {
-        return mRepresentation;
-    }
-
-    public void setRepresentation(FilterRepresentation representation) {
-        mRepresentation = representation;
-        mName = representation.getName();
-    }
-
-    public String getName() {
-        return mName;
-    }
-
-    public void setName(String name) {
-        mName = name;
-    }
-
-    public void setImageFrame(Rect imageFrame, int orientation) {
-        if (mImageFrame != null && mImageFrame.equals(imageFrame)) {
-            return;
-        }
-        Bitmap bitmap = MasterImage.getImage().getLargeThumbnailBitmap();
-        if (bitmap != null) {
-            mImageFrame = imageFrame;
-            int w = mImageFrame.width();
-            int h = mImageFrame.height();
-            if (orientation == CategoryView.VERTICAL
-                && mType == CROP_VIEW) {
-                w /= 2;
-            }
-            Bitmap bitmapCrop = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
-            drawCenteredImage(bitmap, bitmapCrop, true);
-
-            postNewIconRenderRequest(bitmapCrop);
-        }
-    }
-
-    public Bitmap getImage() {
-        return mImage;
-    }
-
-    public void setImage(Bitmap image) {
-        mImage = image;
-    }
-
-    public void setAdapter(ArrayAdapter adapter) {
-        mAdapter = adapter;
-    }
-
-    public void setType(int type) {
-        mType = type;
-    }
-
-    private void postNewIconRenderRequest(Bitmap bitmap) {
-        if (bitmap != null && mRepresentation != null) {
-            ImagePreset preset = new ImagePreset();
-            preset.addFilter(mRepresentation);
-            RenderingRequest.post(mContext, bitmap,
-                    preset, RenderingRequest.ICON_RENDERING, this);
-        }
-    }
-
-    private void drawCenteredImage(Bitmap source, Bitmap destination, boolean scale) {
-        RectF image = new RectF(0, 0, source.getWidth(), source.getHeight());
-        int border = 0;
-        if (!scale) {
-            border = destination.getWidth() - destination.getHeight();
-            if (border < 0) {
-                border = 0;
-            }
-        }
-        RectF frame = new RectF(border, 0,
-                destination.getWidth() - border,
-                destination.getHeight());
-        Matrix m = new Matrix();
-        m.setRectToRect(frame, image, Matrix.ScaleToFit.CENTER);
-        image.set(frame);
-        m.mapRect(image);
-        m.setRectToRect(image, frame, Matrix.ScaleToFit.FILL);
-        Canvas canvas = new Canvas(destination);
-        canvas.drawBitmap(source, m, new Paint(Paint.FILTER_BITMAP_FLAG));
-    }
-
-    @Override
-    public void available(RenderingRequest request) {
-        mImage = request.getBitmap();
-        if (mImage == null) {
-            return;
-        }
-        if (mRepresentation.getOverlayId() != 0 && mOverlayBitmap == null) {
-            mOverlayBitmap = BitmapFactory.decodeResource(
-                    mContext.getResources(),
-                    mRepresentation.getOverlayId());
-        }
-        if (mOverlayBitmap != null) {
-            if (getRepresentation().getFilterType() == FilterRepresentation.TYPE_BORDER) {
-                Canvas canvas = new Canvas(mImage);
-                canvas.drawBitmap(mOverlayBitmap, new Rect(0, 0, mOverlayBitmap.getWidth(), mOverlayBitmap.getHeight()),
-                        new Rect(0, 0, mImage.getWidth(), mImage.getHeight()), new Paint());
-            } else {
-                Canvas canvas = new Canvas(mImage);
-                canvas.drawARGB(128, 0, 0, 0);
-                drawCenteredImage(mOverlayBitmap, mImage, false);
-            }
-        }
-        if (mAdapter != null) {
-            mAdapter.notifyDataSetChanged();
-        }
-    }
-
-    public void setPortraitImage(Bitmap portraitImage) {
-        mPortraitImage = portraitImage;
-    }
-
-    public Bitmap getPortraitImage() {
-        return mPortraitImage;
-    }
-
-    public Bitmap getOverlayBitmap() {
-        return mOverlayBitmap;
-    }
-
-    public void setOverlayBitmap(Bitmap overlayBitmap) {
-        mOverlayBitmap = overlayBitmap;
-    }
-}
diff --git a/src/com/android/gallery3d/filtershow/category/CategoryAdapter.java b/src/com/android/gallery3d/filtershow/category/CategoryAdapter.java
deleted file mode 100644
index 6451c39..0000000
--- a/src/com/android/gallery3d/filtershow/category/CategoryAdapter.java
+++ /dev/null
@@ -1,182 +0,0 @@
-/*
- * Copyright (C) 2013 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.gallery3d.filtershow.category;
-
-import android.content.Context;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.ArrayAdapter;
-import android.widget.ListView;
-
-import com.android.gallery3d.filtershow.filters.FilterRepresentation;
-import com.android.gallery3d.filtershow.filters.FilterTinyPlanetRepresentation;
-import com.android.gallery3d.filtershow.pipeline.ImagePreset;
-
-public class CategoryAdapter extends ArrayAdapter<Action> {
-
-    private static final String LOGTAG = "CategoryAdapter";
-    private int mItemHeight;
-    private View mContainer;
-    private int mItemWidth = ListView.LayoutParams.MATCH_PARENT;
-    private int mSelectedPosition;
-    int mCategory;
-    private int mOrientation;
-
-    public CategoryAdapter(Context context, int textViewResourceId) {
-        super(context, textViewResourceId);
-        mItemHeight = (int) (context.getResources().getDisplayMetrics().density * 100);
-    }
-
-    public CategoryAdapter(Context context) {
-        this(context, 0);
-    }
-
-    public void setItemHeight(int height) {
-        mItemHeight = height;
-    }
-
-    public void setItemWidth(int width) {
-        mItemWidth = width;
-    }
-
-    @Override
-    public void add(Action action) {
-        super.add(action);
-        action.setAdapter(this);
-    }
-
-    public void initializeSelection(int category) {
-        mCategory = category;
-        mSelectedPosition = -1;
-        if (category == MainPanel.LOOKS) {
-            mSelectedPosition = 0;
-        }
-        if (category == MainPanel.BORDERS) {
-            mSelectedPosition = 0;
-        }
-    }
-
-    @Override
-    public View getView(int position, View convertView, ViewGroup parent) {
-        if (convertView == null) {
-            convertView = new CategoryView(getContext());
-        }
-        CategoryView view = (CategoryView) convertView;
-        view.setOrientation(mOrientation);
-        view.setAction(getItem(position), this);
-        view.setLayoutParams(
-                new ListView.LayoutParams(mItemWidth, mItemHeight));
-        view.setTag(position);
-        view.invalidate();
-        return view;
-    }
-
-    public void setSelected(View v) {
-        int old = mSelectedPosition;
-        mSelectedPosition = (Integer) v.getTag();
-        if (old != -1) {
-            invalidateView(old);
-        }
-        invalidateView(mSelectedPosition);
-    }
-
-    public boolean isSelected(View v) {
-        return (Integer) v.getTag() == mSelectedPosition;
-    }
-
-    private void invalidateView(int position) {
-        View child = null;
-        if (mContainer instanceof ListView) {
-            ListView lv = (ListView) mContainer;
-            child = lv.getChildAt(position - lv.getFirstVisiblePosition());
-        } else {
-            CategoryTrack ct = (CategoryTrack) mContainer;
-            child = ct.getChildAt(position);
-        }
-        if (child != null) {
-            child.invalidate();
-        }
-    }
-
-    public void setContainer(View container) {
-        mContainer = container;
-    }
-
-    public void imageLoaded() {
-        notifyDataSetChanged();
-    }
-
-    public FilterRepresentation getTinyPlanet() {
-        for (int i = 0; i < getCount(); i++) {
-            Action action = getItem(i);
-            if (action.getRepresentation() != null
-                    && action.getRepresentation()
-                    instanceof FilterTinyPlanetRepresentation) {
-                return action.getRepresentation();
-            }
-        }
-        return null;
-    }
-
-    public void removeTinyPlanet() {
-        for (int i = 0; i < getCount(); i++) {
-            Action action = getItem(i);
-            if (action.getRepresentation() != null
-                    && action.getRepresentation()
-                    instanceof FilterTinyPlanetRepresentation) {
-                remove(action);
-                return;
-            }
-        }
-    }
-
-    public void setOrientation(int orientation) {
-        mOrientation = orientation;
-    }
-
-    public void reflectImagePreset(ImagePreset preset) {
-        if (preset == null) {
-            return;
-        }
-        int selected = 0; // if nothing found, select "none" (first element)
-        FilterRepresentation rep = null;
-        if (mCategory == MainPanel.LOOKS) {
-            int pos = preset.getPositionForType(FilterRepresentation.TYPE_FX);
-            if (pos != -1) {
-                rep = preset.getFilterRepresentation(pos);
-            }
-        } else if (mCategory == MainPanel.BORDERS) {
-            int pos = preset.getPositionForType(FilterRepresentation.TYPE_BORDER);
-            if (pos != -1) {
-                rep = preset.getFilterRepresentation(pos);
-            }
-        }
-        if (rep != null) {
-            for (int i = 0; i < getCount(); i++) {
-                if (rep.getName().equalsIgnoreCase(
-                        getItem(i).getRepresentation().getName())) {
-                    selected = i;
-                    break;
-                }
-            }
-        }
-        if (mSelectedPosition != selected) {
-            mSelectedPosition = selected;
-            this.notifyDataSetChanged();
-        }
-    }
-}
diff --git a/src/com/android/gallery3d/filtershow/category/CategoryPanel.java b/src/com/android/gallery3d/filtershow/category/CategoryPanel.java
deleted file mode 100644
index de2481f..0000000
--- a/src/com/android/gallery3d/filtershow/category/CategoryPanel.java
+++ /dev/null
@@ -1,108 +0,0 @@
-/*
- * Copyright (C) 2013 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.gallery3d.filtershow.category;
-
-import android.app.Activity;
-import android.os.Bundle;
-import android.support.v4.app.Fragment;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.LinearLayout;
-import android.widget.ListView;
-import com.android.gallery3d.R;
-import com.android.gallery3d.filtershow.FilterShowActivity;
-
-public class CategoryPanel extends Fragment {
-
-    public static final String FRAGMENT_TAG = "CategoryPanel";
-    private static final String PARAMETER_TAG = "currentPanel";
-
-    private int mCurrentAdapter = MainPanel.LOOKS;
-    private CategoryAdapter mAdapter;
-
-    public void setAdapter(int value) {
-        mCurrentAdapter = value;
-    }
-
-    @Override
-    public void onAttach(Activity activity) {
-        super.onAttach(activity);
-        loadAdapter(mCurrentAdapter);
-    }
-
-    private void loadAdapter(int adapter) {
-        FilterShowActivity activity = (FilterShowActivity) getActivity();
-        switch (adapter) {
-            case MainPanel.LOOKS: {
-                mAdapter = activity.getCategoryLooksAdapter();
-                mAdapter.initializeSelection(MainPanel.LOOKS);
-                activity.updateCategories();
-                break;
-            }
-            case MainPanel.BORDERS: {
-                mAdapter = activity.getCategoryBordersAdapter();
-                mAdapter.initializeSelection(MainPanel.BORDERS);
-                activity.updateCategories();
-                break;
-            }
-            case MainPanel.GEOMETRY: {
-                mAdapter = activity.getCategoryGeometryAdapter();
-                mAdapter.initializeSelection(MainPanel.GEOMETRY);
-                break;
-            }
-            case MainPanel.FILTERS: {
-                mAdapter = activity.getCategoryFiltersAdapter();
-                mAdapter.initializeSelection(MainPanel.FILTERS);
-                break;
-            }
-        }
-    }
-
-    @Override
-    public void onSaveInstanceState(Bundle state) {
-        super.onSaveInstanceState(state);
-        state.putInt(PARAMETER_TAG, mCurrentAdapter);
-    }
-
-    @Override
-    public View onCreateView(LayoutInflater inflater, ViewGroup container,
-                             Bundle savedInstanceState) {
-        LinearLayout main = (LinearLayout) inflater.inflate(
-                R.layout.filtershow_category_panel_new, container,
-                false);
-
-        if (savedInstanceState != null) {
-            int selectedPanel = savedInstanceState.getInt(PARAMETER_TAG);
-            loadAdapter(selectedPanel);
-        }
-
-        View panelView = main.findViewById(R.id.listItems);
-        if (panelView instanceof CategoryTrack) {
-            CategoryTrack panel = (CategoryTrack) panelView;
-            mAdapter.setOrientation(CategoryView.HORIZONTAL);
-            panel.setAdapter(mAdapter);
-            mAdapter.setContainer(panel);
-        } else {
-            ListView panel = (ListView) main.findViewById(R.id.listItems);
-            panel.setAdapter(mAdapter);
-            mAdapter.setContainer(panel);
-        }
-        return main;
-    }
-
-}
diff --git a/src/com/android/gallery3d/filtershow/category/CategoryTrack.java b/src/com/android/gallery3d/filtershow/category/CategoryTrack.java
deleted file mode 100644
index ac8245a..0000000
--- a/src/com/android/gallery3d/filtershow/category/CategoryTrack.java
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * Copyright (C) 2013 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.gallery3d.filtershow.category;
-
-import android.content.Context;
-import android.content.res.TypedArray;
-import android.database.DataSetObserver;
-import android.util.AttributeSet;
-import android.util.Log;
-import android.view.View;
-import android.widget.LinearLayout;
-import com.android.gallery3d.R;
-
-public class CategoryTrack extends LinearLayout {
-
-    private CategoryAdapter mAdapter;
-    private int mElemSize;
-    private DataSetObserver mDataSetObserver = new DataSetObserver() {
-        @Override
-        public void onChanged() {
-            super.onChanged();
-            invalidate();
-        }
-        @Override
-        public void onInvalidated() {
-            super.onInvalidated();
-            fillContent();
-        }
-    };
-
-    public CategoryTrack(Context context, AttributeSet attrs) {
-        super(context, attrs);
-        TypedArray a = getContext().obtainStyledAttributes(attrs, R.styleable.CategoryTrack);
-        mElemSize = a.getDimensionPixelSize(R.styleable.CategoryTrack_iconSize, 0);
-    }
-
-    public void setAdapter(CategoryAdapter adapter) {
-        mAdapter = adapter;
-        mAdapter.registerDataSetObserver(mDataSetObserver);
-        fillContent();
-    }
-
-    public void fillContent() {
-        removeAllViews();
-        mAdapter.setItemWidth(mElemSize);
-        mAdapter.setItemHeight(LayoutParams.MATCH_PARENT);
-        int n = mAdapter.getCount();
-        for (int i = 0; i < n; i++) {
-            View view = mAdapter.getView(i, null, this);
-            addView(view, i);
-        }
-        requestLayout();
-    }
-
-    @Override
-    public void invalidate() {
-        for (int i = 0; i < this.getChildCount(); i++) {
-            View child = getChildAt(i);
-            child.invalidate();
-        }
-    }
-
-}
diff --git a/src/com/android/gallery3d/filtershow/category/CategoryView.java b/src/com/android/gallery3d/filtershow/category/CategoryView.java
deleted file mode 100644
index c456dc2..0000000
--- a/src/com/android/gallery3d/filtershow/category/CategoryView.java
+++ /dev/null
@@ -1,176 +0,0 @@
-/*
- * Copyright (C) 2013 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.gallery3d.filtershow.category;
-
-import android.content.Context;
-import android.content.res.Resources;
-import android.graphics.Bitmap;
-import android.graphics.Canvas;
-import android.graphics.Color;
-import android.graphics.Paint;
-import android.graphics.Rect;
-import android.graphics.Typeface;
-import android.view.View;
-import com.android.gallery3d.R;
-import com.android.gallery3d.filtershow.FilterShowActivity;
-import com.android.gallery3d.filtershow.filters.FilterRepresentation;
-import com.android.gallery3d.filtershow.ui.SelectionRenderer;
-
-public class CategoryView extends View implements View.OnClickListener {
-
-    private static final String LOGTAG = "CategoryView";
-    public static final int VERTICAL = 0;
-    public static final int HORIZONTAL = 1;
-    private Paint mPaint = new Paint();
-    private Action mAction;
-    private Rect mTextBounds = new Rect();
-    private int mMargin = 16;
-    private int mTextSize = 32;
-    private int mTextColor;
-    private int mBackgroundColor;
-    private Paint mSelectPaint;
-    CategoryAdapter mAdapter;
-    private int mSelectionStroke;
-    private Paint mBorderPaint;
-    private int mBorderStroke;
-    private int mOrientation = VERTICAL;
-
-    public CategoryView(Context context) {
-        super(context);
-        setOnClickListener(this);
-        Resources res = getResources();
-        mBackgroundColor = res.getColor(R.color.filtershow_categoryview_background);
-        mTextColor = res.getColor(R.color.filtershow_categoryview_text);
-        mSelectionStroke = res.getDimensionPixelSize(R.dimen.thumbnail_margin);
-        mTextSize = res.getDimensionPixelSize(R.dimen.category_panel_text_size);
-        mMargin = res.getDimensionPixelOffset(R.dimen.category_panel_margin);
-        mSelectPaint = new Paint();
-        mSelectPaint.setStyle(Paint.Style.FILL);
-        mSelectPaint.setColor(res.getColor(R.color.filtershow_category_selection));
-        mBorderPaint = new Paint(mSelectPaint);
-        mBorderPaint.setColor(Color.BLACK);
-        mBorderStroke = mSelectionStroke / 3;
-    }
-
-    private void computeTextPosition(String text) {
-        if (text == null) {
-            return;
-        }
-        mPaint.setTextSize(mTextSize);
-        if (mOrientation == VERTICAL) {
-            text = text.toUpperCase();
-            // TODO: set this in xml
-            mPaint.setTypeface(Typeface.DEFAULT_BOLD);
-        }
-        mPaint.getTextBounds(text, 0, text.length(), mTextBounds);
-    }
-
-    public void drawText(Canvas canvas, String text) {
-        if (text == null) {
-            return;
-        }
-        float textWidth = mPaint.measureText(text);
-        int x = (int) (canvas.getWidth() - textWidth - mMargin);
-        if (mOrientation == HORIZONTAL) {
-            x = (int) ((canvas.getWidth() - textWidth) / 2.0f);
-        }
-        if (x < 0) {
-            // If the text takes more than the view width,
-            // justify to the left.
-            x = mMargin;
-        }
-        int y = canvas.getHeight() - mMargin;
-        canvas.drawText(text, x, y, mPaint);
-    }
-
-    @Override
-    public CharSequence getContentDescription () {
-        if (mAction != null) {
-            return mAction.getName();
-        }
-        return null;
-    }
-
-    @Override
-    public void onDraw(Canvas canvas) {
-        canvas.drawColor(mBackgroundColor);
-        if (mAction != null) {
-            mPaint.reset();
-            mPaint.setAntiAlias(true);
-            computeTextPosition(mAction.getName());
-            if (mAction.getImage() == null) {
-                mAction.setImageFrame(new Rect(0, 0, getWidth(), getHeight()), mOrientation);
-            } else {
-                Bitmap bitmap = mAction.getImage();
-                canvas.save();
-                Rect clipRect = new Rect(mSelectionStroke, mSelectionStroke,
-                        getWidth() - mSelectionStroke,
-                        getHeight() - 2* mMargin - mTextSize);
-                int offsetx = 0;
-                int offsety = 0;
-                if (mOrientation == HORIZONTAL) {
-                    canvas.clipRect(clipRect);
-                    offsetx = - (bitmap.getWidth() - clipRect.width()) / 2;
-                    offsety = - (bitmap.getHeight() - clipRect.height()) / 2;
-                }
-                canvas.drawBitmap(bitmap, offsetx, offsety, mPaint);
-                canvas.restore();
-                if (mAdapter.isSelected(this)) {
-                    if (mOrientation == HORIZONTAL) {
-                        SelectionRenderer.drawSelection(canvas, 0, 0,
-                                getWidth(), getHeight() - mMargin - mTextSize,
-                                mSelectionStroke, mSelectPaint, mBorderStroke, mBorderPaint);
-                    } else {
-                        SelectionRenderer.drawSelection(canvas, 0, 0,
-                                Math.min(bitmap.getWidth(), getWidth()),
-                                Math.min(bitmap.getHeight(), getHeight()),
-                                mSelectionStroke, mSelectPaint, mBorderStroke, mBorderPaint);
-                    }
-                }
-            }
-            mPaint.setColor(mBackgroundColor);
-            mPaint.setStyle(Paint.Style.STROKE);
-            mPaint.setStrokeWidth(3);
-            drawText(canvas, mAction.getName());
-            mPaint.setColor(mTextColor);
-            mPaint.setStyle(Paint.Style.FILL);
-            mPaint.setStrokeWidth(1);
-            drawText(canvas, mAction.getName());
-        }
-    }
-
-    public void setAction(Action action, CategoryAdapter adapter) {
-        mAction = action;
-        mAdapter = adapter;
-        invalidate();
-    }
-
-    public FilterRepresentation getRepresentation() {
-        return mAction.getRepresentation();
-    }
-
-    @Override
-    public void onClick(View view) {
-        FilterShowActivity activity = (FilterShowActivity) getContext();
-        activity.showRepresentation(mAction.getRepresentation());
-        mAdapter.setSelected(this);
-    }
-
-    public void setOrientation(int orientation) {
-        mOrientation = orientation;
-    }
-}
diff --git a/src/com/android/gallery3d/filtershow/category/MainPanel.java b/src/com/android/gallery3d/filtershow/category/MainPanel.java
deleted file mode 100644
index 9a64ffb..0000000
--- a/src/com/android/gallery3d/filtershow/category/MainPanel.java
+++ /dev/null
@@ -1,239 +0,0 @@
-/*
- * Copyright (C) 2013 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.gallery3d.filtershow.category;
-
-import android.os.Bundle;
-import android.support.v4.app.Fragment;
-import android.support.v4.app.FragmentTransaction;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.ImageButton;
-import android.widget.LinearLayout;
-
-import com.android.gallery3d.R;
-import com.android.gallery3d.filtershow.FilterShowActivity;
-import com.android.gallery3d.filtershow.state.StatePanel;
-
-public class MainPanel extends Fragment {
-
-    private static final String LOGTAG = "MainPanel";
-
-    private LinearLayout mMainView;
-    private ImageButton looksButton;
-    private ImageButton bordersButton;
-    private ImageButton geometryButton;
-    private ImageButton filtersButton;
-
-    public static final String FRAGMENT_TAG = "MainPanel";
-    public static final int LOOKS = 0;
-    public static final int BORDERS = 1;
-    public static final int GEOMETRY = 2;
-    public static final int FILTERS = 3;
-
-    private int mCurrentSelected = -1;
-
-    private void selection(int position, boolean value) {
-        if (value) {
-            FilterShowActivity activity = (FilterShowActivity) getActivity();
-            activity.setCurrentPanel(position);
-        }
-        switch (position) {
-            case LOOKS: {
-                looksButton.setSelected(value);
-                break;
-            }
-            case BORDERS: {
-                bordersButton.setSelected(value);
-                break;
-            }
-            case GEOMETRY: {
-                geometryButton.setSelected(value);
-                break;
-            }
-            case FILTERS: {
-                filtersButton.setSelected(value);
-                break;
-            }
-        }
-    }
-
-    @Override
-    public void onDestroyView() {
-        super.onDestroyView();
-        if (mMainView != null) {
-            if (mMainView.getParent() != null) {
-                ViewGroup parent = (ViewGroup) mMainView.getParent();
-                parent.removeView(mMainView);
-            }
-        }
-    }
-
-    @Override
-    public View onCreateView(LayoutInflater inflater, ViewGroup container,
-                             Bundle savedInstanceState) {
-
-        mMainView = (LinearLayout) inflater.inflate(
-                R.layout.filtershow_main_panel, null, false);
-
-        looksButton = (ImageButton) mMainView.findViewById(R.id.fxButton);
-        bordersButton = (ImageButton) mMainView.findViewById(R.id.borderButton);
-        geometryButton = (ImageButton) mMainView.findViewById(R.id.geometryButton);
-        filtersButton = (ImageButton) mMainView.findViewById(R.id.colorsButton);
-
-        looksButton.setOnClickListener(new View.OnClickListener() {
-            @Override
-            public void onClick(View v) {
-                showPanel(LOOKS);
-            }
-        });
-        bordersButton.setOnClickListener(new View.OnClickListener() {
-            @Override
-            public void onClick(View v) {
-                showPanel(BORDERS);
-            }
-        });
-        geometryButton.setOnClickListener(new View.OnClickListener() {
-            @Override
-            public void onClick(View v) {
-                showPanel(GEOMETRY);
-            }
-        });
-        filtersButton.setOnClickListener(new View.OnClickListener() {
-            @Override
-            public void onClick(View v) {
-                showPanel(FILTERS);
-            }
-        });
-
-        FilterShowActivity activity = (FilterShowActivity) getActivity();
-        showImageStatePanel(activity.isShowingImageStatePanel());
-        showPanel(activity.getCurrentPanel());
-        return mMainView;
-    }
-
-    private boolean isRightAnimation(int newPos) {
-        if (newPos < mCurrentSelected) {
-            return false;
-        }
-        return true;
-    }
-
-    private void setCategoryFragment(CategoryPanel category, boolean fromRight) {
-        FragmentTransaction transaction = getChildFragmentManager().beginTransaction();
-        if (fromRight) {
-            transaction.setCustomAnimations(R.anim.slide_in_right, R.anim.slide_out_right);
-        } else {
-            transaction.setCustomAnimations(R.anim.slide_in_left, R.anim.slide_out_left);
-        }
-        transaction.replace(R.id.category_panel_container, category, CategoryPanel.FRAGMENT_TAG);
-        transaction.commit();
-    }
-
-    public void loadCategoryLookPanel() {
-        if (mCurrentSelected == LOOKS) {
-            return;
-        }
-        boolean fromRight = isRightAnimation(LOOKS);
-        selection(mCurrentSelected, false);
-        CategoryPanel categoryPanel = new CategoryPanel();
-        categoryPanel.setAdapter(LOOKS);
-        setCategoryFragment(categoryPanel, fromRight);
-        mCurrentSelected = LOOKS;
-        selection(mCurrentSelected, true);
-    }
-
-    public void loadCategoryBorderPanel() {
-        if (mCurrentSelected == BORDERS) {
-            return;
-        }
-        boolean fromRight = isRightAnimation(BORDERS);
-        selection(mCurrentSelected, false);
-        CategoryPanel categoryPanel = new CategoryPanel();
-        categoryPanel.setAdapter(BORDERS);
-        setCategoryFragment(categoryPanel, fromRight);
-        mCurrentSelected = BORDERS;
-        selection(mCurrentSelected, true);
-    }
-
-    public void loadCategoryGeometryPanel() {
-        if (mCurrentSelected == GEOMETRY) {
-            return;
-        }
-        boolean fromRight = isRightAnimation(GEOMETRY);
-        selection(mCurrentSelected, false);
-        CategoryPanel categoryPanel = new CategoryPanel();
-        categoryPanel.setAdapter(GEOMETRY);
-        setCategoryFragment(categoryPanel, fromRight);
-        mCurrentSelected = GEOMETRY;
-        selection(mCurrentSelected, true);
-    }
-
-    public void loadCategoryFiltersPanel() {
-        if (mCurrentSelected == FILTERS) {
-            return;
-        }
-        boolean fromRight = isRightAnimation(FILTERS);
-        selection(mCurrentSelected, false);
-        CategoryPanel categoryPanel = new CategoryPanel();
-        categoryPanel.setAdapter(FILTERS);
-        setCategoryFragment(categoryPanel, fromRight);
-        mCurrentSelected = FILTERS;
-        selection(mCurrentSelected, true);
-    }
-
-    public void showPanel(int currentPanel) {
-        switch (currentPanel) {
-            case LOOKS: {
-                loadCategoryLookPanel();
-                break;
-            }
-            case BORDERS: {
-                loadCategoryBorderPanel();
-                break;
-            }
-            case GEOMETRY: {
-                loadCategoryGeometryPanel();
-                break;
-            }
-            case FILTERS: {
-                loadCategoryFiltersPanel();
-                break;
-            }
-        }
-    }
-
-    public void showImageStatePanel(boolean show) {
-        if (mMainView.findViewById(R.id.state_panel_container) == null) {
-            return;
-        }
-        FragmentTransaction transaction = getChildFragmentManager().beginTransaction();
-        final View container = mMainView.findViewById(R.id.state_panel_container);
-        if (show) {
-            container.setVisibility(View.VISIBLE);
-            StatePanel statePanel = new StatePanel();
-            transaction.replace(R.id.state_panel_container, statePanel, StatePanel.FRAGMENT_TAG);
-        } else {
-            container.setVisibility(View.GONE);
-            Fragment statePanel = getChildFragmentManager().findFragmentByTag(StatePanel.FRAGMENT_TAG);
-            if (statePanel != null) {
-                transaction.remove(statePanel);
-            }
-        }
-        transaction.commit();
-    }
-}
diff --git a/src/com/android/gallery3d/filtershow/colorpicker/ColorGridDialog.java b/src/com/android/gallery3d/filtershow/colorpicker/ColorGridDialog.java
deleted file mode 100644
index dd4df7d..0000000
--- a/src/com/android/gallery3d/filtershow/colorpicker/ColorGridDialog.java
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
- * Copyright (C) 2013 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.gallery3d.filtershow.colorpicker;
-
-import android.app.Dialog;
-import android.content.Context;
-import android.graphics.Color;
-import android.graphics.drawable.GradientDrawable;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.Button;
-
-import com.android.gallery3d.R;
-
-import java.util.ArrayList;
-
-public class ColorGridDialog extends Dialog {
-    RGBListener mCallback;
-    private static final String LOGTAG = "ColorGridDialog";
-
-    public ColorGridDialog(Context context, final RGBListener cl) {
-        super(context);
-        mCallback = cl;
-        setTitle(R.string.color_pick_title);
-        setContentView(R.layout.filtershow_color_gird);
-        Button sel = (Button) findViewById(R.id.filtershow_cp_custom);
-        ArrayList<Button> b = getButtons((ViewGroup) getWindow().getDecorView());
-        int k = 0;
-        float[] hsv = new float[3];
-
-        for (Button button : b) {
-            if (!button.equals(sel)){
-                hsv[0] = (k % 5) * 360 / 5;
-                hsv[1] = (k / 5) / 3.0f;
-                hsv[2] = (k < 5) ? (k / 4f) : 1;
-                final int c = (Color.HSVToColor(hsv) & 0x00FFFFFF) | 0xAA000000;
-                GradientDrawable sd = ((GradientDrawable) button.getBackground());
-                button.setOnClickListener(new View.OnClickListener() {
-                        @Override
-                    public void onClick(View v) {
-                        mCallback.setColor(c);
-                        dismiss();
-                    }
-                });
-                sd.setColor(c);
-                k++;
-            }
-
-        }
-        sel.setOnClickListener(new View.OnClickListener() {
-                @Override
-            public void onClick(View v) {
-                showColorPicker();
-                ColorGridDialog.this.dismiss();
-            }
-        });
-    }
-
-    private ArrayList<Button> getButtons(ViewGroup vg) {
-        ArrayList<Button> list = new ArrayList<Button>();
-        for (int i = 0; i < vg.getChildCount(); i++) {
-            View v = vg.getChildAt(i);
-            if (v instanceof Button) {
-                list.add((Button) v);
-            } else if (v instanceof ViewGroup) {
-                list.addAll(getButtons((ViewGroup) v));
-            }
-        }
-        return list;
-    }
-
-    public void showColorPicker() {
-        ColorListener cl = new ColorListener() {
-                @Override
-            public void setColor(float[] hsvo) {
-                int c = Color.HSVToColor(hsvo) & 0xFFFFFF;
-                int alpha = (int) (hsvo[3] * 255);
-                c |= alpha << 24;
-                mCallback.setColor(c);
-            }
-        };
-        ColorPickerDialog cpd = new ColorPickerDialog(this.getContext(), cl);
-        cpd.show();
-    }
-
-}
diff --git a/src/com/android/gallery3d/filtershow/colorpicker/ColorListener.java b/src/com/android/gallery3d/filtershow/colorpicker/ColorListener.java
deleted file mode 100644
index 5127dad..0000000
--- a/src/com/android/gallery3d/filtershow/colorpicker/ColorListener.java
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- * Copyright (C) 2013 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.gallery3d.filtershow.colorpicker;
-
-public interface ColorListener {
-    void setColor(float[] hsvo);
-}
diff --git a/src/com/android/gallery3d/filtershow/colorpicker/ColorOpacityView.java b/src/com/android/gallery3d/filtershow/colorpicker/ColorOpacityView.java
deleted file mode 100644
index 2bff501..0000000
--- a/src/com/android/gallery3d/filtershow/colorpicker/ColorOpacityView.java
+++ /dev/null
@@ -1,197 +0,0 @@
-/*
- * Copyright (C) 2013 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.gallery3d.filtershow.colorpicker;
-
-import android.content.Context;
-import android.graphics.Bitmap;
-import android.graphics.BitmapShader;
-import android.graphics.Canvas;
-import android.graphics.Color;
-import android.graphics.LinearGradient;
-import android.graphics.Paint;
-import android.graphics.RadialGradient;
-import android.graphics.Shader;
-import android.util.AttributeSet;
-import android.util.DisplayMetrics;
-import android.view.MotionEvent;
-import android.view.View;
-
-import com.android.gallery3d.R;
-
-import java.util.ArrayList;
-
-public class ColorOpacityView extends View implements ColorListener {
-
-    private float mRadius;
-    private float mWidth;
-    private Paint mBarPaint1;
-    private Paint mLinePaint1;
-    private Paint mLinePaint2;
-    private Paint mCheckPaint;
-
-    private float mHeight;
-    private Paint mDotPaint;
-    private int mBgcolor = 0;
-
-    private float mDotRadius;
-    private float mBorder;
-
-    private float[] mHSVO = new float[4];
-    private int mSliderColor;
-    private float mDotX = mBorder;
-    private float mDotY = mBorder;
-    private final static float DOT_SIZE = ColorRectView.DOT_SIZE;
-    public final static float BORDER_SIZE = 20;;
-
-    public ColorOpacityView(Context ctx, AttributeSet attrs) {
-        super(ctx, attrs);
-        DisplayMetrics metrics = ctx.getResources().getDisplayMetrics();
-        float mDpToPix = metrics.density;
-        mDotRadius = DOT_SIZE * mDpToPix;
-        mBorder = BORDER_SIZE * mDpToPix;
-        mBarPaint1 = new Paint();
-
-        mDotPaint = new Paint();
-
-        mDotPaint.setStyle(Paint.Style.FILL);
-        mDotPaint.setColor(ctx.getResources().getColor(R.color.slider_dot_color));
-        mSliderColor = ctx.getResources().getColor(R.color.slider_line_color);
-
-        mBarPaint1.setStyle(Paint.Style.FILL);
-
-        mLinePaint1 = new Paint();
-        mLinePaint1.setColor(Color.GRAY);
-        mLinePaint2 = new Paint();
-        mLinePaint2.setColor(mSliderColor);
-        mLinePaint2.setStrokeWidth(4);
-
-        int[] colors = new int[16 * 16];
-        for (int i = 0; i < colors.length; i++) {
-            int y = i / (16 * 8);
-            int x = (i / 8) % 2;
-            colors[i] = (x == y) ? 0xFFAAAAAA : 0xFF444444;
-        }
-        Bitmap bitmap = Bitmap.createBitmap(colors, 16, 16, Bitmap.Config.ARGB_8888);
-        BitmapShader bs = new BitmapShader(bitmap, Shader.TileMode.REPEAT, Shader.TileMode.REPEAT);
-        mCheckPaint = new Paint();
-        mCheckPaint.setShader(bs);
-    }
-
-    public boolean onDown(MotionEvent e) {
-        return true;
-    }
-
-    @Override
-    public boolean onTouchEvent(MotionEvent event) {
-        float ox = mDotX;
-        float oy = mDotY;
-
-        float x = event.getX();
-        float y = event.getY();
-
-        mDotX = x;
-
-        if (mDotX < mBorder) {
-            mDotX = mBorder;
-        }
-
-        if (mDotX > mWidth - mBorder) {
-            mDotX = mWidth - mBorder;
-        }
-        mHSVO[3] = (mDotX - mBorder) / (mWidth - mBorder * 2);
-        notifyColorListeners(mHSVO);
-        setupButton();
-        invalidate((int) (ox - mDotRadius), (int) (oy - mDotRadius), (int) (ox + mDotRadius),
-                (int) (oy + mDotRadius));
-        invalidate(
-                (int) (mDotX - mDotRadius), (int) (mDotY - mDotRadius), (int) (mDotX + mDotRadius),
-                (int) (mDotY + mDotRadius));
-
-        return true;
-    }
-
-    private void setupButton() {
-        float pos = mHSVO[3] * (mWidth - mBorder * 2);
-        mDotX = pos + mBorder;
-
-        int[] colors3 = new int[] {
-        mSliderColor, mSliderColor, 0x66000000, 0 };
-        RadialGradient g = new RadialGradient(mDotX, mDotY, mDotRadius, colors3, new float[] {
-        0, .3f, .31f, 1 }, Shader.TileMode.CLAMP);
-        mDotPaint.setShader(g);
-    }
-
-    @Override
-    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
-        mWidth = w;
-        mHeight = h;
-        mDotY = mHeight / 2;
-        updatePaint();
-        setupButton();
-    }
-
-    private void updatePaint() {
-
-        int color2 = Color.HSVToColor(mHSVO);
-        int color1 = color2 & 0xFFFFFF;
-
-        Shader sg = new LinearGradient(
-                mBorder, mBorder, mWidth - mBorder, mBorder, color1, color2, Shader.TileMode.CLAMP);
-        mBarPaint1.setShader(sg);
-
-    }
-
-    @Override
-    protected void onDraw(Canvas canvas) {
-        super.onDraw(canvas);
-        canvas.drawColor(mBgcolor);
-        canvas.drawRect(mBorder, mBorder, mWidth - mBorder, mHeight - mBorder, mCheckPaint);
-        canvas.drawRect(mBorder, mBorder, mWidth - mBorder, mHeight - mBorder, mBarPaint1);
-        canvas.drawLine(mDotX, mDotY, mWidth - mBorder, mDotY, mLinePaint1);
-        canvas.drawLine(mBorder, mDotY, mDotX, mDotY, mLinePaint2);
-        if (mDotX != Float.NaN) {
-            canvas.drawCircle(mDotX, mDotY, mDotRadius, mDotPaint);
-        }
-    }
-
-    @Override
-    public void setColor(float[] hsv) {
-        System.arraycopy(hsv, 0, mHSVO, 0, mHSVO.length);
-
-        float oy = mDotY;
-
-        updatePaint();
-        setupButton();
-        invalidate();
-    }
-
-    ArrayList<ColorListener> mColorListeners = new ArrayList<ColorListener>();
-
-    public void notifyColorListeners(float[] hsvo) {
-        for (ColorListener l : mColorListeners) {
-            l.setColor(hsvo);
-        }
-    }
-
-    public void addColorListener(ColorListener l) {
-        mColorListeners.add(l);
-    }
-
-    public void removeColorListener(ColorListener l) {
-        mColorListeners.remove(l);
-    }
-}
diff --git a/src/com/android/gallery3d/filtershow/colorpicker/ColorPickerDialog.java b/src/com/android/gallery3d/filtershow/colorpicker/ColorPickerDialog.java
deleted file mode 100644
index 73a5c90..0000000
--- a/src/com/android/gallery3d/filtershow/colorpicker/ColorPickerDialog.java
+++ /dev/null
@@ -1,123 +0,0 @@
-/*
- * Copyright (C) 2013 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.gallery3d.filtershow.colorpicker;
-
-import android.app.Dialog;
-import android.content.Context;
-import android.graphics.Color;
-import android.graphics.drawable.GradientDrawable;
-import android.view.View;
-import android.widget.Button;
-import android.widget.ToggleButton;
-
-import com.android.gallery3d.R;
-
-public class ColorPickerDialog extends Dialog implements ColorListener {
-    ToggleButton mSelectedButton;
-    GradientDrawable mSelectRect;
-
-    float[] mHSVO = new float[4];
-
-    public ColorPickerDialog(Context context, final ColorListener cl) {
-        super(context);
-
-        setContentView(R.layout.filtershow_color_picker);
-        ColorValueView csv = (ColorValueView) findViewById(R.id.colorValueView);
-        ColorRectView cwv = (ColorRectView) findViewById(R.id.colorRectView);
-        ColorOpacityView cvv = (ColorOpacityView) findViewById(R.id.colorOpacityView);
-        float[] hsvo = new float[] {
-                123, .9f, 1, 1 };
-
-        mSelectRect = (GradientDrawable) getContext()
-                .getResources().getDrawable(R.drawable.filtershow_color_picker_roundrect);
-        Button selButton = (Button) findViewById(R.id.btnSelect);
-        selButton.setCompoundDrawablesWithIntrinsicBounds(null, null, mSelectRect, null);
-        Button sel = (Button) findViewById(R.id.btnSelect);
-
-        sel.setOnClickListener(new View.OnClickListener() {
-                @Override
-            public void onClick(View v) {
-                ColorPickerDialog.this.dismiss();
-                if (cl != null) {
-                    cl.setColor(mHSVO);
-                }
-            }
-        });
-
-        cwv.setColor(hsvo);
-        cvv.setColor(hsvo);
-        csv.setColor(hsvo);
-        csv.addColorListener(cwv);
-        cwv.addColorListener(csv);
-        csv.addColorListener(cvv);
-        cwv.addColorListener(cvv);
-        cvv.addColorListener(cwv);
-        cvv.addColorListener(csv);
-        cvv.addColorListener(this);
-        csv.addColorListener(this);
-        cwv.addColorListener(this);
-
-    }
-
-    void toggleClick(ToggleButton v, int[] buttons, boolean isChecked) {
-        int id = v.getId();
-        if (!isChecked) {
-            mSelectedButton = null;
-            return;
-        }
-        for (int i = 0; i < buttons.length; i++) {
-            if (id != buttons[i]) {
-                ToggleButton b = (ToggleButton) findViewById(buttons[i]);
-                b.setChecked(false);
-            }
-        }
-        mSelectedButton = v;
-
-        float[] hsv = (float[]) v.getTag();
-
-        ColorValueView csv = (ColorValueView) findViewById(R.id.colorValueView);
-        ColorRectView cwv = (ColorRectView) findViewById(R.id.colorRectView);
-        ColorOpacityView cvv = (ColorOpacityView) findViewById(R.id.colorOpacityView);
-        cwv.setColor(hsv);
-        cvv.setColor(hsv);
-        csv.setColor(hsv);
-    }
-
-    @Override
-    public void setColor(float[] hsvo) {
-        System.arraycopy(hsvo, 0, mHSVO, 0, mHSVO.length);
-        int color = Color.HSVToColor(hsvo);
-        mSelectRect.setColor(color);
-        setButtonColor(mSelectedButton, hsvo);
-    }
-
-    private void setButtonColor(ToggleButton button, float[] hsv) {
-        if (button == null) {
-            return;
-        }
-        int color = Color.HSVToColor(hsv);
-        button.setBackgroundColor(color);
-        float[] fg = new float[] {
-                (hsv[0] + 180) % 360,
-                hsv[1],
-                        (hsv[2] > .5f) ? .1f : .9f
-        };
-        button.setTextColor(Color.HSVToColor(fg));
-        button.setTag(hsv);
-    }
-
-}
diff --git a/src/com/android/gallery3d/filtershow/colorpicker/ColorRectView.java b/src/com/android/gallery3d/filtershow/colorpicker/ColorRectView.java
deleted file mode 100644
index 07d7c71..0000000
--- a/src/com/android/gallery3d/filtershow/colorpicker/ColorRectView.java
+++ /dev/null
@@ -1,225 +0,0 @@
-/*
- * Copyright (C) 2013 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.gallery3d.filtershow.colorpicker;
-
-import android.content.Context;
-import android.graphics.Canvas;
-import android.graphics.Color;
-import android.graphics.LinearGradient;
-import android.graphics.Paint;
-import android.graphics.RadialGradient;
-import android.graphics.RectF;
-import android.graphics.Shader;
-import android.graphics.SweepGradient;
-import android.util.AttributeSet;
-import android.util.DisplayMetrics;
-import android.view.MotionEvent;
-import android.view.View;
-
-import com.android.gallery3d.R;
-
-import java.util.ArrayList;
-
-public class ColorRectView extends View implements ColorListener {
-    private float mDpToPix;
-    private float mRadius = 80;
-    private float mCtrY = 100;
-    private Paint mWheelPaint1;
-    private Paint mWheelPaint2;
-    private Paint mWheelPaint3;
-    private float mCtrX = 100;
-    private Paint mDotPaint;
-    private float mDotRadus;
-    private float mBorder;
-    private int mBgcolor = 0;
-    private float mDotX = Float.NaN;
-    private float mDotY;
-    private int mSliderColor = 0xFF33B5E5;
-    private float[] mHSVO = new float[4];
-    private int[] mColors = new int[] {
-            0xFFFF0000,// red
-            0xFFFFFF00,// yellow
-            0xFF00FF00,// green
-            0xFF00FFFF,// cyan
-            0xFF0000FF,// blue
-            0xFFFF00FF,// magenta
-            0xFFFF0000,// red
-    };
-    private int mWidth;
-    private int mHeight;
-    public final static float DOT_SIZE = 20;
-    public final static float BORDER_SIZE = 10;
-
-    public ColorRectView(Context ctx, AttributeSet attrs) {
-        super(ctx, attrs);
-
-        DisplayMetrics metrics = ctx.getResources().getDisplayMetrics();
-        mDpToPix = metrics.density;
-        mDotRadus = DOT_SIZE * mDpToPix;
-        mBorder = BORDER_SIZE * mDpToPix;
-
-        mWheelPaint1 = new Paint();
-        mWheelPaint2 = new Paint();
-        mWheelPaint3 = new Paint();
-        mDotPaint = new Paint();
-
-        mDotPaint.setStyle(Paint.Style.FILL);
-        mDotPaint.setColor(ctx.getResources().getColor(R.color.slider_dot_color));
-        mSliderColor = ctx.getResources().getColor(R.color.slider_line_color);
-        mWheelPaint1.setStyle(Paint.Style.FILL);
-        mWheelPaint2.setStyle(Paint.Style.FILL);
-        mWheelPaint3.setStyle(Paint.Style.FILL);
-    }
-
-    public boolean onDown(MotionEvent e) {
-        return true;
-    }
-
-    @Override
-    public boolean onTouchEvent(MotionEvent event) {
-
-        invalidate((int) (mDotX - mDotRadus), (int) (mDotY - mDotRadus), (int) (mDotX + mDotRadus),
-                (int) (mDotY + mDotRadus));
-        float x = event.getX();
-        float y = event.getY();
-
-        x = Math.max(Math.min(x, mWidth - mBorder), mBorder);
-        y = Math.max(Math.min(y, mHeight - mBorder), mBorder);
-        mDotX = x;
-        mDotY = y;
-        float sat = 1 - (mDotY - mBorder) / (mHeight - 2 * mBorder);
-        if (sat > 1) {
-            sat = 1;
-        }
-
-        double hue = Math.PI * 2 * (mDotX - mBorder) / (mHeight - 2 * mBorder);
-        mHSVO[0] = ((float) Math.toDegrees(hue) + 360) % 360;
-        mHSVO[1] = sat;
-        notifyColorListeners(mHSVO);
-        updateDotPaint();
-        invalidate((int) (mDotX - mDotRadus), (int) (mDotY - mDotRadus), (int) (mDotX + mDotRadus),
-                (int) (mDotY + mDotRadus));
-
-        return true;
-    }
-
-    @Override
-    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
-        mWidth = w;
-        mHeight = h;
-        mCtrY = h / 2f;
-        mCtrX = w / 2f;
-        mRadius = Math.min(mCtrY, mCtrX) - 2 * mBorder;
-        setUpColorPanel();
-    }
-
-    private void setUpColorPanel() {
-        float val = mHSVO[2];
-        int v = 0xFF000000 | 0x10101 * (int) (val * 0xFF);
-        int[] colors = new int[] {
-                0x0000000, v };
-        int[] colors2 = new int[] {
-                0x0000000, 0xFF000000 };
-        int[] wheelColor = new int[mColors.length];
-        float[] hsv = new float[3];
-        for (int i = 0; i < wheelColor.length; i++) {
-            Color.colorToHSV(mColors[i], hsv);
-            hsv[2] = mHSVO[2];
-            wheelColor[i] = Color.HSVToColor(hsv);
-        }
-        updateDot();
-        updateDotPaint();
-        SweepGradient sg = new SweepGradient(mCtrX, mCtrY, wheelColor, null);
-        LinearGradient lg = new LinearGradient(
-                mBorder, 0, mWidth - mBorder, 0, wheelColor, null, Shader.TileMode.CLAMP);
-
-        mWheelPaint1.setShader(lg);
-        LinearGradient rg = new LinearGradient(
-                0, mBorder, 0, mHeight - mBorder, colors, null, Shader.TileMode.CLAMP);
-        mWheelPaint2.setShader(rg);
-        LinearGradient rg2 = new LinearGradient(
-                0, mBorder, 0, mHeight - mBorder, colors2, null, Shader.TileMode.CLAMP);
-        mWheelPaint3.setShader(rg2);
-    }
-
-    @Override
-    protected void onDraw(Canvas canvas) {
-        super.onDraw(canvas);
-        canvas.drawColor(mBgcolor);
-        RectF rect = new RectF();
-        rect.left = mBorder;
-        rect.right = mWidth - mBorder;
-        rect.top = mBorder;
-        rect.bottom = mHeight - mBorder;
-
-        canvas.drawRect(rect, mWheelPaint1);
-        canvas.drawRect(rect, mWheelPaint3);
-        canvas.drawRect(rect, mWheelPaint2);
-
-        if (mDotX != Float.NaN) {
-
-            canvas.drawCircle(mDotX, mDotY, mDotRadus, mDotPaint);
-        }
-    }
-
-    private void updateDot() {
-
-        double hue = mHSVO[0];
-        double sat = mHSVO[1];
-
-        mDotX = (float) (mBorder + (mHeight - 2 * mBorder) * Math.toRadians(hue) / (Math.PI * 2));
-        mDotY = (float) ((1 - sat) * (mHeight - 2 * mBorder) + mBorder);
-
-    }
-
-    private void updateDotPaint() {
-        int[] colors3 = new int[] {
-                mSliderColor, mSliderColor, 0x66000000, 0 };
-        RadialGradient g = new RadialGradient(mDotX, mDotY, mDotRadus, colors3, new float[] {
-                0, .3f, .31f, 1 }, Shader.TileMode.CLAMP);
-        mDotPaint.setShader(g);
-
-    }
-
-    @Override
-    public void setColor(float[] hsvo) {
-        System.arraycopy(hsvo, 0, mHSVO, 0, mHSVO.length);
-
-        setUpColorPanel();
-        invalidate();
-
-        updateDot();
-        updateDotPaint();
-
-    }
-
-    ArrayList<ColorListener> mColorListeners = new ArrayList<ColorListener>();
-
-    public void notifyColorListeners(float[] hsv) {
-        for (ColorListener l : mColorListeners) {
-            l.setColor(hsv);
-        }
-    }
-
-    public void addColorListener(ColorListener l) {
-        mColorListeners.add(l);
-    }
-
-    public void removeColorListener(ColorListener l) {
-        mColorListeners.remove(l);
-    }
-}
diff --git a/src/com/android/gallery3d/filtershow/colorpicker/ColorValueView.java b/src/com/android/gallery3d/filtershow/colorpicker/ColorValueView.java
deleted file mode 100644
index 13cb44b..0000000
--- a/src/com/android/gallery3d/filtershow/colorpicker/ColorValueView.java
+++ /dev/null
@@ -1,180 +0,0 @@
-/*
- * Copyright (C) 2013 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.gallery3d.filtershow.colorpicker;
-
-import android.content.Context;
-import android.graphics.Canvas;
-import android.graphics.Color;
-import android.graphics.LinearGradient;
-import android.graphics.Paint;
-import android.graphics.RadialGradient;
-import android.graphics.Shader;
-import android.util.AttributeSet;
-import android.util.DisplayMetrics;
-import android.view.MotionEvent;
-import android.view.View;
-
-import com.android.gallery3d.R;
-
-import java.util.ArrayList;
-
-public class ColorValueView extends View implements ColorListener {
-
-    private float mRadius;
-    private float mWidth;
-    private Paint mBarPaint1;
-    private Paint mLinePaint1;
-    private Paint mLinePaint2;
-    private float mHeight;
-    private int mBgcolor = 0;
-    private Paint mDotPaint;
-    private float dotRadus;
-    private float mBorder;
-
-    private float[] mHSVO = new float[4];
-    private int mSliderColor;
-    private float mDotX;
-    private float mDotY = mBorder;
-    private final static float DOT_SIZE = ColorRectView.DOT_SIZE;
-    private final static float BORDER_SIZE = ColorRectView.DOT_SIZE;
-
-    public ColorValueView(Context ctx, AttributeSet attrs) {
-        super(ctx, attrs);
-        DisplayMetrics metrics = ctx.getResources().getDisplayMetrics();
-        float mDpToPix = metrics.density;
-        dotRadus = DOT_SIZE * mDpToPix;
-        mBorder = BORDER_SIZE * mDpToPix;
-
-        mBarPaint1 = new Paint();
-
-        mDotPaint = new Paint();
-
-        mDotPaint.setStyle(Paint.Style.FILL);
-        mDotPaint.setColor(ctx.getResources().getColor(R.color.slider_dot_color));
-
-        mBarPaint1.setStyle(Paint.Style.FILL);
-
-        mLinePaint1 = new Paint();
-        mLinePaint1.setColor(Color.GRAY);
-        mLinePaint2 = new Paint();
-        mSliderColor = ctx.getResources().getColor(R.color.slider_line_color);
-        mLinePaint2.setColor(mSliderColor);
-        mLinePaint2.setStrokeWidth(4);
-    }
-
-    public boolean onDown(MotionEvent e) {
-        return true;
-    }
-
-    public boolean onTouchEvent(MotionEvent event) {
-        float ox = mDotX;
-        float oy = mDotY;
-
-        float x = event.getX();
-        float y = event.getY();
-
-        mDotY = y;
-
-        if (mDotY < mBorder) {
-            mDotY = mBorder;
-        }
-
-        if (mDotY > mHeight - mBorder) {
-            mDotY = mHeight - mBorder;
-        }
-        mHSVO[2] = (mDotY - mBorder) / (mHeight - mBorder * 2);
-        notifyColorListeners(mHSVO);
-        setupButton();
-        invalidate((int) (ox - dotRadus), (int) (oy - dotRadus), (int) (ox + dotRadus),
-                (int) (oy + dotRadus));
-        invalidate((int) (mDotX - dotRadus), (int) (mDotY - dotRadus), (int) (mDotX + dotRadus),
-                (int) (mDotY + dotRadus));
-
-        return true;
-    }
-
-    private void setupButton() {
-        float pos = mHSVO[2] * (mHeight - mBorder * 2);
-        mDotY = pos + mBorder;
-
-        int[] colors3 = new int[] {
-                mSliderColor, mSliderColor, 0x66000000, 0 };
-        RadialGradient g = new RadialGradient(mDotX, mDotY, dotRadus, colors3, new float[] {
-        0, .3f, .31f, 1 }, Shader.TileMode.CLAMP);
-        mDotPaint.setShader(g);
-    }
-
-    @Override
-    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
-        mWidth = w;
-        mHeight = h;
-        mDotX = mWidth / 2;
-        updatePaint();
-        setupButton();
-    }
-
-    private void updatePaint() {
-        float[] hsv = new float[] {
-                mHSVO[0], mHSVO[1], 0f };
-        int color1 = Color.HSVToColor(hsv);
-        hsv[2] = 1;
-        int color2 = Color.HSVToColor(hsv);
-
-        Shader sg = new LinearGradient(mBorder, mBorder, mBorder, mHeight - mBorder, color1, color2,
-                Shader.TileMode.CLAMP);
-        mBarPaint1.setShader(sg);
-    }
-
-    @Override
-    protected void onDraw(Canvas canvas) {
-        super.onDraw(canvas);
-        canvas.drawColor(mBgcolor);
-        canvas.drawRect(mBorder, mBorder, mWidth - mBorder, mHeight - mBorder, mBarPaint1);
-        canvas.drawLine(mDotX, mDotY, mDotX, mHeight - mBorder, mLinePaint2);
-        canvas.drawLine(mDotX, mBorder, mDotX, mDotY, mLinePaint1);
-        if (mDotX != Float.NaN) {
-            canvas.drawCircle(mDotX, mDotY, dotRadus, mDotPaint);
-        }
-    }
-
-    @Override
-    public void setColor(float[] hsvo) {
-        System.arraycopy(hsvo, 0, mHSVO, 0, mHSVO.length);
-
-        float oy = mDotY;
-        updatePaint();
-        setupButton();
-        invalidate();
-
-    }
-
-    ArrayList<ColorListener> mColorListeners = new ArrayList<ColorListener>();
-
-    public void notifyColorListeners(float[] hsv) {
-        for (ColorListener l : mColorListeners) {
-            l.setColor(hsv);
-        }
-    }
-
-    public void addColorListener(ColorListener l) {
-        mColorListeners.add(l);
-    }
-
-    public void removeColorListener(ColorListener l) {
-        mColorListeners.remove(l);
-    }
-}
diff --git a/src/com/android/gallery3d/filtershow/colorpicker/RGBListener.java b/src/com/android/gallery3d/filtershow/colorpicker/RGBListener.java
deleted file mode 100644
index 147fb91..0000000
--- a/src/com/android/gallery3d/filtershow/colorpicker/RGBListener.java
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- * Copyright (C) 2013 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.gallery3d.filtershow.colorpicker;
-
-public interface RGBListener {
-    void setColor(int hsv);
-}
diff --git a/src/com/android/gallery3d/filtershow/controller/ActionSlider.java b/src/com/android/gallery3d/filtershow/controller/ActionSlider.java
deleted file mode 100644
index f80a1ca..0000000
--- a/src/com/android/gallery3d/filtershow/controller/ActionSlider.java
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * Copyright (C) 2013 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.gallery3d.filtershow.controller;
-
-import android.util.Log;
-import android.view.View;
-import android.view.View.OnClickListener;
-import android.view.ViewGroup;
-import android.widget.ImageButton;
-
-import com.android.gallery3d.R;
-import com.android.gallery3d.filtershow.editors.Editor;
-
-public class ActionSlider extends TitledSlider {
-    private static final String LOGTAG = "ActionSlider";
-    ImageButton mLeftButton;
-    ImageButton mRightButton;
-    public ActionSlider() {
-        mLayoutID = R.layout.filtershow_control_action_slider;
-    }
-
-    @Override
-    public void setUp(ViewGroup container, Parameter parameter, Editor editor) {
-        super.setUp(container, parameter, editor);
-        mLeftButton = (ImageButton) mTopView.findViewById(R.id.leftActionButton);
-        mLeftButton.setOnClickListener(new OnClickListener() {
-
-            @Override
-            public void onClick(View v) {
-                ((ParameterActionAndInt) mParameter).fireLeftAction();
-            }
-        });
-
-        mRightButton = (ImageButton) mTopView.findViewById(R.id.rightActionButton);
-        mRightButton.setOnClickListener(new OnClickListener() {
-
-                @Override
-            public void onClick(View v) {
-                ((ParameterActionAndInt) mParameter).fireRightAction();
-            }
-        });
-        updateUI();
-    }
-
-    @Override
-    public void updateUI() {
-        super.updateUI();
-        if (mLeftButton != null) {
-            int iconId = ((ParameterActionAndInt) mParameter).getLeftIcon();
-            mLeftButton.setImageResource(iconId);
-        }
-        if (mRightButton != null) {
-            int iconId = ((ParameterActionAndInt) mParameter).getRightIcon();
-            mRightButton.setImageResource(iconId);
-        }
-    }
-}
diff --git a/src/com/android/gallery3d/filtershow/controller/BasicParameterInt.java b/src/com/android/gallery3d/filtershow/controller/BasicParameterInt.java
deleted file mode 100644
index 92145e9..0000000
--- a/src/com/android/gallery3d/filtershow/controller/BasicParameterInt.java
+++ /dev/null
@@ -1,113 +0,0 @@
-/*
- * Copyright (C) 2013 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.gallery3d.filtershow.controller;
-
-import android.util.Log;
-
-public class BasicParameterInt implements ParameterInteger {
-    protected String mParameterName;
-    protected Control mControl;
-    protected int mMaximum = 100;
-    protected int mMinimum = 0;
-    protected int mDefaultValue;
-    protected int mValue;
-    public final int ID;
-    protected FilterView mEditor;
-    private final String LOGTAG = "BasicParameterInt";
-
-    @Override
-    public void copyFrom(Parameter src) {
-        if (!(src instanceof BasicParameterInt)) {
-            throw new IllegalArgumentException(src.getClass().getName());
-        }
-        BasicParameterInt p = (BasicParameterInt) src;
-        mMaximum = p.mMaximum;
-        mMinimum = p.mMinimum;
-        mDefaultValue = p.mDefaultValue;
-        mValue = p.mValue;
-    }
-
-    public BasicParameterInt(int id, int value) {
-        ID = id;
-        mValue = value;
-    }
-
-    public BasicParameterInt(int id, int value, int min, int max) {
-        ID = id;
-        mValue = value;
-        mMinimum = min;
-        mMaximum = max;
-    }
-
-    @Override
-    public String getParameterName() {
-        return mParameterName;
-    }
-
-    @Override
-    public String getParameterType() {
-        return sParameterType;
-    }
-
-    @Override
-    public String getValueString() {
-        return mParameterName + mValue;
-    }
-
-    @Override
-    public void setController(Control control) {
-        mControl = control;
-    }
-
-    @Override
-    public int getMaximum() {
-        return mMaximum;
-    }
-
-    @Override
-    public int getMinimum() {
-        return mMinimum;
-    }
-
-    @Override
-    public int getDefaultValue() {
-        return mDefaultValue;
-    }
-
-    @Override
-    public int getValue() {
-        return mValue;
-    }
-
-    @Override
-    public void setValue(int value) {
-        mValue = value;
-        if (mEditor != null) {
-            mEditor.commitLocalRepresentation();
-        }
-    }
-
-    @Override
-    public String toString() {
-        return getValueString();
-    }
-
-    @Override
-    public void setFilterView(FilterView editor) {
-        mEditor = editor;
-    }
-}
diff --git a/src/com/android/gallery3d/filtershow/controller/BasicParameterStyle.java b/src/com/android/gallery3d/filtershow/controller/BasicParameterStyle.java
deleted file mode 100644
index fb9f95e..0000000
--- a/src/com/android/gallery3d/filtershow/controller/BasicParameterStyle.java
+++ /dev/null
@@ -1,111 +0,0 @@
-/*
- * Copyright (C) 2013 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.gallery3d.filtershow.controller;
-
-import android.content.Context;
-
-import com.android.gallery3d.filtershow.pipeline.RenderingRequestCaller;
-
-public class BasicParameterStyle implements ParameterStyles {
-    protected String mParameterName;
-    protected int mSelectedStyle;
-    protected int mNumberOfStyles;
-    protected int mDefaultStyle = 0;
-    protected Control mControl;
-    protected FilterView mEditor;
-    public final int ID;
-    private final String LOGTAG = "BasicParameterStyle";
-
-    @Override
-    public void copyFrom(Parameter src) {
-        if (!(src instanceof BasicParameterStyle)) {
-            throw new IllegalArgumentException(src.getClass().getName());
-        }
-        BasicParameterStyle p = (BasicParameterStyle) src;
-        mNumberOfStyles = p.mNumberOfStyles;
-        mSelectedStyle = p.mSelectedStyle;
-        mDefaultStyle = p.mDefaultStyle;
-    }
-
-    public BasicParameterStyle(int id, int numberOfStyles) {
-        ID = id;
-        mNumberOfStyles = numberOfStyles;
-    }
-
-    @Override
-    public String getParameterName() {
-        return mParameterName;
-    }
-
-    @Override
-    public String getParameterType() {
-        return sParameterType;
-    }
-
-    @Override
-    public String getValueString() {
-        return mParameterName + mSelectedStyle;
-    }
-
-    @Override
-    public void setController(Control control) {
-        mControl = control;
-    }
-
-    @Override
-    public int getNumberOfStyles() {
-        return mNumberOfStyles;
-    }
-
-    @Override
-    public int getDefaultSelected() {
-        return mDefaultStyle;
-    }
-
-    @Override
-    public int getSelected() {
-        return mSelectedStyle;
-    }
-
-    @Override
-    public void setSelected(int selectedStyle) {
-        mSelectedStyle = selectedStyle;
-        if (mEditor != null) {
-            mEditor.commitLocalRepresentation();
-        }
-    }
-
-    @Override
-    public void getIcon(int index, RenderingRequestCaller caller) {
-        mEditor.computeIcon(index, caller);
-    }
-
-    @Override
-    public String getStyleTitle(int index, Context context) {
-        return "";
-    }
-
-    @Override
-    public String toString() {
-        return getValueString();
-    }
-
-    @Override
-    public void setFilterView(FilterView editor) {
-        mEditor = editor;
-    }
-}
diff --git a/src/com/android/gallery3d/filtershow/controller/BasicSlider.java b/src/com/android/gallery3d/filtershow/controller/BasicSlider.java
deleted file mode 100644
index 9d8278d..0000000
--- a/src/com/android/gallery3d/filtershow/controller/BasicSlider.java
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * Copyright (C) 2013 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.gallery3d.filtershow.controller;
-
-import android.content.Context;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.LinearLayout;
-import android.widget.SeekBar;
-import android.widget.SeekBar.OnSeekBarChangeListener;
-
-import com.android.gallery3d.R;
-import com.android.gallery3d.filtershow.editors.Editor;
-
-public class BasicSlider implements Control {
-    private SeekBar mSeekBar;
-    private ParameterInteger mParameter;
-    Editor mEditor;
-
-    @Override
-    public void setUp(ViewGroup container, Parameter parameter, Editor editor) {
-        container.removeAllViews();
-        mEditor = editor;
-        Context context = container.getContext();
-        mParameter = (ParameterInteger) parameter;
-        LayoutInflater inflater =
-                (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
-        LinearLayout lp = (LinearLayout) inflater.inflate(
-                R.layout.filtershow_seekbar, container, true);
-        mSeekBar = (SeekBar) lp.findViewById(R.id.primarySeekBar);
-
-        updateUI();
-        mSeekBar.setOnSeekBarChangeListener(new OnSeekBarChangeListener() {
-
-            @Override
-            public void onStopTrackingTouch(SeekBar seekBar) {
-            }
-
-            @Override
-            public void onStartTrackingTouch(SeekBar seekBar) {
-            }
-
-            @Override
-            public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
-                if (mParameter != null) {
-                    mParameter.setValue(progress + mParameter.getMinimum());
-                    mEditor.commitLocalRepresentation();
-
-                }
-            }
-        });
-    }
-
-    @Override
-    public View getTopView() {
-        return mSeekBar;
-    }
-
-    @Override
-    public void setPrameter(Parameter parameter) {
-        mParameter = (ParameterInteger) parameter;
-        if (mSeekBar != null) {
-            updateUI();
-        }
-    }
-
-    @Override
-    public void updateUI() {
-        mSeekBar.setMax(mParameter.getMaximum() - mParameter.getMinimum());
-        mSeekBar.setProgress(mParameter.getValue() - mParameter.getMinimum());
-    }
-}
diff --git a/src/com/android/gallery3d/filtershow/controller/Control.java b/src/com/android/gallery3d/filtershow/controller/Control.java
deleted file mode 100644
index 4342290..0000000
--- a/src/com/android/gallery3d/filtershow/controller/Control.java
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Copyright (C) 2013 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.gallery3d.filtershow.controller;
-
-import android.view.View;
-import android.view.ViewGroup;
-
-import com.android.gallery3d.filtershow.editors.Editor;
-
-public interface Control {
-    public void setUp(ViewGroup container, Parameter parameter, Editor editor);
-
-    public View getTopView();
-
-    public void setPrameter(Parameter parameter);
-
-    public void updateUI();
-}
diff --git a/src/com/android/gallery3d/filtershow/controller/FilterView.java b/src/com/android/gallery3d/filtershow/controller/FilterView.java
deleted file mode 100644
index 9ca81dc..0000000
--- a/src/com/android/gallery3d/filtershow/controller/FilterView.java
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * Copyright (C) 2013 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.gallery3d.filtershow.controller;
-
-import com.android.gallery3d.filtershow.pipeline.RenderingRequestCaller;
-
-public interface FilterView {
-    public void computeIcon(int index, RenderingRequestCaller caller);
-
-    public void commitLocalRepresentation();
-}
diff --git a/src/com/android/gallery3d/filtershow/controller/Parameter.java b/src/com/android/gallery3d/filtershow/controller/Parameter.java
deleted file mode 100644
index 8f4d5c0..0000000
--- a/src/com/android/gallery3d/filtershow/controller/Parameter.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright (C) 2013 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.gallery3d.filtershow.controller;
-
-import com.android.gallery3d.filtershow.editors.Editor;
-
-public interface Parameter {
-    String getParameterName();
-
-    String getParameterType();
-
-    String getValueString();
-
-    public void setController(Control c);
-
-    public void setFilterView(FilterView editor);
-
-    public void copyFrom(Parameter src);
-}
diff --git a/src/com/android/gallery3d/filtershow/controller/ParameterActionAndInt.java b/src/com/android/gallery3d/filtershow/controller/ParameterActionAndInt.java
deleted file mode 100644
index 8a05c3a..0000000
--- a/src/com/android/gallery3d/filtershow/controller/ParameterActionAndInt.java
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright (C) 2013 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.gallery3d.filtershow.controller;
-
-public interface ParameterActionAndInt extends ParameterInteger {
-    static String sParameterType = "ParameterActionAndInt";
-
-    public void fireLeftAction();
-
-    public int getLeftIcon();
-
-    public void fireRightAction();
-
-    public int getRightIcon();
-}
diff --git a/src/com/android/gallery3d/filtershow/controller/ParameterInteger.java b/src/com/android/gallery3d/filtershow/controller/ParameterInteger.java
deleted file mode 100644
index 0bfd201..0000000
--- a/src/com/android/gallery3d/filtershow/controller/ParameterInteger.java
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright (C) 2013 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.gallery3d.filtershow.controller;
-
-public interface ParameterInteger extends Parameter {
-    static String sParameterType = "ParameterInteger";
-
-    int getMaximum();
-
-    int getMinimum();
-
-    int getDefaultValue();
-
-    int getValue();
-
-    void setValue(int value);
-}
diff --git a/src/com/android/gallery3d/filtershow/controller/ParameterSet.java b/src/com/android/gallery3d/filtershow/controller/ParameterSet.java
deleted file mode 100644
index 6b50a4d..0000000
--- a/src/com/android/gallery3d/filtershow/controller/ParameterSet.java
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * Copyright (C) 2013 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.gallery3d.filtershow.controller;
-
-public interface ParameterSet {
-    int getNumberOfParameters();
-
-    Parameter getFilterParameter(int index);
-}
diff --git a/src/com/android/gallery3d/filtershow/controller/ParameterStyles.java b/src/com/android/gallery3d/filtershow/controller/ParameterStyles.java
deleted file mode 100644
index 7d250a0..0000000
--- a/src/com/android/gallery3d/filtershow/controller/ParameterStyles.java
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright (C) 2013 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.gallery3d.filtershow.controller;
-
-import android.content.Context;
-
-import com.android.gallery3d.filtershow.pipeline.RenderingRequestCaller;
-
-public interface ParameterStyles extends Parameter {
-    public static String sParameterType = "ParameterStyles";
-
-    int getNumberOfStyles();
-
-    int getDefaultSelected();
-
-    int getSelected();
-
-    void setSelected(int value);
-
-    void getIcon(int index, RenderingRequestCaller caller);
-
-    String getStyleTitle(int index, Context context);
-}
diff --git a/src/com/android/gallery3d/filtershow/controller/StyleChooser.java b/src/com/android/gallery3d/filtershow/controller/StyleChooser.java
deleted file mode 100644
index fb613ab..0000000
--- a/src/com/android/gallery3d/filtershow/controller/StyleChooser.java
+++ /dev/null
@@ -1,88 +0,0 @@
-package com.android.gallery3d.filtershow.controller;
-
-import android.app.ActionBar.LayoutParams;
-import android.content.Context;
-import android.graphics.Bitmap;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.ImageButton;
-import android.widget.ImageView.ScaleType;
-import android.widget.LinearLayout;
-
-import com.android.gallery3d.R;
-import com.android.gallery3d.filtershow.pipeline.RenderingRequest;
-import com.android.gallery3d.filtershow.pipeline.RenderingRequestCaller;
-import com.android.gallery3d.filtershow.editors.Editor;
-
-import java.util.Vector;
-
-public class StyleChooser implements Control {
-    private final String LOGTAG = "StyleChooser";
-    protected ParameterStyles mParameter;
-    protected LinearLayout mLinearLayout;
-    protected Editor mEditor;
-    private View mTopView;
-    private Vector<ImageButton> mIconButton = new Vector<ImageButton>();
-    protected int mLayoutID = R.layout.filtershow_control_style_chooser;
-
-    @Override
-    public void setUp(ViewGroup container, Parameter parameter, Editor editor) {
-        container.removeAllViews();
-        mEditor = editor;
-        Context context = container.getContext();
-        mParameter = (ParameterStyles) parameter;
-        LayoutInflater inflater =
-                (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
-        mTopView = inflater.inflate(mLayoutID, container, true);
-        mLinearLayout = (LinearLayout) mTopView.findViewById(R.id.listStyles);
-        mTopView.setVisibility(View.VISIBLE);
-        int n = mParameter.getNumberOfStyles();
-        mIconButton.clear();
-        LayoutParams lp = new LayoutParams(120, 120);
-        for (int i = 0; i < n; i++) {
-            final ImageButton button = new ImageButton(context);
-            button.setScaleType(ScaleType.CENTER_CROP);
-            button.setLayoutParams(lp);
-            button.setBackgroundResource(android.R.color.transparent);
-            mIconButton.add(button);
-            final int buttonNo = i;
-            button.setOnClickListener(new View.OnClickListener() {
-                @Override
-                public void onClick(View arg0) {
-                    mParameter.setSelected(buttonNo);
-                }
-            });
-            mLinearLayout.addView(button);
-            mParameter.getIcon(i, new RenderingRequestCaller() {
-                @Override
-                public void available(RenderingRequest request) {
-                    Bitmap bmap = request.getBitmap();
-                    if (bmap == null) {
-                        return;
-                    }
-                    button.setImageBitmap(bmap);
-                }
-            });
-        }
-    }
-
-    @Override
-    public View getTopView() {
-        return mTopView;
-    }
-
-    @Override
-    public void setPrameter(Parameter parameter) {
-        mParameter = (ParameterStyles) parameter;
-        updateUI();
-    }
-
-    @Override
-    public void updateUI() {
-        if (mParameter == null) {
-            return;
-        }
-    }
-
-}
diff --git a/src/com/android/gallery3d/filtershow/controller/TitledSlider.java b/src/com/android/gallery3d/filtershow/controller/TitledSlider.java
deleted file mode 100644
index f29442b..0000000
--- a/src/com/android/gallery3d/filtershow/controller/TitledSlider.java
+++ /dev/null
@@ -1,106 +0,0 @@
-/*
- * Copyright (C) 2013 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.gallery3d.filtershow.controller;
-
-import android.content.Context;
-import android.util.Log;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.SeekBar;
-import android.widget.SeekBar.OnSeekBarChangeListener;
-import android.widget.TextView;
-
-import com.android.gallery3d.R;
-import com.android.gallery3d.filtershow.editors.Editor;
-
-public class TitledSlider implements Control {
-    private final String LOGTAG = "ParametricEditor";
-    private SeekBar mSeekBar;
-    private TextView mControlName;
-    private TextView mControlValue;
-    protected ParameterInteger mParameter;
-    Editor mEditor;
-    View mTopView;
-    protected int mLayoutID = R.layout.filtershow_control_title_slider;
-
-    @Override
-    public void setUp(ViewGroup container, Parameter parameter, Editor editor) {
-        container.removeAllViews();
-        mEditor = editor;
-        Context context = container.getContext();
-        mParameter = (ParameterInteger) parameter;
-        LayoutInflater inflater =
-                (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
-        mTopView = inflater.inflate(mLayoutID, container, true);
-        mTopView.setVisibility(View.VISIBLE);
-        mSeekBar = (SeekBar) mTopView.findViewById(R.id.controlValueSeekBar);
-        mControlName = (TextView) mTopView.findViewById(R.id.controlName);
-        mControlValue = (TextView) mTopView.findViewById(R.id.controlValue);
-        updateUI();
-        mSeekBar.setOnSeekBarChangeListener(new OnSeekBarChangeListener() {
-
-            @Override
-            public void onStopTrackingTouch(SeekBar seekBar) {
-            }
-
-            @Override
-            public void onStartTrackingTouch(SeekBar seekBar) {
-            }
-
-            @Override
-            public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
-                if (mParameter != null) {
-                    mParameter.setValue(progress + mParameter.getMinimum());
-                    if (mControlName != null) {
-                        mControlName.setText(mParameter.getParameterName());
-                    }
-                    if (mControlValue != null) {
-                        mControlValue.setText(Integer.toString(mParameter.getValue()));
-                    }
-                    mEditor.commitLocalRepresentation();
-                }
-            }
-        });
-    }
-
-    @Override
-    public void setPrameter(Parameter parameter) {
-        mParameter = (ParameterInteger) parameter;
-        if (mSeekBar != null)
-            updateUI();
-    }
-
-    @Override
-    public void updateUI() {
-        if (mControlName != null && mParameter.getParameterName() != null) {
-            mControlName.setText(mParameter.getParameterName().toUpperCase());
-        }
-        if (mControlValue != null) {
-            mControlValue.setText(
-                    Integer.toString(mParameter.getValue()));
-        }
-        mSeekBar.setMax(mParameter.getMaximum() - mParameter.getMinimum());
-        mSeekBar.setProgress(mParameter.getValue() - mParameter.getMinimum());
-        mEditor.commitLocalRepresentation();
-    }
-
-    @Override
-    public View getTopView() {
-        return mTopView;
-    }
-}
diff --git a/src/com/android/gallery3d/filtershow/crop/BoundedRect.java b/src/com/android/gallery3d/filtershow/crop/BoundedRect.java
deleted file mode 100644
index 13b8d6d..0000000
--- a/src/com/android/gallery3d/filtershow/crop/BoundedRect.java
+++ /dev/null
@@ -1,368 +0,0 @@
-/*
- * 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.gallery3d.filtershow.crop;
-
-import android.graphics.Matrix;
-import android.graphics.Rect;
-import android.graphics.RectF;
-
-import com.android.gallery3d.filtershow.imageshow.GeometryMathUtils;
-
-import java.util.Arrays;
-
-/**
- * Maintains invariant that inner rectangle is constrained to be within the
- * outer, rotated rectangle.
- */
-public class BoundedRect {
-    private float rot;
-    private RectF outer;
-    private RectF inner;
-    private float[] innerRotated;
-
-    public BoundedRect(float rotation, Rect outerRect, Rect innerRect) {
-        rot = rotation;
-        outer = new RectF(outerRect);
-        inner = new RectF(innerRect);
-        innerRotated = CropMath.getCornersFromRect(inner);
-        rotateInner();
-        if (!isConstrained())
-            reconstrain();
-    }
-
-    public BoundedRect(float rotation, RectF outerRect, RectF innerRect) {
-        rot = rotation;
-        outer = new RectF(outerRect);
-        inner = new RectF(innerRect);
-        innerRotated = CropMath.getCornersFromRect(inner);
-        rotateInner();
-        if (!isConstrained())
-            reconstrain();
-    }
-
-    public void resetTo(float rotation, RectF outerRect, RectF innerRect) {
-        rot = rotation;
-        outer.set(outerRect);
-        inner.set(innerRect);
-        innerRotated = CropMath.getCornersFromRect(inner);
-        rotateInner();
-        if (!isConstrained())
-            reconstrain();
-    }
-
-    /**
-     * Sets inner, and re-constrains it to fit within the rotated bounding rect.
-     */
-    public void setInner(RectF newInner) {
-        if (inner.equals(newInner))
-            return;
-        inner = newInner;
-        innerRotated = CropMath.getCornersFromRect(inner);
-        rotateInner();
-        if (!isConstrained())
-            reconstrain();
-    }
-
-    /**
-     * Sets rotation, and re-constrains inner to fit within the rotated bounding rect.
-     */
-    public void setRotation(float rotation) {
-        if (rotation == rot)
-            return;
-        rot = rotation;
-        innerRotated = CropMath.getCornersFromRect(inner);
-        rotateInner();
-        if (!isConstrained())
-            reconstrain();
-    }
-
-    public void setToInner(RectF r) {
-        r.set(inner);
-    }
-
-    public void setToOuter(RectF r) {
-        r.set(outer);
-    }
-
-    public RectF getInner() {
-        return new RectF(inner);
-    }
-
-    public RectF getOuter() {
-        return new RectF(outer);
-    }
-
-    /**
-     * Tries to move the inner rectangle by (dx, dy).  If this would cause it to leave
-     * the bounding rectangle, snaps the inner rectangle to the edge of the bounding
-     * rectangle.
-     */
-    public void moveInner(float dx, float dy) {
-        Matrix m0 = getInverseRotMatrix();
-
-        RectF translatedInner = new RectF(inner);
-        translatedInner.offset(dx, dy);
-
-        float[] translatedInnerCorners = CropMath.getCornersFromRect(translatedInner);
-        float[] outerCorners = CropMath.getCornersFromRect(outer);
-
-        m0.mapPoints(translatedInnerCorners);
-        float[] correction = {
-                0, 0
-        };
-
-        // find correction vectors for corners that have moved out of bounds
-        for (int i = 0; i < translatedInnerCorners.length; i += 2) {
-            float correctedInnerX = translatedInnerCorners[i] + correction[0];
-            float correctedInnerY = translatedInnerCorners[i + 1] + correction[1];
-            if (!CropMath.inclusiveContains(outer, correctedInnerX, correctedInnerY)) {
-                float[] badCorner = {
-                        correctedInnerX, correctedInnerY
-                };
-                float[] nearestSide = CropMath.closestSide(badCorner, outerCorners);
-                float[] correctionVec =
-                        GeometryMathUtils.shortestVectorFromPointToLine(badCorner, nearestSide);
-                correction[0] += correctionVec[0];
-                correction[1] += correctionVec[1];
-            }
-        }
-
-        for (int i = 0; i < translatedInnerCorners.length; i += 2) {
-            float correctedInnerX = translatedInnerCorners[i] + correction[0];
-            float correctedInnerY = translatedInnerCorners[i + 1] + correction[1];
-            if (!CropMath.inclusiveContains(outer, correctedInnerX, correctedInnerY)) {
-                float[] correctionVec = {
-                        correctedInnerX, correctedInnerY
-                };
-                CropMath.getEdgePoints(outer, correctionVec);
-                correctionVec[0] -= correctedInnerX;
-                correctionVec[1] -= correctedInnerY;
-                correction[0] += correctionVec[0];
-                correction[1] += correctionVec[1];
-            }
-        }
-
-        // Set correction
-        for (int i = 0; i < translatedInnerCorners.length; i += 2) {
-            float correctedInnerX = translatedInnerCorners[i] + correction[0];
-            float correctedInnerY = translatedInnerCorners[i + 1] + correction[1];
-            // update translated corners with correction vectors
-            translatedInnerCorners[i] = correctedInnerX;
-            translatedInnerCorners[i + 1] = correctedInnerY;
-        }
-
-        innerRotated = translatedInnerCorners;
-        // reconstrain to update inner
-        reconstrain();
-    }
-
-    /**
-     * Attempts to resize the inner rectangle.  If this would cause it to leave
-     * the bounding rect, clips the inner rectangle to fit.
-     */
-    public void resizeInner(RectF newInner) {
-        Matrix m = getRotMatrix();
-        Matrix m0 = getInverseRotMatrix();
-
-        float[] outerCorners = CropMath.getCornersFromRect(outer);
-        m.mapPoints(outerCorners);
-        float[] oldInnerCorners = CropMath.getCornersFromRect(inner);
-        float[] newInnerCorners = CropMath.getCornersFromRect(newInner);
-        RectF ret = new RectF(newInner);
-
-        for (int i = 0; i < newInnerCorners.length; i += 2) {
-            float[] c = {
-                    newInnerCorners[i], newInnerCorners[i + 1]
-            };
-            float[] c0 = Arrays.copyOf(c, 2);
-            m0.mapPoints(c0);
-            if (!CropMath.inclusiveContains(outer, c0[0], c0[1])) {
-                float[] outerSide = CropMath.closestSide(c, outerCorners);
-                float[] pathOfCorner = {
-                        newInnerCorners[i], newInnerCorners[i + 1],
-                        oldInnerCorners[i], oldInnerCorners[i + 1]
-                };
-                float[] p = GeometryMathUtils.lineIntersect(pathOfCorner, outerSide);
-                if (p == null) {
-                    // lines are parallel or not well defined, so don't resize
-                    p = new float[2];
-                    p[0] = oldInnerCorners[i];
-                    p[1] = oldInnerCorners[i + 1];
-                }
-                // relies on corners being in same order as method
-                // getCornersFromRect
-                switch (i) {
-                    case 0:
-                    case 1:
-                        ret.left = (p[0] > ret.left) ? p[0] : ret.left;
-                        ret.top = (p[1] > ret.top) ? p[1] : ret.top;
-                        break;
-                    case 2:
-                    case 3:
-                        ret.right = (p[0] < ret.right) ? p[0] : ret.right;
-                        ret.top = (p[1] > ret.top) ? p[1] : ret.top;
-                        break;
-                    case 4:
-                    case 5:
-                        ret.right = (p[0] < ret.right) ? p[0] : ret.right;
-                        ret.bottom = (p[1] < ret.bottom) ? p[1] : ret.bottom;
-                        break;
-                    case 6:
-                    case 7:
-                        ret.left = (p[0] > ret.left) ? p[0] : ret.left;
-                        ret.bottom = (p[1] < ret.bottom) ? p[1] : ret.bottom;
-                        break;
-                    default:
-                        break;
-                }
-            }
-        }
-        float[] retCorners = CropMath.getCornersFromRect(ret);
-        m0.mapPoints(retCorners);
-        innerRotated = retCorners;
-        // reconstrain to update inner
-        reconstrain();
-    }
-
-    /**
-     * Attempts to resize the inner rectangle.  If this would cause it to leave
-     * the bounding rect, clips the inner rectangle to fit while maintaining
-     * aspect ratio.
-     */
-    public void fixedAspectResizeInner(RectF newInner) {
-        Matrix m = getRotMatrix();
-        Matrix m0 = getInverseRotMatrix();
-
-        float aspectW = inner.width();
-        float aspectH = inner.height();
-        float aspRatio = aspectW / aspectH;
-        float[] corners = CropMath.getCornersFromRect(outer);
-
-        m.mapPoints(corners);
-        float[] oldInnerCorners = CropMath.getCornersFromRect(inner);
-        float[] newInnerCorners = CropMath.getCornersFromRect(newInner);
-
-        // find fixed corner
-        int fixed = -1;
-        if (inner.top == newInner.top) {
-            if (inner.left == newInner.left)
-                fixed = 0; // top left
-            else if (inner.right == newInner.right)
-                fixed = 2; // top right
-        } else if (inner.bottom == newInner.bottom) {
-            if (inner.right == newInner.right)
-                fixed = 4; // bottom right
-            else if (inner.left == newInner.left)
-                fixed = 6; // bottom left
-        }
-        // no fixed corner, return without update
-        if (fixed == -1)
-            return;
-        float widthSoFar = newInner.width();
-        int moved = -1;
-        for (int i = 0; i < newInnerCorners.length; i += 2) {
-            float[] c = {
-                    newInnerCorners[i], newInnerCorners[i + 1]
-            };
-            float[] c0 = Arrays.copyOf(c, 2);
-            m0.mapPoints(c0);
-            if (!CropMath.inclusiveContains(outer, c0[0], c0[1])) {
-                moved = i;
-                if (moved == fixed)
-                    continue;
-                float[] l2 = CropMath.closestSide(c, corners);
-                float[] l1 = {
-                        newInnerCorners[i], newInnerCorners[i + 1],
-                        oldInnerCorners[i], oldInnerCorners[i + 1]
-                };
-                float[] p = GeometryMathUtils.lineIntersect(l1, l2);
-                if (p == null) {
-                    // lines are parallel or not well defined, so set to old
-                    // corner
-                    p = new float[2];
-                    p[0] = oldInnerCorners[i];
-                    p[1] = oldInnerCorners[i + 1];
-                }
-                // relies on corners being in same order as method
-                // getCornersFromRect
-                float fixed_x = oldInnerCorners[fixed];
-                float fixed_y = oldInnerCorners[fixed + 1];
-                float newWidth = Math.abs(fixed_x - p[0]);
-                float newHeight = Math.abs(fixed_y - p[1]);
-                newWidth = Math.max(newWidth, aspRatio * newHeight);
-                if (newWidth < widthSoFar)
-                    widthSoFar = newWidth;
-            }
-        }
-
-        float heightSoFar = widthSoFar / aspRatio;
-        RectF ret = new RectF(inner);
-        if (fixed == 0) {
-            ret.right = ret.left + widthSoFar;
-            ret.bottom = ret.top + heightSoFar;
-        } else if (fixed == 2) {
-            ret.left = ret.right - widthSoFar;
-            ret.bottom = ret.top + heightSoFar;
-        } else if (fixed == 4) {
-            ret.left = ret.right - widthSoFar;
-            ret.top = ret.bottom - heightSoFar;
-        } else if (fixed == 6) {
-            ret.right = ret.left + widthSoFar;
-            ret.top = ret.bottom - heightSoFar;
-        }
-        float[] retCorners = CropMath.getCornersFromRect(ret);
-        m0.mapPoints(retCorners);
-        innerRotated = retCorners;
-        // reconstrain to update inner
-        reconstrain();
-    }
-
-    // internal methods
-
-    private boolean isConstrained() {
-        for (int i = 0; i < 8; i += 2) {
-            if (!CropMath.inclusiveContains(outer, innerRotated[i], innerRotated[i + 1]))
-                return false;
-        }
-        return true;
-    }
-
-    private void reconstrain() {
-        // innerRotated has been changed to have incorrect values
-        CropMath.getEdgePoints(outer, innerRotated);
-        Matrix m = getRotMatrix();
-        float[] unrotated = Arrays.copyOf(innerRotated, 8);
-        m.mapPoints(unrotated);
-        inner = CropMath.trapToRect(unrotated);
-    }
-
-    private void rotateInner() {
-        Matrix m = getInverseRotMatrix();
-        m.mapPoints(innerRotated);
-    }
-
-    private Matrix getRotMatrix() {
-        Matrix m = new Matrix();
-        m.setRotate(rot, outer.centerX(), outer.centerY());
-        return m;
-    }
-
-    private Matrix getInverseRotMatrix() {
-        Matrix m = new Matrix();
-        m.setRotate(-rot, outer.centerX(), outer.centerY());
-        return m;
-    }
-}
diff --git a/src/com/android/gallery3d/filtershow/crop/CropActivity.java b/src/com/android/gallery3d/filtershow/crop/CropActivity.java
deleted file mode 100644
index 0a0c367..0000000
--- a/src/com/android/gallery3d/filtershow/crop/CropActivity.java
+++ /dev/null
@@ -1,697 +0,0 @@
-/*
- * Copyright (C) 2013 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.gallery3d.filtershow.crop;
-
-import android.app.ActionBar;
-import android.app.Activity;
-import android.app.WallpaperManager;
-import android.content.Context;
-import android.content.Intent;
-import android.content.res.Configuration;
-import android.graphics.Bitmap;
-import android.graphics.Bitmap.CompressFormat;
-import android.graphics.BitmapFactory;
-import android.graphics.BitmapRegionDecoder;
-import android.graphics.Canvas;
-import android.graphics.Matrix;
-import android.graphics.Paint;
-import android.graphics.Rect;
-import android.graphics.RectF;
-import android.net.Uri;
-import android.os.AsyncTask;
-import android.os.Bundle;
-import android.provider.MediaStore;
-import android.util.DisplayMetrics;
-import android.util.Log;
-import android.view.View;
-import android.view.View.OnClickListener;
-import android.view.WindowManager;
-import android.widget.Toast;
-
-import com.android.gallery3d.R;
-import com.android.gallery3d.common.Utils;
-import com.android.gallery3d.filtershow.cache.ImageLoader;
-import com.android.gallery3d.filtershow.tools.SaveImage;
-
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-
-/**
- * Activity for cropping an image.
- */
-public class CropActivity extends Activity {
-    private static final String LOGTAG = "CropActivity";
-    public static final String CROP_ACTION = "com.android.camera.action.CROP";
-    private CropExtras mCropExtras = null;
-    private LoadBitmapTask mLoadBitmapTask = null;
-
-    private int mOutputX = 0;
-    private int mOutputY = 0;
-    private Bitmap mOriginalBitmap = null;
-    private RectF mOriginalBounds = null;
-    private int mOriginalRotation = 0;
-    private Uri mSourceUri = null;
-    private CropView mCropView = null;
-    private View mSaveButton = null;
-    private boolean finalIOGuard = false;
-
-    private static final int SELECT_PICTURE = 1; // request code for picker
-
-    private static final int DEFAULT_COMPRESS_QUALITY = 90;
-    /**
-     * The maximum bitmap size we allow to be returned through the intent.
-     * Intents have a maximum of 1MB in total size. However, the Bitmap seems to
-     * have some overhead to hit so that we go way below the limit here to make
-     * sure the intent stays below 1MB.We should consider just returning a byte
-     * array instead of a Bitmap instance to avoid overhead.
-     */
-    public static final int MAX_BMAP_IN_INTENT = 750000;
-
-    // Flags
-    private static final int DO_SET_WALLPAPER = 1;
-    private static final int DO_RETURN_DATA = 1 << 1;
-    private static final int DO_EXTRA_OUTPUT = 1 << 2;
-
-    private static final int FLAG_CHECK = DO_SET_WALLPAPER | DO_RETURN_DATA | DO_EXTRA_OUTPUT;
-
-    @Override
-    public void onCreate(Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-        Intent intent = getIntent();
-        setResult(RESULT_CANCELED, new Intent());
-        mCropExtras = getExtrasFromIntent(intent);
-        if (mCropExtras != null && mCropExtras.getShowWhenLocked()) {
-            getWindow().addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED);
-        }
-
-        setContentView(R.layout.crop_activity);
-        mCropView = (CropView) findViewById(R.id.cropView);
-
-        ActionBar actionBar = getActionBar();
-        actionBar.setDisplayOptions(ActionBar.DISPLAY_SHOW_CUSTOM);
-        actionBar.setCustomView(R.layout.filtershow_actionbar);
-
-        View mSaveButton = actionBar.getCustomView();
-        mSaveButton.setOnClickListener(new OnClickListener() {
-            @Override
-            public void onClick(View view) {
-                startFinishOutput();
-            }
-        });
-
-        if (intent.getData() != null) {
-            mSourceUri = intent.getData();
-            startLoadBitmap(mSourceUri);
-        } else {
-            pickImage();
-        }
-    }
-
-    private void enableSave(boolean enable) {
-        if (mSaveButton != null) {
-            mSaveButton.setEnabled(enable);
-        }
-    }
-
-    @Override
-    protected void onDestroy() {
-        if (mLoadBitmapTask != null) {
-            mLoadBitmapTask.cancel(false);
-        }
-        super.onDestroy();
-    }
-
-    @Override
-    public void onConfigurationChanged (Configuration newConfig) {
-        super.onConfigurationChanged(newConfig);
-        mCropView.configChanged();
-    }
-
-    /**
-     * Opens a selector in Gallery to chose an image for use when none was given
-     * in the CROP intent.
-     */
-    private void pickImage() {
-        Intent intent = new Intent();
-        intent.setType("image/*");
-        intent.setAction(Intent.ACTION_GET_CONTENT);
-        startActivityForResult(Intent.createChooser(intent, getString(R.string.select_image)),
-                SELECT_PICTURE);
-    }
-
-    /**
-     * Callback for pickImage().
-     */
-    @Override
-    public void onActivityResult(int requestCode, int resultCode, Intent data) {
-        if (resultCode == RESULT_OK && requestCode == SELECT_PICTURE) {
-            mSourceUri = data.getData();
-            startLoadBitmap(mSourceUri);
-        }
-    }
-
-    /**
-     * Gets screen size metric.
-     */
-    private int getScreenImageSize() {
-        DisplayMetrics outMetrics = new DisplayMetrics();
-        getWindowManager().getDefaultDisplay().getMetrics(outMetrics);
-        return (int) Math.max(outMetrics.heightPixels, outMetrics.widthPixels);
-    }
-
-    /**
-     * Method that loads a bitmap in an async task.
-     */
-    private void startLoadBitmap(Uri uri) {
-        if (uri != null) {
-            enableSave(false);
-            final View loading = findViewById(R.id.loading);
-            loading.setVisibility(View.VISIBLE);
-            mLoadBitmapTask = new LoadBitmapTask();
-            mLoadBitmapTask.execute(uri);
-        } else {
-            cannotLoadImage();
-            done();
-        }
-    }
-
-    /**
-     * Method called on UI thread with loaded bitmap.
-     */
-    private void doneLoadBitmap(Bitmap bitmap, RectF bounds, int orientation) {
-        final View loading = findViewById(R.id.loading);
-        loading.setVisibility(View.GONE);
-        mOriginalBitmap = bitmap;
-        mOriginalBounds = bounds;
-        mOriginalRotation = orientation;
-        if (bitmap != null && bitmap.getWidth() != 0 && bitmap.getHeight() != 0) {
-            RectF imgBounds = new RectF(0, 0, bitmap.getWidth(), bitmap.getHeight());
-            mCropView.initialize(bitmap, imgBounds, imgBounds, orientation);
-            if (mCropExtras != null) {
-                int aspectX = mCropExtras.getAspectX();
-                int aspectY = mCropExtras.getAspectY();
-                mOutputX = mCropExtras.getOutputX();
-                mOutputY = mCropExtras.getOutputY();
-                if (mOutputX > 0 && mOutputY > 0) {
-                    mCropView.applyAspect(mOutputX, mOutputY);
-
-                }
-                float spotX = mCropExtras.getSpotlightX();
-                float spotY = mCropExtras.getSpotlightY();
-                if (spotX > 0 && spotY > 0) {
-                    mCropView.setWallpaperSpotlight(spotX, spotY);
-                }
-                if (aspectX > 0 && aspectY > 0) {
-                    mCropView.applyAspect(aspectX, aspectY);
-                }
-            }
-            enableSave(true);
-        } else {
-            Log.w(LOGTAG, "could not load image for cropping");
-            cannotLoadImage();
-            setResult(RESULT_CANCELED, new Intent());
-            done();
-        }
-    }
-
-    /**
-     * Display toast for image loading failure.
-     */
-    private void cannotLoadImage() {
-        CharSequence text = getString(R.string.cannot_load_image);
-        Toast toast = Toast.makeText(this, text, Toast.LENGTH_SHORT);
-        toast.show();
-    }
-
-    /**
-     * AsyncTask for loading a bitmap into memory.
-     *
-     * @see #startLoadBitmap(Uri)
-     * @see #doneLoadBitmap(Bitmap)
-     */
-    private class LoadBitmapTask extends AsyncTask<Uri, Void, Bitmap> {
-        int mBitmapSize;
-        Context mContext;
-        Rect mOriginalBounds;
-        int mOrientation;
-
-        public LoadBitmapTask() {
-            mBitmapSize = getScreenImageSize();
-            mContext = getApplicationContext();
-            mOriginalBounds = new Rect();
-            mOrientation = 0;
-        }
-
-        @Override
-        protected Bitmap doInBackground(Uri... params) {
-            Uri uri = params[0];
-            Bitmap bmap = ImageLoader.loadConstrainedBitmap(uri, mContext, mBitmapSize,
-                    mOriginalBounds, false);
-            mOrientation = ImageLoader.getMetadataRotation(mContext, uri);
-            return bmap;
-        }
-
-        @Override
-        protected void onPostExecute(Bitmap result) {
-            doneLoadBitmap(result, new RectF(mOriginalBounds), mOrientation);
-        }
-    }
-
-    private void startFinishOutput() {
-        if (finalIOGuard) {
-            return;
-        } else {
-            finalIOGuard = true;
-        }
-        enableSave(false);
-        Uri destinationUri = null;
-        int flags = 0;
-        if (mOriginalBitmap != null && mCropExtras != null) {
-            if (mCropExtras.getExtraOutput() != null) {
-                destinationUri = mCropExtras.getExtraOutput();
-                if (destinationUri != null) {
-                    flags |= DO_EXTRA_OUTPUT;
-                }
-            }
-            if (mCropExtras.getSetAsWallpaper()) {
-                flags |= DO_SET_WALLPAPER;
-            }
-            if (mCropExtras.getReturnData()) {
-                flags |= DO_RETURN_DATA;
-            }
-        }
-        if (flags == 0) {
-            destinationUri = SaveImage.makeAndInsertUri(this, mSourceUri);
-            if (destinationUri != null) {
-                flags |= DO_EXTRA_OUTPUT;
-            }
-        }
-        if ((flags & FLAG_CHECK) != 0 && mOriginalBitmap != null) {
-            RectF photo = new RectF(0, 0, mOriginalBitmap.getWidth(), mOriginalBitmap.getHeight());
-            RectF crop = getBitmapCrop(photo);
-            startBitmapIO(flags, mOriginalBitmap, mSourceUri, destinationUri, crop,
-                    photo, mOriginalBounds,
-                    (mCropExtras == null) ? null : mCropExtras.getOutputFormat(), mOriginalRotation);
-            return;
-        }
-        setResult(RESULT_CANCELED, new Intent());
-        done();
-        return;
-    }
-
-    private void startBitmapIO(int flags, Bitmap currentBitmap, Uri sourceUri, Uri destUri,
-            RectF cropBounds, RectF photoBounds, RectF currentBitmapBounds, String format,
-            int rotation) {
-        if (cropBounds == null || photoBounds == null || currentBitmap == null
-                || currentBitmap.getWidth() == 0 || currentBitmap.getHeight() == 0
-                || cropBounds.width() == 0 || cropBounds.height() == 0 || photoBounds.width() == 0
-                || photoBounds.height() == 0) {
-            return; // fail fast
-        }
-        if ((flags & FLAG_CHECK) == 0) {
-            return; // no output options
-        }
-        if ((flags & DO_SET_WALLPAPER) != 0) {
-            Toast.makeText(this, R.string.setting_wallpaper, Toast.LENGTH_LONG).show();
-        }
-
-        final View loading = findViewById(R.id.loading);
-        loading.setVisibility(View.VISIBLE);
-        BitmapIOTask ioTask = new BitmapIOTask(sourceUri, destUri, format, flags, cropBounds,
-                photoBounds, currentBitmapBounds, rotation, mOutputX, mOutputY);
-        ioTask.execute(currentBitmap);
-    }
-
-    private void doneBitmapIO(boolean success, Intent intent) {
-        final View loading = findViewById(R.id.loading);
-        loading.setVisibility(View.GONE);
-        if (success) {
-            setResult(RESULT_OK, intent);
-        } else {
-            setResult(RESULT_CANCELED, intent);
-        }
-        done();
-    }
-
-    private class BitmapIOTask extends AsyncTask<Bitmap, Void, Boolean> {
-
-        private final WallpaperManager mWPManager;
-        InputStream mInStream = null;
-        OutputStream mOutStream = null;
-        String mOutputFormat = null;
-        Uri mOutUri = null;
-        Uri mInUri = null;
-        int mFlags = 0;
-        RectF mCrop = null;
-        RectF mPhoto = null;
-        RectF mOrig = null;
-        Intent mResultIntent = null;
-        int mRotation = 0;
-
-        // Helper to setup input stream
-        private void regenerateInputStream() {
-            if (mInUri == null) {
-                Log.w(LOGTAG, "cannot read original file, no input URI given");
-            } else {
-                Utils.closeSilently(mInStream);
-                try {
-                    mInStream = getContentResolver().openInputStream(mInUri);
-                } catch (FileNotFoundException e) {
-                    Log.w(LOGTAG, "cannot read file: " + mInUri.toString(), e);
-                }
-            }
-        }
-
-        public BitmapIOTask(Uri sourceUri, Uri destUri, String outputFormat, int flags,
-                RectF cropBounds, RectF photoBounds, RectF originalBitmapBounds, int rotation,
-                int outputX, int outputY) {
-            mOutputFormat = outputFormat;
-            mOutStream = null;
-            mOutUri = destUri;
-            mInUri = sourceUri;
-            mFlags = flags;
-            mCrop = cropBounds;
-            mPhoto = photoBounds;
-            mOrig = originalBitmapBounds;
-            mWPManager = WallpaperManager.getInstance(getApplicationContext());
-            mResultIntent = new Intent();
-            mRotation = (rotation < 0) ? -rotation : rotation;
-            mRotation %= 360;
-            mRotation = 90 * (int) (mRotation / 90);  // now mRotation is a multiple of 90
-            mOutputX = outputX;
-            mOutputY = outputY;
-
-            if ((flags & DO_EXTRA_OUTPUT) != 0) {
-                if (mOutUri == null) {
-                    Log.w(LOGTAG, "cannot write file, no output URI given");
-                } else {
-                    try {
-                        mOutStream = getContentResolver().openOutputStream(mOutUri);
-                    } catch (FileNotFoundException e) {
-                        Log.w(LOGTAG, "cannot write file: " + mOutUri.toString(), e);
-                    }
-                }
-            }
-
-            if ((flags & (DO_EXTRA_OUTPUT | DO_SET_WALLPAPER)) != 0) {
-                regenerateInputStream();
-            }
-        }
-
-        @Override
-        protected Boolean doInBackground(Bitmap... params) {
-            boolean failure = false;
-            Bitmap img = params[0];
-
-            // Set extra for crop bounds
-            if (mCrop != null && mPhoto != null && mOrig != null) {
-                RectF trueCrop = CropMath.getScaledCropBounds(mCrop, mPhoto, mOrig);
-                Matrix m = new Matrix();
-                m.setRotate(mRotation);
-                m.mapRect(trueCrop);
-                if (trueCrop != null) {
-                    Rect rounded = new Rect();
-                    trueCrop.roundOut(rounded);
-                    mResultIntent.putExtra(CropExtras.KEY_CROPPED_RECT, rounded);
-                }
-            }
-
-            // Find the small cropped bitmap that is returned in the intent
-            if ((mFlags & DO_RETURN_DATA) != 0) {
-                assert (img != null);
-                Bitmap ret = getCroppedImage(img, mCrop, mPhoto);
-                if (ret != null) {
-                    ret = getDownsampledBitmap(ret, MAX_BMAP_IN_INTENT);
-                }
-                if (ret == null) {
-                    Log.w(LOGTAG, "could not downsample bitmap to return in data");
-                    failure = true;
-                } else {
-                    if (mRotation > 0) {
-                        Matrix m = new Matrix();
-                        m.setRotate(mRotation);
-                        Bitmap tmp = Bitmap.createBitmap(ret, 0, 0, ret.getWidth(),
-                                ret.getHeight(), m, true);
-                        if (tmp != null) {
-                            ret = tmp;
-                        }
-                    }
-                    mResultIntent.putExtra(CropExtras.KEY_DATA, ret);
-                }
-            }
-
-            // Do the large cropped bitmap and/or set the wallpaper
-            if ((mFlags & (DO_EXTRA_OUTPUT | DO_SET_WALLPAPER)) != 0 && mInStream != null) {
-                // Find crop bounds (scaled to original image size)
-                RectF trueCrop = CropMath.getScaledCropBounds(mCrop, mPhoto, mOrig);
-                if (trueCrop == null) {
-                    Log.w(LOGTAG, "cannot find crop for full size image");
-                    failure = true;
-                    return false;
-                }
-                Rect roundedTrueCrop = new Rect();
-                trueCrop.roundOut(roundedTrueCrop);
-
-                if (roundedTrueCrop.width() <= 0 || roundedTrueCrop.height() <= 0) {
-                    Log.w(LOGTAG, "crop has bad values for full size image");
-                    failure = true;
-                    return false;
-                }
-
-                // Attempt to open a region decoder
-                BitmapRegionDecoder decoder = null;
-                try {
-                    decoder = BitmapRegionDecoder.newInstance(mInStream, true);
-                } catch (IOException e) {
-                    Log.w(LOGTAG, "cannot open region decoder for file: " + mInUri.toString(), e);
-                }
-
-                Bitmap crop = null;
-                if (decoder != null) {
-                    // Do region decoding to get crop bitmap
-                    BitmapFactory.Options options = new BitmapFactory.Options();
-                    options.inMutable = true;
-                    crop = decoder.decodeRegion(roundedTrueCrop, options);
-                    decoder.recycle();
-                }
-
-                if (crop == null) {
-                    // BitmapRegionDecoder has failed, try to crop in-memory
-                    regenerateInputStream();
-                    Bitmap fullSize = null;
-                    if (mInStream != null) {
-                        fullSize = BitmapFactory.decodeStream(mInStream);
-                    }
-                    if (fullSize != null) {
-                        crop = Bitmap.createBitmap(fullSize, roundedTrueCrop.left,
-                                roundedTrueCrop.top, roundedTrueCrop.width(),
-                                roundedTrueCrop.height());
-                    }
-                }
-
-                if (crop == null) {
-                    Log.w(LOGTAG, "cannot decode file: " + mInUri.toString());
-                    failure = true;
-                    return false;
-                }
-                if (mOutputX > 0 && mOutputY > 0) {
-                    Matrix m = new Matrix();
-                    RectF cropRect = new RectF(0, 0, crop.getWidth(), crop.getHeight());
-                    if (mRotation > 0) {
-                        m.setRotate(mRotation);
-                        m.mapRect(cropRect);
-                    }
-                    RectF returnRect = new RectF(0, 0, mOutputX, mOutputY);
-                    m.setRectToRect(cropRect, returnRect, Matrix.ScaleToFit.FILL);
-                    m.preRotate(mRotation);
-                    Bitmap tmp = Bitmap.createBitmap((int) returnRect.width(),
-                            (int) returnRect.height(), Bitmap.Config.ARGB_8888);
-                    if (tmp != null) {
-                        Canvas c = new Canvas(tmp);
-                        c.drawBitmap(crop, m, new Paint());
-                        crop = tmp;
-                    }
-                } else if (mRotation > 0) {
-                    Matrix m = new Matrix();
-                    m.setRotate(mRotation);
-                    Bitmap tmp = Bitmap.createBitmap(crop, 0, 0, crop.getWidth(),
-                            crop.getHeight(), m, true);
-                    if (tmp != null) {
-                        crop = tmp;
-                    }
-                }
-                // Get output compression format
-                CompressFormat cf =
-                        convertExtensionToCompressFormat(getFileExtension(mOutputFormat));
-
-                // If we only need to output to a URI, compress straight to file
-                if (mFlags == DO_EXTRA_OUTPUT) {
-                    if (mOutStream == null
-                            || !crop.compress(cf, DEFAULT_COMPRESS_QUALITY, mOutStream)) {
-                        Log.w(LOGTAG, "failed to compress bitmap to file: " + mOutUri.toString());
-                        failure = true;
-                    } else {
-                        mResultIntent.setData(mOutUri);
-                    }
-                } else {
-                    // Compress to byte array
-                    ByteArrayOutputStream tmpOut = new ByteArrayOutputStream(2048);
-                    if (crop.compress(cf, DEFAULT_COMPRESS_QUALITY, tmpOut)) {
-
-                        // If we need to output to a Uri, write compressed
-                        // bitmap out
-                        if ((mFlags & DO_EXTRA_OUTPUT) != 0) {
-                            if (mOutStream == null) {
-                                Log.w(LOGTAG,
-                                        "failed to compress bitmap to file: " + mOutUri.toString());
-                                failure = true;
-                            } else {
-                                try {
-                                    mOutStream.write(tmpOut.toByteArray());
-                                    mResultIntent.setData(mOutUri);
-                                } catch (IOException e) {
-                                    Log.w(LOGTAG,
-                                            "failed to compress bitmap to file: "
-                                                    + mOutUri.toString(), e);
-                                    failure = true;
-                                }
-                            }
-                        }
-
-                        // If we need to set to the wallpaper, set it
-                        if ((mFlags & DO_SET_WALLPAPER) != 0 && mWPManager != null) {
-                            if (mWPManager == null) {
-                                Log.w(LOGTAG, "no wallpaper manager");
-                                failure = true;
-                            } else {
-                                try {
-                                    mWPManager.setStream(new ByteArrayInputStream(tmpOut
-                                            .toByteArray()));
-                                } catch (IOException e) {
-                                    Log.w(LOGTAG, "cannot write stream to wallpaper", e);
-                                    failure = true;
-                                }
-                            }
-                        }
-                    } else {
-                        Log.w(LOGTAG, "cannot compress bitmap");
-                        failure = true;
-                    }
-                }
-            }
-            return !failure; // True if any of the operations failed
-        }
-
-        @Override
-        protected void onPostExecute(Boolean result) {
-            Utils.closeSilently(mOutStream);
-            Utils.closeSilently(mInStream);
-            doneBitmapIO(result.booleanValue(), mResultIntent);
-        }
-
-    }
-
-    private void done() {
-        finish();
-    }
-
-    protected static Bitmap getCroppedImage(Bitmap image, RectF cropBounds, RectF photoBounds) {
-        RectF imageBounds = new RectF(0, 0, image.getWidth(), image.getHeight());
-        RectF crop = CropMath.getScaledCropBounds(cropBounds, photoBounds, imageBounds);
-        if (crop == null) {
-            return null;
-        }
-        Rect intCrop = new Rect();
-        crop.roundOut(intCrop);
-        return Bitmap.createBitmap(image, intCrop.left, intCrop.top, intCrop.width(),
-                intCrop.height());
-    }
-
-    protected static Bitmap getDownsampledBitmap(Bitmap image, int max_size) {
-        if (image == null || image.getWidth() == 0 || image.getHeight() == 0 || max_size < 16) {
-            throw new IllegalArgumentException("Bad argument to getDownsampledBitmap()");
-        }
-        int shifts = 0;
-        int size = CropMath.getBitmapSize(image);
-        while (size > max_size) {
-            shifts++;
-            size /= 4;
-        }
-        Bitmap ret = Bitmap.createScaledBitmap(image, image.getWidth() >> shifts,
-                image.getHeight() >> shifts, true);
-        if (ret == null) {
-            return null;
-        }
-        // Handle edge case for rounding.
-        if (CropMath.getBitmapSize(ret) > max_size) {
-            return Bitmap.createScaledBitmap(ret, ret.getWidth() >> 1, ret.getHeight() >> 1, true);
-        }
-        return ret;
-    }
-
-    /**
-     * Gets the crop extras from the intent, or null if none exist.
-     */
-    protected static CropExtras getExtrasFromIntent(Intent intent) {
-        Bundle extras = intent.getExtras();
-        if (extras != null) {
-            return new CropExtras(extras.getInt(CropExtras.KEY_OUTPUT_X, 0),
-                    extras.getInt(CropExtras.KEY_OUTPUT_Y, 0),
-                    extras.getBoolean(CropExtras.KEY_SCALE, true) &&
-                            extras.getBoolean(CropExtras.KEY_SCALE_UP_IF_NEEDED, false),
-                    extras.getInt(CropExtras.KEY_ASPECT_X, 0),
-                    extras.getInt(CropExtras.KEY_ASPECT_Y, 0),
-                    extras.getBoolean(CropExtras.KEY_SET_AS_WALLPAPER, false),
-                    extras.getBoolean(CropExtras.KEY_RETURN_DATA, false),
-                    (Uri) extras.getParcelable(MediaStore.EXTRA_OUTPUT),
-                    extras.getString(CropExtras.KEY_OUTPUT_FORMAT),
-                    extras.getBoolean(CropExtras.KEY_SHOW_WHEN_LOCKED, false),
-                    extras.getFloat(CropExtras.KEY_SPOTLIGHT_X),
-                    extras.getFloat(CropExtras.KEY_SPOTLIGHT_Y));
-        }
-        return null;
-    }
-
-    protected static CompressFormat convertExtensionToCompressFormat(String extension) {
-        return extension.equals("png") ? CompressFormat.PNG : CompressFormat.JPEG;
-    }
-
-    protected static String getFileExtension(String requestFormat) {
-        String outputFormat = (requestFormat == null)
-                ? "jpg"
-                : requestFormat;
-        outputFormat = outputFormat.toLowerCase();
-        return (outputFormat.equals("png") || outputFormat.equals("gif"))
-                ? "png" // We don't support gif compression.
-                : "jpg";
-    }
-
-    private RectF getBitmapCrop(RectF imageBounds) {
-        RectF crop = mCropView.getCrop();
-        RectF photo = mCropView.getPhoto();
-        if (crop == null || photo == null) {
-            Log.w(LOGTAG, "could not get crop");
-            return null;
-        }
-        RectF scaledCrop = CropMath.getScaledCropBounds(crop, photo, imageBounds);
-        return scaledCrop;
-    }
-}
diff --git a/src/com/android/gallery3d/filtershow/crop/CropDrawingUtils.java b/src/com/android/gallery3d/filtershow/crop/CropDrawingUtils.java
deleted file mode 100644
index b0d324c..0000000
--- a/src/com/android/gallery3d/filtershow/crop/CropDrawingUtils.java
+++ /dev/null
@@ -1,168 +0,0 @@
-/*
- * Copyright (C) 2013 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.gallery3d.filtershow.crop;
-
-import android.graphics.Canvas;
-import android.graphics.Color;
-import android.graphics.Matrix;
-import android.graphics.Paint;
-import android.graphics.Path;
-import android.graphics.RectF;
-import android.graphics.Region;
-import android.graphics.drawable.Drawable;
-
-public abstract class CropDrawingUtils {
-
-    public static void drawRuleOfThird(Canvas canvas, RectF bounds) {
-        Paint p = new Paint();
-        p.setStyle(Paint.Style.STROKE);
-        p.setColor(Color.argb(128, 255, 255, 255));
-        p.setStrokeWidth(2);
-        float stepX = bounds.width() / 3.0f;
-        float stepY = bounds.height() / 3.0f;
-        float x = bounds.left + stepX;
-        float y = bounds.top + stepY;
-        for (int i = 0; i < 2; i++) {
-            canvas.drawLine(x, bounds.top, x, bounds.bottom, p);
-            x += stepX;
-        }
-        for (int j = 0; j < 2; j++) {
-            canvas.drawLine(bounds.left, y, bounds.right, y, p);
-            y += stepY;
-        }
-    }
-
-    public static void drawCropRect(Canvas canvas, RectF bounds) {
-        Paint p = new Paint();
-        p.setStyle(Paint.Style.STROKE);
-        p.setColor(Color.WHITE);
-        p.setStrokeWidth(3);
-        canvas.drawRect(bounds, p);
-    }
-
-    public static void drawIndicator(Canvas canvas, Drawable indicator, int indicatorSize,
-            float centerX, float centerY) {
-        int left = (int) centerX - indicatorSize / 2;
-        int top = (int) centerY - indicatorSize / 2;
-        indicator.setBounds(left, top, left + indicatorSize, top + indicatorSize);
-        indicator.draw(canvas);
-    }
-
-    public static void drawIndicators(Canvas canvas, Drawable cropIndicator, int indicatorSize,
-            RectF bounds, boolean fixedAspect, int selection) {
-        boolean notMoving = (selection == CropObject.MOVE_NONE);
-        if (fixedAspect) {
-            if ((selection == CropObject.TOP_LEFT) || notMoving) {
-                drawIndicator(canvas, cropIndicator, indicatorSize, bounds.left, bounds.top);
-            }
-            if ((selection == CropObject.TOP_RIGHT) || notMoving) {
-                drawIndicator(canvas, cropIndicator, indicatorSize, bounds.right, bounds.top);
-            }
-            if ((selection == CropObject.BOTTOM_LEFT) || notMoving) {
-                drawIndicator(canvas, cropIndicator, indicatorSize, bounds.left, bounds.bottom);
-            }
-            if ((selection == CropObject.BOTTOM_RIGHT) || notMoving) {
-                drawIndicator(canvas, cropIndicator, indicatorSize, bounds.right, bounds.bottom);
-            }
-        } else {
-            if (((selection & CropObject.MOVE_TOP) != 0) || notMoving) {
-                drawIndicator(canvas, cropIndicator, indicatorSize, bounds.centerX(), bounds.top);
-            }
-            if (((selection & CropObject.MOVE_BOTTOM) != 0) || notMoving) {
-                drawIndicator(canvas, cropIndicator, indicatorSize, bounds.centerX(), bounds.bottom);
-            }
-            if (((selection & CropObject.MOVE_LEFT) != 0) || notMoving) {
-                drawIndicator(canvas, cropIndicator, indicatorSize, bounds.left, bounds.centerY());
-            }
-            if (((selection & CropObject.MOVE_RIGHT) != 0) || notMoving) {
-                drawIndicator(canvas, cropIndicator, indicatorSize, bounds.right, bounds.centerY());
-            }
-        }
-    }
-
-    public static void drawWallpaperSelectionFrame(Canvas canvas, RectF cropBounds, float spotX,
-            float spotY, Paint p, Paint shadowPaint) {
-        float sx = cropBounds.width() * spotX;
-        float sy = cropBounds.height() * spotY;
-        float cx = cropBounds.centerX();
-        float cy = cropBounds.centerY();
-        RectF r1 = new RectF(cx - sx / 2, cy - sy / 2, cx + sx / 2, cy + sy / 2);
-        float temp = sx;
-        sx = sy;
-        sy = temp;
-        RectF r2 = new RectF(cx - sx / 2, cy - sy / 2, cx + sx / 2, cy + sy / 2);
-        canvas.save();
-        canvas.clipRect(cropBounds);
-        canvas.clipRect(r1, Region.Op.DIFFERENCE);
-        canvas.clipRect(r2, Region.Op.DIFFERENCE);
-        canvas.drawPaint(shadowPaint);
-        canvas.restore();
-        Path path = new Path();
-        path.moveTo(r1.left, r1.top);
-        path.lineTo(r1.right, r1.top);
-        path.moveTo(r1.left, r1.top);
-        path.lineTo(r1.left, r1.bottom);
-        path.moveTo(r1.left, r1.bottom);
-        path.lineTo(r1.right, r1.bottom);
-        path.moveTo(r1.right, r1.top);
-        path.lineTo(r1.right, r1.bottom);
-        path.moveTo(r2.left, r2.top);
-        path.lineTo(r2.right, r2.top);
-        path.moveTo(r2.right, r2.top);
-        path.lineTo(r2.right, r2.bottom);
-        path.moveTo(r2.left, r2.bottom);
-        path.lineTo(r2.right, r2.bottom);
-        path.moveTo(r2.left, r2.top);
-        path.lineTo(r2.left, r2.bottom);
-        canvas.drawPath(path, p);
-    }
-
-    public static void drawShadows(Canvas canvas, Paint p, RectF innerBounds, RectF outerBounds) {
-        canvas.drawRect(outerBounds.left, outerBounds.top, innerBounds.right, innerBounds.top, p);
-        canvas.drawRect(innerBounds.right, outerBounds.top, outerBounds.right, innerBounds.bottom,
-                p);
-        canvas.drawRect(innerBounds.left, innerBounds.bottom, outerBounds.right,
-                outerBounds.bottom, p);
-        canvas.drawRect(outerBounds.left, innerBounds.top, innerBounds.left, outerBounds.bottom, p);
-    }
-
-    public static Matrix getBitmapToDisplayMatrix(RectF imageBounds, RectF displayBounds) {
-        Matrix m = new Matrix();
-        CropDrawingUtils.setBitmapToDisplayMatrix(m, imageBounds, displayBounds);
-        return m;
-    }
-
-    public static boolean setBitmapToDisplayMatrix(Matrix m, RectF imageBounds,
-            RectF displayBounds) {
-        m.reset();
-        return m.setRectToRect(imageBounds, displayBounds, Matrix.ScaleToFit.CENTER);
-    }
-
-    public static boolean setImageToScreenMatrix(Matrix dst, RectF image,
-            RectF screen, int rotation) {
-        RectF rotatedImage = new RectF();
-        dst.setRotate(rotation, image.centerX(), image.centerY());
-        if (!dst.mapRect(rotatedImage, image)) {
-            return false; // fails for rotations that are not multiples of 90
-                          // degrees
-        }
-        boolean rToR = dst.setRectToRect(rotatedImage, screen, Matrix.ScaleToFit.CENTER);
-        boolean rot = dst.preRotate(rotation, image.centerX(), image.centerY());
-        return rToR && rot;
-    }
-
-}
diff --git a/src/com/android/gallery3d/filtershow/crop/CropExtras.java b/src/com/android/gallery3d/filtershow/crop/CropExtras.java
deleted file mode 100644
index 60fe9af..0000000
--- a/src/com/android/gallery3d/filtershow/crop/CropExtras.java
+++ /dev/null
@@ -1,121 +0,0 @@
-/*
- * 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.gallery3d.filtershow.crop;
-
-import android.net.Uri;
-
-public class CropExtras {
-
-    public static final String KEY_CROPPED_RECT = "cropped-rect";
-    public static final String KEY_OUTPUT_X = "outputX";
-    public static final String KEY_OUTPUT_Y = "outputY";
-    public static final String KEY_SCALE = "scale";
-    public static final String KEY_SCALE_UP_IF_NEEDED = "scaleUpIfNeeded";
-    public static final String KEY_ASPECT_X = "aspectX";
-    public static final String KEY_ASPECT_Y = "aspectY";
-    public static final String KEY_SET_AS_WALLPAPER = "set-as-wallpaper";
-    public static final String KEY_RETURN_DATA = "return-data";
-    public static final String KEY_DATA = "data";
-    public static final String KEY_SPOTLIGHT_X = "spotlightX";
-    public static final String KEY_SPOTLIGHT_Y = "spotlightY";
-    public static final String KEY_SHOW_WHEN_LOCKED = "showWhenLocked";
-    public static final String KEY_OUTPUT_FORMAT = "outputFormat";
-
-    private int mOutputX = 0;
-    private int mOutputY = 0;
-    private boolean mScaleUp = true;
-    private int mAspectX = 0;
-    private int mAspectY = 0;
-    private boolean mSetAsWallpaper = false;
-    private boolean mReturnData = false;
-    private Uri mExtraOutput = null;
-    private String mOutputFormat = null;
-    private boolean mShowWhenLocked = false;
-    private float mSpotlightX = 0;
-    private float mSpotlightY = 0;
-
-    public CropExtras(int outputX, int outputY, boolean scaleUp, int aspectX, int aspectY,
-            boolean setAsWallpaper, boolean returnData, Uri extraOutput, String outputFormat,
-            boolean showWhenLocked, float spotlightX, float spotlightY) {
-        mOutputX = outputX;
-        mOutputY = outputY;
-        mScaleUp = scaleUp;
-        mAspectX = aspectX;
-        mAspectY = aspectY;
-        mSetAsWallpaper = setAsWallpaper;
-        mReturnData = returnData;
-        mExtraOutput = extraOutput;
-        mOutputFormat = outputFormat;
-        mShowWhenLocked = showWhenLocked;
-        mSpotlightX = spotlightX;
-        mSpotlightY = spotlightY;
-    }
-
-    public CropExtras(CropExtras c) {
-        this(c.mOutputX, c.mOutputY, c.mScaleUp, c.mAspectX, c.mAspectY, c.mSetAsWallpaper,
-                c.mReturnData, c.mExtraOutput, c.mOutputFormat, c.mShowWhenLocked,
-                c.mSpotlightX, c.mSpotlightY);
-    }
-
-    public int getOutputX() {
-        return mOutputX;
-    }
-
-    public int getOutputY() {
-        return mOutputY;
-    }
-
-    public boolean getScaleUp() {
-        return mScaleUp;
-    }
-
-    public int getAspectX() {
-        return mAspectX;
-    }
-
-    public int getAspectY() {
-        return mAspectY;
-    }
-
-    public boolean getSetAsWallpaper() {
-        return mSetAsWallpaper;
-    }
-
-    public boolean getReturnData() {
-        return mReturnData;
-    }
-
-    public Uri getExtraOutput() {
-        return mExtraOutput;
-    }
-
-    public String getOutputFormat() {
-        return mOutputFormat;
-    }
-
-    public boolean getShowWhenLocked() {
-        return mShowWhenLocked;
-    }
-
-    public float getSpotlightX() {
-        return mSpotlightX;
-    }
-
-    public float getSpotlightY() {
-        return mSpotlightY;
-    }
-}
diff --git a/src/com/android/gallery3d/filtershow/crop/CropMath.java b/src/com/android/gallery3d/filtershow/crop/CropMath.java
deleted file mode 100644
index 02c6531..0000000
--- a/src/com/android/gallery3d/filtershow/crop/CropMath.java
+++ /dev/null
@@ -1,260 +0,0 @@
-/*
- * 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.gallery3d.filtershow.crop;
-
-import android.graphics.Bitmap;
-import android.graphics.Matrix;
-import android.graphics.RectF;
-
-import com.android.gallery3d.filtershow.imageshow.GeometryMathUtils;
-
-import java.util.Arrays;
-
-public class CropMath {
-
-    /**
-     * Gets a float array of the 2D coordinates representing a rectangles
-     * corners.
-     * The order of the corners in the float array is:
-     * 0------->1
-     * ^        |
-     * |        v
-     * 3<-------2
-     *
-     * @param r  the rectangle to get the corners of
-     * @return  the float array of corners (8 floats)
-     */
-
-    public static float[] getCornersFromRect(RectF r) {
-        float[] corners = {
-                r.left, r.top,
-                r.right, r.top,
-                r.right, r.bottom,
-                r.left, r.bottom
-        };
-        return corners;
-    }
-
-    /**
-     * Returns true iff point (x, y) is within or on the rectangle's bounds.
-     * RectF's "contains" function treats points on the bottom and right bound
-     * as not being contained.
-     *
-     * @param r the rectangle
-     * @param x the x value of the point
-     * @param y the y value of the point
-     * @return
-     */
-    public static boolean inclusiveContains(RectF r, float x, float y) {
-        return !(x > r.right || x < r.left || y > r.bottom || y < r.top);
-    }
-
-    /**
-     * Takes an array of 2D coordinates representing corners and returns the
-     * smallest rectangle containing those coordinates.
-     *
-     * @param array array of 2D coordinates
-     * @return smallest rectangle containing coordinates
-     */
-    public static RectF trapToRect(float[] array) {
-        RectF r = new RectF(Float.POSITIVE_INFINITY, Float.POSITIVE_INFINITY,
-                Float.NEGATIVE_INFINITY, Float.NEGATIVE_INFINITY);
-        for (int i = 1; i < array.length; i += 2) {
-            float x = array[i - 1];
-            float y = array[i];
-            r.left = (x < r.left) ? x : r.left;
-            r.top = (y < r.top) ? y : r.top;
-            r.right = (x > r.right) ? x : r.right;
-            r.bottom = (y > r.bottom) ? y : r.bottom;
-        }
-        r.sort();
-        return r;
-    }
-
-    /**
-     * If edge point [x, y] in array [x0, y0, x1, y1, ...] is outside of the
-     * image bound rectangle, clamps it to the edge of the rectangle.
-     *
-     * @param imageBound the rectangle to clamp edge points to.
-     * @param array an array of points to clamp to the rectangle, gets set to
-     *            the clamped values.
-     */
-    public static void getEdgePoints(RectF imageBound, float[] array) {
-        if (array.length < 2)
-            return;
-        for (int x = 0; x < array.length; x += 2) {
-            array[x] = GeometryMathUtils.clamp(array[x], imageBound.left, imageBound.right);
-            array[x + 1] = GeometryMathUtils.clamp(array[x + 1], imageBound.top, imageBound.bottom);
-        }
-    }
-
-    /**
-     * Takes a point and the corners of a rectangle and returns the two corners
-     * representing the side of the rectangle closest to the point.
-     *
-     * @param point the point which is being checked
-     * @param corners the corners of the rectangle
-     * @return two corners representing the side of the rectangle
-     */
-    public static float[] closestSide(float[] point, float[] corners) {
-        int len = corners.length;
-        float oldMag = Float.POSITIVE_INFINITY;
-        float[] bestLine = null;
-        for (int i = 0; i < len; i += 2) {
-            float[] line = {
-                    corners[i], corners[(i + 1) % len],
-                    corners[(i + 2) % len], corners[(i + 3) % len]
-            };
-            float mag = GeometryMathUtils.vectorLength(
-                    GeometryMathUtils.shortestVectorFromPointToLine(point, line));
-            if (mag < oldMag) {
-                oldMag = mag;
-                bestLine = line;
-            }
-        }
-        return bestLine;
-    }
-
-    /**
-     * Checks if a given point is within a rotated rectangle.
-     *
-     * @param point 2D point to check
-     * @param bound rectangle to rotate
-     * @param rot angle of rotation about rectangle center
-     * @return true if point is within rotated rectangle
-     */
-    public static boolean pointInRotatedRect(float[] point, RectF bound, float rot) {
-        Matrix m = new Matrix();
-        float[] p = Arrays.copyOf(point, 2);
-        m.setRotate(rot, bound.centerX(), bound.centerY());
-        Matrix m0 = new Matrix();
-        if (!m.invert(m0))
-            return false;
-        m0.mapPoints(p);
-        return inclusiveContains(bound, p[0], p[1]);
-    }
-
-    /**
-     * Checks if a given point is within a rotated rectangle.
-     *
-     * @param point 2D point to check
-     * @param rotatedRect corners of a rotated rectangle
-     * @param center center of the rotated rectangle
-     * @return true if point is within rotated rectangle
-     */
-    public static boolean pointInRotatedRect(float[] point, float[] rotatedRect, float[] center) {
-        RectF unrotated = new RectF();
-        float angle = getUnrotated(rotatedRect, center, unrotated);
-        return pointInRotatedRect(point, unrotated, angle);
-    }
-
-    /**
-     * Resizes rectangle to have a certain aspect ratio (center remains
-     * stationary).
-     *
-     * @param r rectangle to resize
-     * @param w new width aspect
-     * @param h new height aspect
-     */
-    public static void fixAspectRatio(RectF r, float w, float h) {
-        float scale = Math.min(r.width() / w, r.height() / h);
-        float centX = r.centerX();
-        float centY = r.centerY();
-        float hw = scale * w / 2;
-        float hh = scale * h / 2;
-        r.set(centX - hw, centY - hh, centX + hw, centY + hh);
-    }
-
-    /**
-     * Resizes rectangle to have a certain aspect ratio (center remains
-     * stationary) while constraining it to remain within the original rect.
-     *
-     * @param r rectangle to resize
-     * @param w new width aspect
-     * @param h new height aspect
-     */
-    public static void fixAspectRatioContained(RectF r, float w, float h) {
-        float origW = r.width();
-        float origH = r.height();
-        float origA = origW / origH;
-        float a = w / h;
-        float finalW = origW;
-        float finalH = origH;
-        if (origA < a) {
-            finalH = origW / a;
-            r.top = r.centerY() - finalH / 2;
-            r.bottom = r.top + finalH;
-        } else {
-            finalW = origH * a;
-            r.left = r.centerX() - finalW / 2;
-            r.right = r.left + finalW;
-        }
-    }
-
-    /**
-     * Stretches/Scales/Translates photoBounds to match displayBounds, and
-     * and returns an equivalent stretched/scaled/translated cropBounds or null
-     * if the mapping is invalid.
-     * @param cropBounds  cropBounds to transform
-     * @param photoBounds  original bounds containing crop bounds
-     * @param displayBounds  final bounds for crop
-     * @return  the stretched/scaled/translated crop bounds that fit within displayBounds
-     */
-    public static RectF getScaledCropBounds(RectF cropBounds, RectF photoBounds,
-            RectF displayBounds) {
-        Matrix m = new Matrix();
-        m.setRectToRect(photoBounds, displayBounds, Matrix.ScaleToFit.FILL);
-        RectF trueCrop = new RectF(cropBounds);
-        if (!m.mapRect(trueCrop)) {
-            return null;
-        }
-        return trueCrop;
-    }
-
-    /**
-     * Returns the size of a bitmap in bytes.
-     * @param bmap  bitmap whose size to check
-     * @return  bitmap size in bytes
-     */
-    public static int getBitmapSize(Bitmap bmap) {
-        return bmap.getRowBytes() * bmap.getHeight();
-    }
-
-    /**
-     * Constrains rotation to be in [0, 90, 180, 270] rounding down.
-     * @param rotation  any rotation value, in degrees
-     * @return  integer rotation in [0, 90, 180, 270]
-     */
-    public static int constrainedRotation(float rotation) {
-        int r = (int) ((rotation % 360) / 90);
-        r = (r < 0) ? (r + 4) : r;
-        return r * 90;
-    }
-
-    private static float getUnrotated(float[] rotatedRect, float[] center, RectF unrotated) {
-        float dy = rotatedRect[1] - rotatedRect[3];
-        float dx = rotatedRect[0] - rotatedRect[2];
-        float angle = (float) (Math.atan(dy / dx) * 180 / Math.PI);
-        Matrix m = new Matrix();
-        m.setRotate(-angle, center[0], center[1]);
-        float[] unrotatedRect = new float[rotatedRect.length];
-        m.mapPoints(unrotatedRect, rotatedRect);
-        unrotated.set(trapToRect(unrotatedRect));
-        return angle;
-    }
-
-}
diff --git a/src/com/android/gallery3d/filtershow/crop/CropObject.java b/src/com/android/gallery3d/filtershow/crop/CropObject.java
deleted file mode 100644
index b98ed1b..0000000
--- a/src/com/android/gallery3d/filtershow/crop/CropObject.java
+++ /dev/null
@@ -1,330 +0,0 @@
-/*
- * Copyright (C) 2013 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.gallery3d.filtershow.crop;
-
-import android.graphics.Rect;
-import android.graphics.RectF;
-
-import com.android.gallery3d.filtershow.imageshow.GeometryMathUtils;
-
-public class CropObject {
-    private BoundedRect mBoundedRect;
-    private float mAspectWidth = 1;
-    private float mAspectHeight = 1;
-    private boolean mFixAspectRatio = false;
-    private float mRotation = 0;
-    private float mTouchTolerance = 45;
-    private float mMinSideSize = 20;
-
-    public static final int MOVE_NONE = 0;
-    // Sides
-    public static final int MOVE_LEFT = 1;
-    public static final int MOVE_TOP = 2;
-    public static final int MOVE_RIGHT = 4;
-    public static final int MOVE_BOTTOM = 8;
-    public static final int MOVE_BLOCK = 16;
-
-    // Corners
-    public static final int TOP_LEFT = MOVE_TOP | MOVE_LEFT;
-    public static final int TOP_RIGHT = MOVE_TOP | MOVE_RIGHT;
-    public static final int BOTTOM_RIGHT = MOVE_BOTTOM | MOVE_RIGHT;
-    public static final int BOTTOM_LEFT = MOVE_BOTTOM | MOVE_LEFT;
-
-    private int mMovingEdges = MOVE_NONE;
-
-    public CropObject(Rect outerBound, Rect innerBound, int outerAngle) {
-        mBoundedRect = new BoundedRect(outerAngle % 360, outerBound, innerBound);
-    }
-
-    public CropObject(RectF outerBound, RectF innerBound, int outerAngle) {
-        mBoundedRect = new BoundedRect(outerAngle % 360, outerBound, innerBound);
-    }
-
-    public void resetBoundsTo(RectF inner, RectF outer) {
-        mBoundedRect.resetTo(0, outer, inner);
-    }
-
-    public void getInnerBounds(RectF r) {
-        mBoundedRect.setToInner(r);
-    }
-
-    public void getOuterBounds(RectF r) {
-        mBoundedRect.setToOuter(r);
-    }
-
-    public RectF getInnerBounds() {
-        return mBoundedRect.getInner();
-    }
-
-    public RectF getOuterBounds() {
-        return mBoundedRect.getOuter();
-    }
-
-    public int getSelectState() {
-        return mMovingEdges;
-    }
-
-    public boolean isFixedAspect() {
-        return mFixAspectRatio;
-    }
-
-    public void rotateOuter(int angle) {
-        mRotation = angle % 360;
-        mBoundedRect.setRotation(mRotation);
-        clearSelectState();
-    }
-
-    public boolean setInnerAspectRatio(float width, float height) {
-        if (width <= 0 || height <= 0) {
-            throw new IllegalArgumentException("Width and Height must be greater than zero");
-        }
-        RectF inner = mBoundedRect.getInner();
-        CropMath.fixAspectRatioContained(inner, width, height);
-        if (inner.width() < mMinSideSize || inner.height() < mMinSideSize) {
-            return false;
-        }
-        mAspectWidth = width;
-        mAspectHeight = height;
-        mFixAspectRatio = true;
-        mBoundedRect.setInner(inner);
-        clearSelectState();
-        return true;
-    }
-
-    public void setTouchTolerance(float tolerance) {
-        if (tolerance <= 0) {
-            throw new IllegalArgumentException("Tolerance must be greater than zero");
-        }
-        mTouchTolerance = tolerance;
-    }
-
-    public void setMinInnerSideSize(float minSide) {
-        if (minSide <= 0) {
-            throw new IllegalArgumentException("Min dide must be greater than zero");
-        }
-        mMinSideSize = minSide;
-    }
-
-    public void unsetAspectRatio() {
-        mFixAspectRatio = false;
-        clearSelectState();
-    }
-
-    public boolean hasSelectedEdge() {
-        return mMovingEdges != MOVE_NONE;
-    }
-
-    public static boolean checkCorner(int selected) {
-        return selected == TOP_LEFT || selected == TOP_RIGHT || selected == BOTTOM_RIGHT
-                || selected == BOTTOM_LEFT;
-    }
-
-    public static boolean checkEdge(int selected) {
-        return selected == MOVE_LEFT || selected == MOVE_TOP || selected == MOVE_RIGHT
-                || selected == MOVE_BOTTOM;
-    }
-
-    public static boolean checkBlock(int selected) {
-        return selected == MOVE_BLOCK;
-    }
-
-    public static boolean checkValid(int selected) {
-        return selected == MOVE_NONE || checkBlock(selected) || checkEdge(selected)
-                || checkCorner(selected);
-    }
-
-    public void clearSelectState() {
-        mMovingEdges = MOVE_NONE;
-    }
-
-    public int wouldSelectEdge(float x, float y) {
-        int edgeSelected = calculateSelectedEdge(x, y);
-        if (edgeSelected != MOVE_NONE && edgeSelected != MOVE_BLOCK) {
-            return edgeSelected;
-        }
-        return MOVE_NONE;
-    }
-
-    public boolean selectEdge(int edge) {
-        if (!checkValid(edge)) {
-            // temporary
-            throw new IllegalArgumentException("bad edge selected");
-            // return false;
-        }
-        if ((mFixAspectRatio && !checkCorner(edge)) && !checkBlock(edge) && edge != MOVE_NONE) {
-            // temporary
-            throw new IllegalArgumentException("bad corner selected");
-            // return false;
-        }
-        mMovingEdges = edge;
-        return true;
-    }
-
-    public boolean selectEdge(float x, float y) {
-        int edgeSelected = calculateSelectedEdge(x, y);
-        if (mFixAspectRatio) {
-            edgeSelected = fixEdgeToCorner(edgeSelected);
-        }
-        if (edgeSelected == MOVE_NONE) {
-            return false;
-        }
-        return selectEdge(edgeSelected);
-    }
-
-    public boolean moveCurrentSelection(float dX, float dY) {
-        if (mMovingEdges == MOVE_NONE) {
-            return false;
-        }
-        RectF crop = mBoundedRect.getInner();
-
-        float minWidthHeight = mMinSideSize;
-
-        int movingEdges = mMovingEdges;
-        if (movingEdges == MOVE_BLOCK) {
-            mBoundedRect.moveInner(dX, dY);
-            return true;
-        } else {
-            float dx = 0;
-            float dy = 0;
-
-            if ((movingEdges & MOVE_LEFT) != 0) {
-                dx = Math.min(crop.left + dX, crop.right - minWidthHeight) - crop.left;
-            }
-            if ((movingEdges & MOVE_TOP) != 0) {
-                dy = Math.min(crop.top + dY, crop.bottom - minWidthHeight) - crop.top;
-            }
-            if ((movingEdges & MOVE_RIGHT) != 0) {
-                dx = Math.max(crop.right + dX, crop.left + minWidthHeight)
-                        - crop.right;
-            }
-            if ((movingEdges & MOVE_BOTTOM) != 0) {
-                dy = Math.max(crop.bottom + dY, crop.top + minWidthHeight)
-                        - crop.bottom;
-            }
-
-            if (mFixAspectRatio) {
-                float[] l1 = {
-                        crop.left, crop.bottom
-                };
-                float[] l2 = {
-                        crop.right, crop.top
-                };
-                if (movingEdges == TOP_LEFT || movingEdges == BOTTOM_RIGHT) {
-                    l1[1] = crop.top;
-                    l2[1] = crop.bottom;
-                }
-                float[] b = {
-                        l1[0] - l2[0], l1[1] - l2[1]
-                };
-                float[] disp = {
-                        dx, dy
-                };
-                float[] bUnit = GeometryMathUtils.normalize(b);
-                float sp = GeometryMathUtils.scalarProjection(disp, bUnit);
-                dx = sp * bUnit[0];
-                dy = sp * bUnit[1];
-                RectF newCrop = fixedCornerResize(crop, movingEdges, dx, dy);
-
-                mBoundedRect.fixedAspectResizeInner(newCrop);
-            } else {
-                if ((movingEdges & MOVE_LEFT) != 0) {
-                    crop.left += dx;
-                }
-                if ((movingEdges & MOVE_TOP) != 0) {
-                    crop.top += dy;
-                }
-                if ((movingEdges & MOVE_RIGHT) != 0) {
-                    crop.right += dx;
-                }
-                if ((movingEdges & MOVE_BOTTOM) != 0) {
-                    crop.bottom += dy;
-                }
-                mBoundedRect.resizeInner(crop);
-            }
-        }
-        return true;
-    }
-
-    // Helper methods
-
-    private int calculateSelectedEdge(float x, float y) {
-        RectF cropped = mBoundedRect.getInner();
-
-        float left = Math.abs(x - cropped.left);
-        float right = Math.abs(x - cropped.right);
-        float top = Math.abs(y - cropped.top);
-        float bottom = Math.abs(y - cropped.bottom);
-
-        int edgeSelected = MOVE_NONE;
-        // Check left or right.
-        if ((left <= mTouchTolerance) && ((y + mTouchTolerance) >= cropped.top)
-                && ((y - mTouchTolerance) <= cropped.bottom) && (left < right)) {
-            edgeSelected |= MOVE_LEFT;
-        }
-        else if ((right <= mTouchTolerance) && ((y + mTouchTolerance) >= cropped.top)
-                && ((y - mTouchTolerance) <= cropped.bottom)) {
-            edgeSelected |= MOVE_RIGHT;
-        }
-
-        // Check top or bottom.
-        if ((top <= mTouchTolerance) && ((x + mTouchTolerance) >= cropped.left)
-                && ((x - mTouchTolerance) <= cropped.right) && (top < bottom)) {
-            edgeSelected |= MOVE_TOP;
-        }
-        else if ((bottom <= mTouchTolerance) && ((x + mTouchTolerance) >= cropped.left)
-                && ((x - mTouchTolerance) <= cropped.right)) {
-            edgeSelected |= MOVE_BOTTOM;
-        }
-        return edgeSelected;
-    }
-
-    private static RectF fixedCornerResize(RectF r, int moving_corner, float dx, float dy) {
-        RectF newCrop = null;
-        // Fix opposite corner in place and move sides
-        if (moving_corner == BOTTOM_RIGHT) {
-            newCrop = new RectF(r.left, r.top, r.left + r.width() + dx, r.top + r.height()
-                    + dy);
-        } else if (moving_corner == BOTTOM_LEFT) {
-            newCrop = new RectF(r.right - r.width() + dx, r.top, r.right, r.top + r.height()
-                    + dy);
-        } else if (moving_corner == TOP_LEFT) {
-            newCrop = new RectF(r.right - r.width() + dx, r.bottom - r.height() + dy,
-                    r.right, r.bottom);
-        } else if (moving_corner == TOP_RIGHT) {
-            newCrop = new RectF(r.left, r.bottom - r.height() + dy, r.left
-                    + r.width() + dx, r.bottom);
-        }
-        return newCrop;
-    }
-
-    private static int fixEdgeToCorner(int moving_edges) {
-        if (moving_edges == MOVE_LEFT) {
-            moving_edges |= MOVE_TOP;
-        }
-        if (moving_edges == MOVE_TOP) {
-            moving_edges |= MOVE_LEFT;
-        }
-        if (moving_edges == MOVE_RIGHT) {
-            moving_edges |= MOVE_BOTTOM;
-        }
-        if (moving_edges == MOVE_BOTTOM) {
-            moving_edges |= MOVE_RIGHT;
-        }
-        return moving_edges;
-    }
-
-}
diff --git a/src/com/android/gallery3d/filtershow/crop/CropView.java b/src/com/android/gallery3d/filtershow/crop/CropView.java
deleted file mode 100644
index bbb7cfd..0000000
--- a/src/com/android/gallery3d/filtershow/crop/CropView.java
+++ /dev/null
@@ -1,378 +0,0 @@
-/*
- * Copyright (C) 2013 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.gallery3d.filtershow.crop;
-
-import android.content.Context;
-import android.content.res.Resources;
-import android.graphics.Bitmap;
-import android.graphics.Canvas;
-import android.graphics.DashPathEffect;
-import android.graphics.Matrix;
-import android.graphics.Paint;
-import android.graphics.Rect;
-import android.graphics.RectF;
-import android.graphics.drawable.Drawable;
-import android.graphics.drawable.NinePatchDrawable;
-import android.util.AttributeSet;
-import android.util.Log;
-import android.view.MotionEvent;
-import android.view.View;
-
-import com.android.gallery3d.R;
-
-
-public class CropView extends View {
-    private static final String LOGTAG = "CropView";
-
-    private RectF mImageBounds = new RectF();
-    private RectF mScreenBounds = new RectF();
-    private RectF mScreenImageBounds = new RectF();
-    private RectF mScreenCropBounds = new RectF();
-    private Rect mShadowBounds = new Rect();
-
-    private Bitmap mBitmap;
-    private Paint mPaint = new Paint();
-
-    private NinePatchDrawable mShadow;
-    private CropObject mCropObj = null;
-    private Drawable mCropIndicator;
-    private int mIndicatorSize;
-    private int mRotation = 0;
-    private boolean mMovingBlock = false;
-    private Matrix mDisplayMatrix = null;
-    private Matrix mDisplayMatrixInverse = null;
-    private boolean mDirty = false;
-
-    private float mPrevX = 0;
-    private float mPrevY = 0;
-    private float mSpotX = 0;
-    private float mSpotY = 0;
-    private boolean mDoSpot = false;
-
-    private int mShadowMargin = 15;
-    private int mMargin = 32;
-    private int mOverlayShadowColor = 0xCF000000;
-    private int mOverlayWPShadowColor = 0x5F000000;
-    private int mWPMarkerColor = 0x7FFFFFFF;
-    private int mMinSideSize = 90;
-    private int mTouchTolerance = 40;
-    private float mDashOnLength = 20;
-    private float mDashOffLength = 10;
-
-    private enum Mode {
-        NONE, MOVE
-    }
-
-    private Mode mState = Mode.NONE;
-
-    public CropView(Context context) {
-        super(context);
-        setup(context);
-    }
-
-    public CropView(Context context, AttributeSet attrs) {
-        super(context, attrs);
-        setup(context);
-    }
-
-    public CropView(Context context, AttributeSet attrs, int defStyle) {
-        super(context, attrs, defStyle);
-        setup(context);
-    }
-
-    private void setup(Context context) {
-        Resources rsc = context.getResources();
-        mShadow = (NinePatchDrawable) rsc.getDrawable(R.drawable.geometry_shadow);
-        mCropIndicator = rsc.getDrawable(R.drawable.camera_crop);
-        mIndicatorSize = (int) rsc.getDimension(R.dimen.crop_indicator_size);
-        mShadowMargin = (int) rsc.getDimension(R.dimen.shadow_margin);
-        mMargin = (int) rsc.getDimension(R.dimen.preview_margin);
-        mMinSideSize = (int) rsc.getDimension(R.dimen.crop_min_side);
-        mTouchTolerance = (int) rsc.getDimension(R.dimen.crop_touch_tolerance);
-        mOverlayShadowColor = (int) rsc.getColor(R.color.crop_shadow_color);
-        mOverlayWPShadowColor = (int) rsc.getColor(R.color.crop_shadow_wp_color);
-        mWPMarkerColor = (int) rsc.getColor(R.color.crop_wp_markers);
-        mDashOnLength = rsc.getDimension(R.dimen.wp_selector_dash_length);
-        mDashOffLength = rsc.getDimension(R.dimen.wp_selector_off_length);
-    }
-
-    public void initialize(Bitmap image, RectF newCropBounds, RectF newPhotoBounds, int rotation) {
-        mBitmap = image;
-        if (mCropObj != null) {
-            RectF crop = mCropObj.getInnerBounds();
-            RectF containing = mCropObj.getOuterBounds();
-            if (crop != newCropBounds || containing != newPhotoBounds
-                    || mRotation != rotation) {
-                mRotation = rotation;
-                mCropObj.resetBoundsTo(newCropBounds, newPhotoBounds);
-                clearDisplay();
-            }
-        } else {
-            mRotation = rotation;
-            mCropObj = new CropObject(newPhotoBounds, newCropBounds, 0);
-            clearDisplay();
-        }
-    }
-
-    public RectF getCrop() {
-        return mCropObj.getInnerBounds();
-    }
-
-    public RectF getPhoto() {
-        return mCropObj.getOuterBounds();
-    }
-
-    @Override
-    public boolean onTouchEvent(MotionEvent event) {
-        float x = event.getX();
-        float y = event.getY();
-        if (mDisplayMatrix == null || mDisplayMatrixInverse == null) {
-            return true;
-        }
-        float[] touchPoint = {
-                x, y
-        };
-        mDisplayMatrixInverse.mapPoints(touchPoint);
-        x = touchPoint[0];
-        y = touchPoint[1];
-        switch (event.getActionMasked()) {
-            case (MotionEvent.ACTION_DOWN):
-                if (mState == Mode.NONE) {
-                    if (!mCropObj.selectEdge(x, y)) {
-                        mMovingBlock = mCropObj.selectEdge(CropObject.MOVE_BLOCK);
-                    }
-                    mPrevX = x;
-                    mPrevY = y;
-                    mState = Mode.MOVE;
-                }
-                break;
-            case (MotionEvent.ACTION_UP):
-                if (mState == Mode.MOVE) {
-                    mCropObj.selectEdge(CropObject.MOVE_NONE);
-                    mMovingBlock = false;
-                    mPrevX = x;
-                    mPrevY = y;
-                    mState = Mode.NONE;
-                }
-                break;
-            case (MotionEvent.ACTION_MOVE):
-                if (mState == Mode.MOVE) {
-                    float dx = x - mPrevX;
-                    float dy = y - mPrevY;
-                    mCropObj.moveCurrentSelection(dx, dy);
-                    mPrevX = x;
-                    mPrevY = y;
-                }
-                break;
-            default:
-                break;
-        }
-        invalidate();
-        return true;
-    }
-
-    private void reset() {
-        Log.w(LOGTAG, "crop reset called");
-        mState = Mode.NONE;
-        mCropObj = null;
-        mRotation = 0;
-        mMovingBlock = false;
-        clearDisplay();
-    }
-
-    private void clearDisplay() {
-        mDisplayMatrix = null;
-        mDisplayMatrixInverse = null;
-        invalidate();
-    }
-
-    protected void configChanged() {
-        mDirty = true;
-    }
-
-    public void applyFreeAspect() {
-        mCropObj.unsetAspectRatio();
-        invalidate();
-    }
-
-    public void applyOriginalAspect() {
-        RectF outer = mCropObj.getOuterBounds();
-        float w = outer.width();
-        float h = outer.height();
-        if (w > 0 && h > 0) {
-            applyAspect(w, h);
-            mCropObj.resetBoundsTo(outer, outer);
-        } else {
-            Log.w(LOGTAG, "failed to set aspect ratio original");
-        }
-    }
-
-    public void applySquareAspect() {
-        applyAspect(1, 1);
-    }
-
-    public void applyAspect(float x, float y) {
-        if (x <= 0 || y <= 0) {
-            throw new IllegalArgumentException("Bad arguments to applyAspect");
-        }
-        // If we are rotated by 90 degrees from horizontal, swap x and y
-        if (((mRotation < 0) ? -mRotation : mRotation) % 180 == 90) {
-            float tmp = x;
-            x = y;
-            y = tmp;
-        }
-        if (!mCropObj.setInnerAspectRatio(x, y)) {
-            Log.w(LOGTAG, "failed to set aspect ratio");
-        }
-        invalidate();
-    }
-
-    public void setWallpaperSpotlight(float spotlightX, float spotlightY) {
-        mSpotX = spotlightX;
-        mSpotY = spotlightY;
-        if (mSpotX > 0 && mSpotY > 0) {
-            mDoSpot = true;
-        }
-    }
-
-    public void unsetWallpaperSpotlight() {
-        mDoSpot = false;
-    }
-
-    /**
-     * Rotates first d bits in integer x to the left some number of times.
-     */
-    private int bitCycleLeft(int x, int times, int d) {
-        int mask = (1 << d) - 1;
-        int mout = x & mask;
-        times %= d;
-        int hi = mout >> (d - times);
-        int low = (mout << times) & mask;
-        int ret = x & ~mask;
-        ret |= low;
-        ret |= hi;
-        return ret;
-    }
-
-    /**
-     * Find the selected edge or corner in screen coordinates.
-     */
-    private int decode(int movingEdges, float rotation) {
-        int rot = CropMath.constrainedRotation(rotation);
-        switch (rot) {
-            case 90:
-                return bitCycleLeft(movingEdges, 1, 4);
-            case 180:
-                return bitCycleLeft(movingEdges, 2, 4);
-            case 270:
-                return bitCycleLeft(movingEdges, 3, 4);
-            default:
-                return movingEdges;
-        }
-    }
-
-    @Override
-    public void onDraw(Canvas canvas) {
-        if (mBitmap == null) {
-            return;
-        }
-        if (mDirty) {
-            mDirty = false;
-            clearDisplay();
-        }
-
-        mImageBounds = new RectF(0, 0, mBitmap.getWidth(), mBitmap.getHeight());
-        mScreenBounds = new RectF(0, 0, canvas.getWidth(), canvas.getHeight());
-        mScreenBounds.inset(mMargin, mMargin);
-
-        // If crop object doesn't exist, create it and update it from master
-        // state
-        if (mCropObj == null) {
-            reset();
-            mCropObj = new CropObject(mImageBounds, mImageBounds, 0);
-        }
-
-        // If display matrix doesn't exist, create it and its dependencies
-        if (mDisplayMatrix == null || mDisplayMatrixInverse == null) {
-            mDisplayMatrix = new Matrix();
-            mDisplayMatrix.reset();
-            if (!CropDrawingUtils.setImageToScreenMatrix(mDisplayMatrix, mImageBounds, mScreenBounds,
-                    mRotation)) {
-                Log.w(LOGTAG, "failed to get screen matrix");
-                mDisplayMatrix = null;
-                return;
-            }
-            mDisplayMatrixInverse = new Matrix();
-            mDisplayMatrixInverse.reset();
-            if (!mDisplayMatrix.invert(mDisplayMatrixInverse)) {
-                Log.w(LOGTAG, "could not invert display matrix");
-                mDisplayMatrixInverse = null;
-                return;
-            }
-            // Scale min side and tolerance by display matrix scale factor
-            mCropObj.setMinInnerSideSize(mDisplayMatrixInverse.mapRadius(mMinSideSize));
-            mCropObj.setTouchTolerance(mDisplayMatrixInverse.mapRadius(mTouchTolerance));
-        }
-
-        mScreenImageBounds.set(mImageBounds);
-
-        // Draw background shadow
-        if (mDisplayMatrix.mapRect(mScreenImageBounds)) {
-            int margin = (int) mDisplayMatrix.mapRadius(mShadowMargin);
-            mScreenImageBounds.roundOut(mShadowBounds);
-            mShadowBounds.set(mShadowBounds.left - margin, mShadowBounds.top -
-                    margin, mShadowBounds.right + margin, mShadowBounds.bottom + margin);
-            mShadow.setBounds(mShadowBounds);
-            mShadow.draw(canvas);
-        }
-
-        mPaint.setAntiAlias(true);
-        mPaint.setFilterBitmap(true);
-        // Draw actual bitmap
-        canvas.drawBitmap(mBitmap, mDisplayMatrix, mPaint);
-
-        mCropObj.getInnerBounds(mScreenCropBounds);
-
-        if (mDisplayMatrix.mapRect(mScreenCropBounds)) {
-
-            // Draw overlay shadows
-            Paint p = new Paint();
-            p.setColor(mOverlayShadowColor);
-            p.setStyle(Paint.Style.FILL);
-            CropDrawingUtils.drawShadows(canvas, p, mScreenCropBounds, mScreenImageBounds);
-
-            // Draw crop rect and markers
-            CropDrawingUtils.drawCropRect(canvas, mScreenCropBounds);
-            if (!mDoSpot) {
-                CropDrawingUtils.drawRuleOfThird(canvas, mScreenCropBounds);
-            } else {
-                Paint wpPaint = new Paint();
-                wpPaint.setColor(mWPMarkerColor);
-                wpPaint.setStrokeWidth(3);
-                wpPaint.setStyle(Paint.Style.STROKE);
-                wpPaint.setPathEffect(new DashPathEffect(new float[]
-                        {mDashOnLength, mDashOnLength + mDashOffLength}, 0));
-                p.setColor(mOverlayWPShadowColor);
-                CropDrawingUtils.drawWallpaperSelectionFrame(canvas, mScreenCropBounds,
-                        mSpotX, mSpotY, wpPaint, p);
-            }
-            CropDrawingUtils.drawIndicators(canvas, mCropIndicator, mIndicatorSize,
-                    mScreenCropBounds, mCropObj.isFixedAspect(), decode(mCropObj.getSelectState(), mRotation));
-        }
-
-    }
-}
diff --git a/src/com/android/gallery3d/filtershow/data/FilterStackDBHelper.java b/src/com/android/gallery3d/filtershow/data/FilterStackDBHelper.java
deleted file mode 100644
index e18d310..0000000
--- a/src/com/android/gallery3d/filtershow/data/FilterStackDBHelper.java
+++ /dev/null
@@ -1,101 +0,0 @@
-/*
- * Copyright (C) 2013 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.gallery3d.filtershow.data;
-
-import android.content.Context;
-import android.database.sqlite.SQLiteDatabase;
-import android.database.sqlite.SQLiteOpenHelper;
-
-public class FilterStackDBHelper extends SQLiteOpenHelper {
-
-    public static final int DATABASE_VERSION = 1;
-    public static final String DATABASE_NAME = "filterstacks.db";
-    private static final String SQL_CREATE_TABLE = "CREATE TABLE ";
-
-    public static interface FilterStack {
-        /** The row uid */
-        public static final String _ID = "_id";
-        /** The table name */
-        public static final String TABLE = "filterstack";
-        /** The stack name */
-        public static final String STACK_ID = "stack_id";
-        /** A serialized stack of filters. */
-        public static final String FILTER_STACK= "stack";
-    }
-
-    private static final String[][] CREATE_FILTER_STACK = {
-            { FilterStack._ID, "INTEGER PRIMARY KEY AUTOINCREMENT" },
-            { FilterStack.STACK_ID, "TEXT" },
-            { FilterStack.FILTER_STACK, "BLOB" },
-    };
-
-    public FilterStackDBHelper(Context context, String name, int version) {
-        super(context, name, null, version);
-    }
-
-    public FilterStackDBHelper(Context context, String name) {
-        this(context, name, DATABASE_VERSION);
-    }
-
-    public FilterStackDBHelper(Context context) {
-        this(context, DATABASE_NAME);
-    }
-
-    @Override
-    public void onCreate(SQLiteDatabase db) {
-        createTable(db, FilterStack.TABLE, CREATE_FILTER_STACK);
-    }
-
-    @Override
-    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
-        dropTable(db, FilterStack.TABLE);
-        onCreate(db);
-    }
-
-    protected static void createTable(SQLiteDatabase db, String table, String[][] columns) {
-        StringBuilder create = new StringBuilder(SQL_CREATE_TABLE);
-        create.append(table).append('(');
-        boolean first = true;
-        for (String[] column : columns) {
-            if (!first) {
-                create.append(',');
-            }
-            first = false;
-            for (String val : column) {
-                create.append(val).append(' ');
-            }
-        }
-        create.append(')');
-        db.beginTransaction();
-        try {
-            db.execSQL(create.toString());
-            db.setTransactionSuccessful();
-        } finally {
-            db.endTransaction();
-        }
-    }
-
-    protected static void dropTable(SQLiteDatabase db, String table) {
-        db.beginTransaction();
-        try {
-            db.execSQL("drop table if exists " + table);
-            db.setTransactionSuccessful();
-        } finally {
-            db.endTransaction();
-        }
-    }
-}
diff --git a/src/com/android/gallery3d/filtershow/data/FilterStackSource.java b/src/com/android/gallery3d/filtershow/data/FilterStackSource.java
deleted file mode 100644
index d283771..0000000
--- a/src/com/android/gallery3d/filtershow/data/FilterStackSource.java
+++ /dev/null
@@ -1,197 +0,0 @@
-/*
- * Copyright (C) 2013 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.gallery3d.filtershow.data;
-
-import android.content.ContentValues;
-import android.content.Context;
-import android.database.Cursor;
-import android.database.sqlite.SQLiteDatabase;
-import android.database.sqlite.SQLiteException;
-import android.util.Log;
-import android.util.Pair;
-
-import com.android.gallery3d.filtershow.data.FilterStackDBHelper.FilterStack;
-import com.android.gallery3d.filtershow.filters.FilterUserPresetRepresentation;
-import com.android.gallery3d.filtershow.pipeline.ImagePreset;
-
-import java.util.ArrayList;
-import java.util.List;
-
-public class FilterStackSource {
-    private static final String LOGTAG = "FilterStackSource";
-
-    private SQLiteDatabase database = null;
-    private final FilterStackDBHelper dbHelper;
-
-    public FilterStackSource(Context context) {
-        dbHelper = new FilterStackDBHelper(context);
-    }
-
-    public void open() {
-        try {
-            database = dbHelper.getWritableDatabase();
-        } catch (SQLiteException e) {
-            Log.w(LOGTAG, "could not open database", e);
-        }
-    }
-
-    public void close() {
-        database = null;
-        dbHelper.close();
-    }
-
-    public boolean insertStack(String stackName, byte[] stackBlob) {
-        boolean ret = true;
-        ContentValues val = new ContentValues();
-        val.put(FilterStack.STACK_ID, stackName);
-        val.put(FilterStack.FILTER_STACK, stackBlob);
-        database.beginTransaction();
-        try {
-            ret = (-1 != database.insert(FilterStack.TABLE, null, val));
-            database.setTransactionSuccessful();
-        } finally {
-            database.endTransaction();
-        }
-        return ret;
-    }
-
-    public void updateStackName(int id, String stackName) {
-        ContentValues val = new ContentValues();
-        val.put(FilterStack.STACK_ID, stackName);
-        database.beginTransaction();
-        try {
-            database.update(FilterStack.TABLE, val, FilterStack._ID + " = ?",
-                    new String[] { "" + id});
-            database.setTransactionSuccessful();
-        } finally {
-            database.endTransaction();
-        }
-    }
-
-    public boolean removeStack(int id) {
-        boolean ret = true;
-        database.beginTransaction();
-        try {
-            ret = (0 != database.delete(FilterStack.TABLE, FilterStack._ID + " = ?",
-                    new String[] { "" + id }));
-            database.setTransactionSuccessful();
-        } finally {
-            database.endTransaction();
-        }
-        return ret;
-    }
-
-    public void removeAllStacks() {
-        database.beginTransaction();
-        try {
-            database.delete(FilterStack.TABLE, null, null);
-            database.setTransactionSuccessful();
-        } finally {
-            database.endTransaction();
-        }
-    }
-
-    public byte[] getStack(String stackName) {
-        byte[] ret = null;
-        Cursor c = null;
-        database.beginTransaction();
-        try {
-            c = database.query(FilterStack.TABLE,
-                    new String[] { FilterStack.FILTER_STACK },
-                    FilterStack.STACK_ID + " = ?",
-                    new String[] { stackName }, null, null, null, null);
-            if (c != null && c.moveToFirst() && !c.isNull(0)) {
-                ret = c.getBlob(0);
-            }
-            database.setTransactionSuccessful();
-        } finally {
-            if (c != null) {
-                c.close();
-            }
-            database.endTransaction();
-        }
-        return ret;
-    }
-
-    public ArrayList<FilterUserPresetRepresentation> getAllUserPresets() {
-        ArrayList<FilterUserPresetRepresentation> ret =
-                new ArrayList<FilterUserPresetRepresentation>();
-
-        Cursor c = null;
-        database.beginTransaction();
-        try {
-            c = database.query(FilterStack.TABLE,
-                    new String[] { FilterStack._ID,
-                            FilterStack.STACK_ID,
-                            FilterStack.FILTER_STACK },
-                    null, null, null, null, null, null);
-            if (c != null) {
-                boolean loopCheck = c.moveToFirst();
-                while (loopCheck) {
-                    int id = c.getInt(0);
-                    String name = (c.isNull(1)) ?  null : c.getString(1);
-                    byte[] b = (c.isNull(2)) ? null : c.getBlob(2);
-                    String json = new String(b);
-
-                    ImagePreset preset = new ImagePreset();
-                    preset.readJsonFromString(json);
-                    FilterUserPresetRepresentation representation =
-                            new FilterUserPresetRepresentation(name, preset, id);
-                    ret.add(representation);
-                    loopCheck = c.moveToNext();
-                }
-            }
-            database.setTransactionSuccessful();
-        } finally {
-            if (c != null) {
-                c.close();
-            }
-            database.endTransaction();
-        }
-
-        return ret;
-    }
-
-    public List<Pair<String, byte[]>> getAllStacks() {
-        List<Pair<String, byte[]>> ret = new ArrayList<Pair<String, byte[]>>();
-        Cursor c = null;
-        database.beginTransaction();
-        try {
-            c = database.query(FilterStack.TABLE,
-                    new String[] { FilterStack.STACK_ID, FilterStack.FILTER_STACK },
-                    null, null, null, null, null, null);
-            if (c != null) {
-                boolean loopCheck = c.moveToFirst();
-                while (loopCheck) {
-                    String name = (c.isNull(0)) ?  null : c.getString(0);
-                    byte[] b = (c.isNull(1)) ? null : c.getBlob(1);
-                    ret.add(new Pair<String, byte[]>(name, b));
-                    loopCheck = c.moveToNext();
-                }
-            }
-            database.setTransactionSuccessful();
-        } finally {
-            if (c != null) {
-                c.close();
-            }
-            database.endTransaction();
-        }
-        if (ret.size() <= 0) {
-            return null;
-        }
-        return ret;
-    }
-}
diff --git a/src/com/android/gallery3d/filtershow/data/UserPresetsManager.java b/src/com/android/gallery3d/filtershow/data/UserPresetsManager.java
deleted file mode 100644
index 114cd3e..0000000
--- a/src/com/android/gallery3d/filtershow/data/UserPresetsManager.java
+++ /dev/null
@@ -1,149 +0,0 @@
-package com.android.gallery3d.filtershow.data;
-
-import android.os.Handler;
-import android.os.HandlerThread;
-import android.os.Message;
-import com.android.gallery3d.R;
-import com.android.gallery3d.filtershow.FilterShowActivity;
-import com.android.gallery3d.filtershow.filters.FilterUserPresetRepresentation;
-import com.android.gallery3d.filtershow.pipeline.ImagePreset;
-
-import java.util.ArrayList;
-
-public class UserPresetsManager implements Handler.Callback {
-
-    private static final String LOGTAG = "UserPresetsManager";
-
-    private FilterShowActivity mActivity;
-    private HandlerThread mHandlerThread = null;
-    private Handler mProcessingHandler = null;
-    private FilterStackSource mUserPresets;
-
-    private static final int LOAD = 1;
-    private static final int LOAD_RESULT = 2;
-    private static final int SAVE = 3;
-    private static final int DELETE = 4;
-    private static final int UPDATE = 5;
-
-    private ArrayList<FilterUserPresetRepresentation> mRepresentations;
-
-    private final Handler mResultHandler = new Handler() {
-        @Override
-        public void handleMessage(Message msg) {
-            switch (msg.what) {
-                case LOAD_RESULT:
-                    resultLoad(msg);
-                    break;
-            }
-        }
-    };
-
-    @Override
-    public boolean handleMessage(Message msg) {
-        switch (msg.what) {
-            case LOAD:
-                processLoad();
-                return true;
-            case SAVE:
-                processSave(msg);
-                return true;
-            case DELETE:
-                processDelete(msg);
-                return true;
-            case UPDATE:
-                processUpdate(msg);
-                return true;
-        }
-        return false;
-    }
-
-    public UserPresetsManager(FilterShowActivity context) {
-        mActivity = context;
-        mHandlerThread = new HandlerThread(LOGTAG,
-                android.os.Process.THREAD_PRIORITY_BACKGROUND);
-        mHandlerThread.start();
-        mProcessingHandler = new Handler(mHandlerThread.getLooper(), this);
-        mUserPresets = new FilterStackSource(mActivity);
-        mUserPresets.open();
-    }
-
-    public ArrayList<FilterUserPresetRepresentation> getRepresentations() {
-        return mRepresentations;
-    }
-
-    public void load() {
-        Message msg = mProcessingHandler.obtainMessage(LOAD);
-        mProcessingHandler.sendMessage(msg);
-    }
-
-    public void close() {
-        mUserPresets.close();
-        mHandlerThread.quit();
-    }
-
-    static class SaveOperation {
-        String json;
-        String name;
-    }
-
-    public void save(ImagePreset preset) {
-        Message msg = mProcessingHandler.obtainMessage(SAVE);
-        SaveOperation op = new SaveOperation();
-        op.json = preset.getJsonString(mActivity.getString(R.string.saved));
-        op.name= mActivity.getString(R.string.filtershow_new_preset);
-        msg.obj = op;
-        mProcessingHandler.sendMessage(msg);
-    }
-
-    public void delete(int id) {
-        Message msg = mProcessingHandler.obtainMessage(DELETE);
-        msg.arg1 = id;
-        mProcessingHandler.sendMessage(msg);
-    }
-
-    static class UpdateOperation {
-        int id;
-        String name;
-    }
-
-    public void update(FilterUserPresetRepresentation representation) {
-        Message msg = mProcessingHandler.obtainMessage(UPDATE);
-        UpdateOperation op = new UpdateOperation();
-        op.id = representation.getId();
-        op.name = representation.getName();
-        msg.obj = op;
-        mProcessingHandler.sendMessage(msg);
-    }
-
-    private void processLoad() {
-        ArrayList<FilterUserPresetRepresentation> list = mUserPresets.getAllUserPresets();
-        Message msg = mResultHandler.obtainMessage(LOAD_RESULT);
-        msg.obj = list;
-        mResultHandler.sendMessage(msg);
-    }
-
-    private void resultLoad(Message msg) {
-        mRepresentations =
-                (ArrayList<FilterUserPresetRepresentation>) msg.obj;
-        mActivity.updateUserPresetsFromManager();
-    }
-
-    private void processSave(Message msg) {
-        SaveOperation op = (SaveOperation) msg.obj;
-        mUserPresets.insertStack(op.name, op.json.getBytes());
-        processLoad();
-    }
-
-    private void processDelete(Message msg) {
-        int id = msg.arg1;
-        mUserPresets.removeStack(id);
-        processLoad();
-    }
-
-    private void processUpdate(Message msg) {
-        UpdateOperation op = (UpdateOperation) msg.obj;
-        mUserPresets.updateStackName(op.id, op.name);
-        processLoad();
-    }
-
-}
diff --git a/src/com/android/gallery3d/filtershow/editors/BasicEditor.java b/src/com/android/gallery3d/filtershow/editors/BasicEditor.java
deleted file mode 100644
index af694d8..0000000
--- a/src/com/android/gallery3d/filtershow/editors/BasicEditor.java
+++ /dev/null
@@ -1,138 +0,0 @@
-/*
- * Copyright (C) 2013 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.gallery3d.filtershow.editors;
-
-import android.content.Context;
-
-import com.android.gallery3d.R;
-import com.android.gallery3d.filtershow.controller.Control;
-import com.android.gallery3d.filtershow.controller.FilterView;
-import com.android.gallery3d.filtershow.controller.Parameter;
-import com.android.gallery3d.filtershow.controller.ParameterInteger;
-import com.android.gallery3d.filtershow.filters.FilterBasicRepresentation;
-import com.android.gallery3d.filtershow.filters.FilterRepresentation;
-
-
-/**
- * The basic editor that all the one parameter filters
- */
-public class BasicEditor extends ParametricEditor implements ParameterInteger {
-    public static int ID = R.id.basicEditor;
-    private final String LOGTAG = "BasicEditor";
-
-    public BasicEditor() {
-        super(ID, R.layout.filtershow_default_editor, R.id.basicEditor);
-    }
-
-    protected BasicEditor(int id) {
-        super(id, R.layout.filtershow_default_editor, R.id.basicEditor);
-    }
-
-    protected BasicEditor(int id, int layoutID, int viewID) {
-        super(id, layoutID, viewID);
-    }
-
-    @Override
-    public void reflectCurrentFilter() {
-        super.reflectCurrentFilter();
-        if (getLocalRepresentation() != null && getLocalRepresentation() instanceof FilterBasicRepresentation) {
-            FilterBasicRepresentation interval = (FilterBasicRepresentation) getLocalRepresentation();
-            updateText();
-        }
-    }
-
-    private FilterBasicRepresentation getBasicRepresentation() {
-        FilterRepresentation tmpRep = getLocalRepresentation();
-        if (tmpRep != null && tmpRep instanceof FilterBasicRepresentation) {
-            return (FilterBasicRepresentation) tmpRep;
-
-        }
-        return null;
-    }
-
-    @Override
-    public int getMaximum() {
-        FilterBasicRepresentation rep = getBasicRepresentation();
-        if (rep == null) {
-            return 0;
-        }
-        return rep.getMaximum();
-    }
-
-    @Override
-    public int getMinimum() {
-        FilterBasicRepresentation rep = getBasicRepresentation();
-        if (rep == null) {
-            return 0;
-        }
-        return rep.getMinimum();
-    }
-
-    @Override
-    public int getDefaultValue() {
-        return 0;
-    }
-
-    @Override
-    public int getValue() {
-        FilterBasicRepresentation rep = getBasicRepresentation();
-        if (rep == null) {
-            return 0;
-        }
-        return rep.getValue();
-    }
-
-    @Override
-    public String getValueString() {
-        return null;
-    }
-
-    @Override
-    public void setValue(int value) {
-        FilterBasicRepresentation rep = getBasicRepresentation();
-        if (rep == null) {
-            return;
-        }
-        rep.setValue(value);
-        commitLocalRepresentation();
-    }
-
-    @Override
-    public String getParameterName() {
-        FilterBasicRepresentation rep = getBasicRepresentation();
-        return mContext.getString(rep.getTextId());
-    }
-
-    @Override
-    public String getParameterType() {
-        return sParameterType;
-    }
-
-    @Override
-    public void setController(Control c) {
-    }
-
-    @Override
-    public void setFilterView(FilterView editor) {
-
-    }
-
-    @Override
-    public void copyFrom(Parameter src) {
-
-    }
-}
diff --git a/src/com/android/gallery3d/filtershow/editors/Editor.java b/src/com/android/gallery3d/filtershow/editors/Editor.java
deleted file mode 100644
index a9e56e0..0000000
--- a/src/com/android/gallery3d/filtershow/editors/Editor.java
+++ /dev/null
@@ -1,330 +0,0 @@
-/*
- * 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.gallery3d.filtershow.editors;
-
-import android.content.Context;
-import android.util.AttributeSet;
-import android.view.LayoutInflater;
-import android.view.Menu;
-import android.view.MenuItem;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.Button;
-import android.widget.FrameLayout;
-import android.widget.LinearLayout;
-import android.widget.PopupMenu;
-import android.widget.SeekBar;
-import android.widget.SeekBar.OnSeekBarChangeListener;
-
-import com.android.gallery3d.R;
-import com.android.gallery3d.filtershow.controller.Control;
-import com.android.gallery3d.filtershow.filters.FilterRepresentation;
-import com.android.gallery3d.filtershow.imageshow.ImageShow;
-import com.android.gallery3d.filtershow.imageshow.MasterImage;
-import com.android.gallery3d.filtershow.pipeline.ImagePreset;
-
-import java.util.ArrayList;
-import java.util.Collection;
-
-/**
- * Base class for Editors Must contain a mImageShow and a top level view
- */
-public class Editor implements OnSeekBarChangeListener, SwapButton.SwapButtonListener {
-    protected Context mContext;
-    protected View mView;
-    protected ImageShow mImageShow;
-    protected FrameLayout mFrameLayout;
-    protected SeekBar mSeekBar;
-    Button mEditTitle;
-    protected Button mFilterTitle;
-    protected int mID;
-    private final String LOGTAG = "Editor";
-    protected boolean mChangesGeometry = false;
-    protected FilterRepresentation mLocalRepresentation = null;
-    protected byte mShowParameter = SHOW_VALUE_UNDEFINED;
-    private Button mButton;
-    public static byte SHOW_VALUE_UNDEFINED = -1;
-    public static byte SHOW_VALUE_OFF = 0;
-    public static byte SHOW_VALUE_INT = 1;
-
-    public static void hackFixStrings(Menu menu) {
-        int count = menu.size();
-        for (int i = 0; i < count; i++) {
-            MenuItem item = menu.getItem(i);
-            item.setTitle(item.getTitle().toString().toUpperCase());
-        }
-    }
-
-    public String calculateUserMessage(Context context, String effectName, Object parameterValue) {
-        return effectName.toUpperCase() + " " + parameterValue;
-    }
-
-    protected Editor(int id) {
-        mID = id;
-    }
-
-    public int getID() {
-        return mID;
-    }
-
-    public byte showParameterValue() {
-        return mShowParameter;
-    }
-
-    public boolean showsSeekBar() {
-        return true;
-    }
-
-    public void setUpEditorUI(View actionButton, View editControl,
-                              Button editTitle, Button stateButton) {
-        mEditTitle = editTitle;
-        mFilterTitle = stateButton;
-        mButton = editTitle;
-        setMenuIcon(true);
-        setUtilityPanelUI(actionButton, editControl);
-    }
-
-    public boolean showsPopupIndicator() {
-        return true;
-    }
-
-    /**
-     * @param actionButton the would be the area for menu etc
-     * @param editControl this is the black area for sliders etc
-     */
-    public void setUtilityPanelUI(View actionButton, View editControl) {
-
-        AttributeSet aset;
-        Context context = editControl.getContext();
-        LayoutInflater inflater =
-                (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
-        LinearLayout lp = (LinearLayout) inflater.inflate(
-                R.layout.filtershow_seekbar, (ViewGroup) editControl, true);
-        mSeekBar = (SeekBar) lp.findViewById(R.id.primarySeekBar);
-        mSeekBar.setOnSeekBarChangeListener(this);
-
-        if (showsSeekBar()) {
-            mSeekBar.setOnSeekBarChangeListener(this);
-            mSeekBar.setVisibility(View.VISIBLE);
-        } else {
-            mSeekBar.setVisibility(View.INVISIBLE);
-        }
-
-        if (mButton != null) {
-            if (showsPopupIndicator()) {
-                mButton.setCompoundDrawablesRelativeWithIntrinsicBounds(0, 0,
-                        R.drawable.filtershow_menu_marker, 0);
-            } else {
-                mButton.setCompoundDrawablesRelativeWithIntrinsicBounds(0, 0, 0, 0);
-            }
-        }
-    }
-
-    @Override
-    public void onProgressChanged(SeekBar sbar, int progress, boolean arg2) {
-
-    }
-
-    public void setPanel() {
-
-    }
-
-    public void createEditor(Context context,FrameLayout frameLayout) {
-        mContext = context;
-        mFrameLayout = frameLayout;
-        mLocalRepresentation = null;
-    }
-
-    protected void unpack(int viewid, int layoutid) {
-
-        if (mView == null) {
-            mView = mFrameLayout.findViewById(viewid);
-            if (mView == null) {
-                LayoutInflater inflater = (LayoutInflater) mContext.getSystemService
-                        (Context.LAYOUT_INFLATER_SERVICE);
-                mView = inflater.inflate(layoutid, mFrameLayout, false);
-                mFrameLayout.addView(mView, mView.getLayoutParams());
-            }
-        }
-        mImageShow = findImageShow(mView);
-    }
-
-    private ImageShow findImageShow(View view) {
-        if (view instanceof ImageShow) {
-            return (ImageShow) view;
-        }
-        if (!(view instanceof ViewGroup)) {
-            return null;
-        }
-        ViewGroup vg = (ViewGroup) view;
-        int n = vg.getChildCount();
-        for (int i = 0; i < n; i++) {
-            View v = vg.getChildAt(i);
-            if (v instanceof ImageShow) {
-                return (ImageShow) v;
-            } else if (v instanceof ViewGroup) {
-                return findImageShow(v);
-            }
-        }
-        return null;
-    }
-
-    public View getTopLevelView() {
-        return mView;
-    }
-
-    public ImageShow getImageShow() {
-        return mImageShow;
-    }
-
-    public void setVisibility(int visible) {
-        mView.setVisibility(visible);
-    }
-
-    public FilterRepresentation getLocalRepresentation() {
-        if (mLocalRepresentation == null) {
-            ImagePreset preset = MasterImage.getImage().getPreset();
-            FilterRepresentation filterRepresentation = MasterImage.getImage().getCurrentFilterRepresentation();
-            mLocalRepresentation = preset.getFilterRepresentationCopyFrom(filterRepresentation);
-            if (mShowParameter == SHOW_VALUE_UNDEFINED && filterRepresentation != null) {
-                boolean show = filterRepresentation.showParameterValue();
-                mShowParameter = show ? SHOW_VALUE_INT : SHOW_VALUE_OFF;
-            }
-
-        }
-        return mLocalRepresentation;
-    }
-
-    /**
-     *  Call this to update the preset in MasterImage with the current representation
-     *  returned by getLocalRepresentation.  This causes the preview bitmap to be
-     *  regenerated.
-     */
-    public void commitLocalRepresentation() {
-        commitLocalRepresentation(getLocalRepresentation());
-    }
-
-    /**
-     *  Call this to update the preset in MasterImage with a given representation.
-     *  This causes the preview bitmap to be regenerated.
-     */
-    public void commitLocalRepresentation(FilterRepresentation rep) {
-        ArrayList<FilterRepresentation> filter = new ArrayList<FilterRepresentation>(1);
-        filter.add(rep);
-        commitLocalRepresentation(filter);
-    }
-
-    /**
-     *  Call this to update the preset in MasterImage with a collection of FilterRepresnations.
-     *  This causes the preview bitmap to be regenerated.
-     */
-    public void commitLocalRepresentation(Collection<FilterRepresentation> reps) {
-        ImagePreset preset = MasterImage.getImage().getPreset();
-        preset.updateFilterRepresentations(reps);
-        if (mButton != null) {
-            updateText();
-        }
-        if (mChangesGeometry) {
-            // Regenerate both the filtered and the geometry-only bitmaps
-            MasterImage.getImage().updatePresets(true);
-        } else {
-            // Regenerate only the filtered bitmap.
-            MasterImage.getImage().invalidateFiltersOnly();
-        }
-        preset.fillImageStateAdapter(MasterImage.getImage().getState());
-    }
-
-    /**
-     * This is called in response to a click to apply and leave the editor.
-     */
-    public void finalApplyCalled() {
-        commitLocalRepresentation();
-    }
-
-    protected void updateText() {
-        String s = "";
-        if (mLocalRepresentation != null) {
-            s = mContext.getString(mLocalRepresentation.getTextId());
-        }
-        mButton.setText(calculateUserMessage(mContext, s, ""));
-    }
-
-    /**
-     * called after the filter is set and the select is called
-     */
-    public void reflectCurrentFilter() {
-        mLocalRepresentation = null;
-        FilterRepresentation representation = getLocalRepresentation();
-        if (representation != null && mFilterTitle != null && representation.getTextId() != 0) {
-            String text = mContext.getString(representation.getTextId()).toUpperCase();
-            mFilterTitle.setText(text);
-            updateText();
-        }
-    }
-
-    public boolean useUtilityPanel() {
-        return true;
-    }
-
-    public void openUtilityPanel(LinearLayout mAccessoryViewList) {
-        setMenuIcon(false);
-        if (mImageShow != null) {
-            mImageShow.openUtilityPanel(mAccessoryViewList);
-        }
-    }
-
-    protected void setMenuIcon(boolean on) {
-        mEditTitle.setCompoundDrawablesRelativeWithIntrinsicBounds(
-                0, 0, on ? R.drawable.filtershow_menu_marker : 0, 0);
-    }
-
-    protected void createMenu(int[] strId, View button) {
-        PopupMenu pmenu = new PopupMenu(mContext, button);
-        Menu menu = pmenu.getMenu();
-        for (int i = 0; i < strId.length; i++) {
-            menu.add(Menu.NONE, Menu.FIRST + i, 0, mContext.getString(strId[i]));
-        }
-        setMenuIcon(true);
-
-    }
-
-    public Control[] getControls() {
-        return null;
-    }
-    @Override
-    public void onStartTrackingTouch(SeekBar arg0) {
-
-    }
-
-    @Override
-    public void onStopTrackingTouch(SeekBar arg0) {
-
-    }
-
-    @Override
-    public void swapLeft(MenuItem item) {
-
-    }
-
-    @Override
-    public void swapRight(MenuItem item) {
-
-    }
-
-    public void detach() {
-    }
-}
diff --git a/src/com/android/gallery3d/filtershow/editors/EditorChanSat.java b/src/com/android/gallery3d/filtershow/editors/EditorChanSat.java
deleted file mode 100644
index 7e31f09..0000000
--- a/src/com/android/gallery3d/filtershow/editors/EditorChanSat.java
+++ /dev/null
@@ -1,227 +0,0 @@
-/*
- * Copyright (C) 2013 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.gallery3d.filtershow.editors;
-
-import android.content.Context;
-import android.graphics.Bitmap;
-import android.os.Handler;
-import android.view.MenuItem;
-import android.view.View;
-import android.view.View.OnClickListener;
-import android.widget.LinearLayout;
-import android.widget.PopupMenu;
-import android.widget.SeekBar.OnSeekBarChangeListener;
-
-import com.android.gallery3d.R;
-import com.android.gallery3d.filtershow.controller.BasicParameterStyle;
-import com.android.gallery3d.filtershow.controller.FilterView;
-import com.android.gallery3d.filtershow.controller.Parameter;
-import com.android.gallery3d.filtershow.filters.FilterChanSatRepresentation;
-import com.android.gallery3d.filtershow.filters.FilterRepresentation;
-import com.android.gallery3d.filtershow.imageshow.MasterImage;
-import com.android.gallery3d.filtershow.pipeline.ImagePreset;
-import com.android.gallery3d.filtershow.pipeline.RenderingRequest;
-import com.android.gallery3d.filtershow.pipeline.RenderingRequestCaller;
-
-public class EditorChanSat extends ParametricEditor implements OnSeekBarChangeListener, FilterView {
-    public static final int ID = R.id.editorChanSat;
-    private final String LOGTAG = "EditorGrunge";
-    private SwapButton mButton;
-    private final Handler mHandler = new Handler();
-
-    int[] mMenuStrings = {
-            R.string.editor_chan_sat_main,
-            R.string.editor_chan_sat_red,
-            R.string.editor_chan_sat_yellow,
-            R.string.editor_chan_sat_green,
-            R.string.editor_chan_sat_cyan,
-            R.string.editor_chan_sat_blue,
-            R.string.editor_chan_sat_magenta
-    };
-
-    String mCurrentlyEditing = null;
-
-    public EditorChanSat() {
-        super(ID, R.layout.filtershow_default_editor, R.id.basicEditor);
-    }
-
-    @Override
-    public String calculateUserMessage(Context context, String effectName, Object parameterValue) {
-        FilterRepresentation rep = getLocalRepresentation();
-        if (rep == null || !(rep instanceof FilterChanSatRepresentation)) {
-            return "";
-        }
-        FilterChanSatRepresentation csrep = (FilterChanSatRepresentation) rep;
-        int mode = csrep.getParameterMode();
-        String paramString;
-
-        paramString = mContext.getString(mMenuStrings[mode]);
-
-        int val = csrep.getCurrentParameter();
-        return paramString + ((val > 0) ? " +" : " ") + val;
-    }
-
-    @Override
-    public void openUtilityPanel(final LinearLayout accessoryViewList) {
-        mButton = (SwapButton) accessoryViewList.findViewById(R.id.applyEffect);
-        mButton.setText(mContext.getString(R.string.editor_chan_sat_main));
-
-        final PopupMenu popupMenu = new PopupMenu(mImageShow.getActivity(), mButton);
-
-        popupMenu.getMenuInflater().inflate(R.menu.filtershow_menu_chan_sat, popupMenu.getMenu());
-
-        popupMenu.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
-            @Override
-            public boolean onMenuItemClick(MenuItem item) {
-                selectMenuItem(item);
-                return true;
-            }
-        });
-        mButton.setOnClickListener(new OnClickListener() {
-            @Override
-            public void onClick(View arg0) {
-                popupMenu.show();
-            }
-        });
-        mButton.setListener(this);
-
-        FilterChanSatRepresentation csrep = getChanSatRep();
-        String menuString = mContext.getString(mMenuStrings[0]);
-        switchToMode(csrep, FilterChanSatRepresentation.MODE_MASTER, menuString);
-
-    }
-
-    public int getParameterIndex(int id) {
-        switch (id) {
-            case R.id.editor_chan_sat_main:
-                return FilterChanSatRepresentation.MODE_MASTER;
-            case R.id.editor_chan_sat_red:
-                return FilterChanSatRepresentation.MODE_RED;
-            case R.id.editor_chan_sat_yellow:
-                return FilterChanSatRepresentation.MODE_YELLOW;
-            case R.id.editor_chan_sat_green:
-                return FilterChanSatRepresentation.MODE_GREEN;
-            case R.id.editor_chan_sat_cyan:
-                return FilterChanSatRepresentation.MODE_CYAN;
-            case R.id.editor_chan_sat_blue:
-                return FilterChanSatRepresentation.MODE_BLUE;
-            case R.id.editor_chan_sat_magenta:
-                return FilterChanSatRepresentation.MODE_MAGENTA;
-        }
-        return -1;
-    }
-
-    @Override
-    public void detach() {
-        mButton.setListener(null);
-        mButton.setOnClickListener(null);
-    }
-
-    private void updateSeekBar(FilterChanSatRepresentation rep) {
-        mControl.updateUI();
-    }
-
-    @Override
-    protected Parameter getParameterToEdit(FilterRepresentation rep) {
-        if (rep instanceof FilterChanSatRepresentation) {
-            FilterChanSatRepresentation csrep = (FilterChanSatRepresentation) rep;
-            Parameter param = csrep.getFilterParameter(csrep.getParameterMode());
-            if (param instanceof BasicParameterStyle) {
-                param.setFilterView(EditorChanSat.this);
-            }
-            return param;
-        }
-        return null;
-    }
-
-    private FilterChanSatRepresentation getChanSatRep() {
-        FilterRepresentation rep = getLocalRepresentation();
-        if (rep != null
-                && rep instanceof FilterChanSatRepresentation) {
-            FilterChanSatRepresentation csrep = (FilterChanSatRepresentation) rep;
-            return csrep;
-        }
-        return null;
-    }
-
-    @Override
-    public void computeIcon(int n, RenderingRequestCaller caller) {
-        FilterChanSatRepresentation rep = getChanSatRep();
-        if (rep == null) return;
-        rep = (FilterChanSatRepresentation) rep.copy();
-        ImagePreset preset = new ImagePreset();
-        preset.addFilter(rep);
-        Bitmap src = MasterImage.getImage().getThumbnailBitmap();
-        RenderingRequest.post(null, src, preset, RenderingRequest.STYLE_ICON_RENDERING,
-                caller);
-    }
-
-    protected void selectMenuItem(MenuItem item) {
-        if (getLocalRepresentation() != null
-                && getLocalRepresentation() instanceof FilterChanSatRepresentation) {
-            FilterChanSatRepresentation csrep =
-                    (FilterChanSatRepresentation) getLocalRepresentation();
-
-            switchToMode(csrep, getParameterIndex(item.getItemId()), item.getTitle().toString());
-
-        }
-    }
-
-    protected void switchToMode(FilterChanSatRepresentation csrep, int mode, String title) {
-        csrep.setParameterMode(mode);
-        mCurrentlyEditing = title;
-        mButton.setText(mCurrentlyEditing);
-        {
-            Parameter param = getParameterToEdit(csrep);
-
-            control(param, mEditControl);
-        }
-        updateSeekBar(csrep);
-        mView.invalidate();
-    }
-
-    @Override
-    public void swapLeft(MenuItem item) {
-        super.swapLeft(item);
-        mButton.setTranslationX(0);
-        mButton.animate().translationX(mButton.getWidth()).setDuration(SwapButton.ANIM_DURATION);
-        Runnable updateButton = new Runnable() {
-            @Override
-            public void run() {
-                mButton.animate().cancel();
-                mButton.setTranslationX(0);
-            }
-        };
-        mHandler.postDelayed(updateButton, SwapButton.ANIM_DURATION);
-        selectMenuItem(item);
-    }
-
-    @Override
-    public void swapRight(MenuItem item) {
-        super.swapRight(item);
-        mButton.setTranslationX(0);
-        mButton.animate().translationX(-mButton.getWidth()).setDuration(SwapButton.ANIM_DURATION);
-        Runnable updateButton = new Runnable() {
-            @Override
-            public void run() {
-                mButton.animate().cancel();
-                mButton.setTranslationX(0);
-            }
-        };
-        mHandler.postDelayed(updateButton, SwapButton.ANIM_DURATION);
-        selectMenuItem(item);
-    }
-}
diff --git a/src/com/android/gallery3d/filtershow/editors/EditorCrop.java b/src/com/android/gallery3d/filtershow/editors/EditorCrop.java
deleted file mode 100644
index 511d4ff..0000000
--- a/src/com/android/gallery3d/filtershow/editors/EditorCrop.java
+++ /dev/null
@@ -1,168 +0,0 @@
-/*
- * Copyright (C) 2013 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.gallery3d.filtershow.editors;
-
-import android.content.Context;
-import android.util.Log;
-import android.util.SparseArray;
-import android.view.MenuItem;
-import android.view.View;
-import android.view.View.OnClickListener;
-import android.widget.Button;
-import android.widget.FrameLayout;
-import android.widget.LinearLayout;
-import android.widget.PopupMenu;
-
-import com.android.gallery3d.R;
-import com.android.gallery3d.filtershow.filters.FilterCropRepresentation;
-import com.android.gallery3d.filtershow.filters.FilterRepresentation;
-import com.android.gallery3d.filtershow.imageshow.ImageCrop;
-import com.android.gallery3d.filtershow.imageshow.MasterImage;
-
-public class EditorCrop extends Editor implements EditorInfo {
-    public static final String TAG = EditorCrop.class.getSimpleName();
-    public static final int ID = R.id.editorCrop;
-
-    // Holder for an aspect ratio it's string id
-    protected static final class AspectInfo {
-        int mAspectX;
-        int mAspectY;
-        int mStringId;
-        AspectInfo(int stringID, int x, int y) {
-            mStringId = stringID;
-            mAspectX = x;
-            mAspectY = y;
-        }
-    };
-
-    // Mapping from menu id to aspect ratio
-    protected static final SparseArray<AspectInfo> sAspects;
-    static {
-        sAspects = new SparseArray<AspectInfo>();
-        sAspects.put(R.id.crop_menu_1to1, new AspectInfo(R.string.aspect1to1_effect, 1, 1));
-        sAspects.put(R.id.crop_menu_4to3, new AspectInfo(R.string.aspect4to3_effect, 4, 3));
-        sAspects.put(R.id.crop_menu_3to4, new AspectInfo(R.string.aspect3to4_effect, 3, 4));
-        sAspects.put(R.id.crop_menu_5to7, new AspectInfo(R.string.aspect5to7_effect, 5, 7));
-        sAspects.put(R.id.crop_menu_7to5, new AspectInfo(R.string.aspect7to5_effect, 7, 5));
-        sAspects.put(R.id.crop_menu_none, new AspectInfo(R.string.aspectNone_effect, 0, 0));
-        sAspects.put(R.id.crop_menu_original, new AspectInfo(R.string.aspectOriginal_effect, 0, 0));
-    }
-
-    protected ImageCrop mImageCrop;
-    private String mAspectString = "";
-
-    public EditorCrop() {
-        super(ID);
-        mChangesGeometry = true;
-    }
-
-    @Override
-    public void createEditor(Context context, FrameLayout frameLayout) {
-        super.createEditor(context, frameLayout);
-        if (mImageCrop == null) {
-            mImageCrop = new ImageCrop(context);
-        }
-        mView = mImageShow = mImageCrop;
-        mImageCrop.setEditor(this);
-    }
-
-    @Override
-    public void reflectCurrentFilter() {
-        MasterImage master = MasterImage.getImage();
-        master.setCurrentFilterRepresentation(master.getPreset()
-                .getFilterWithSerializationName(FilterCropRepresentation.SERIALIZATION_NAME));
-        super.reflectCurrentFilter();
-        FilterRepresentation rep = getLocalRepresentation();
-        if (rep == null || rep instanceof FilterCropRepresentation) {
-            mImageCrop.setFilterCropRepresentation((FilterCropRepresentation) rep);
-        } else {
-            Log.w(TAG, "Could not reflect current filter, not of type: "
-                    + FilterCropRepresentation.class.getSimpleName());
-        }
-        mImageCrop.invalidate();
-    }
-
-    @Override
-    public void finalApplyCalled() {
-        commitLocalRepresentation(mImageCrop.getFinalRepresentation());
-    }
-
-    @Override
-    public void openUtilityPanel(final LinearLayout accessoryViewList) {
-        Button view = (Button) accessoryViewList.findViewById(R.id.applyEffect);
-        view.setText(mContext.getString(R.string.crop));
-        view.setOnClickListener(new OnClickListener() {
-            @Override
-            public void onClick(View arg0) {
-                showPopupMenu(accessoryViewList);
-            }
-        });
-    }
-
-    private void changeCropAspect(int itemId) {
-        AspectInfo info = sAspects.get(itemId);
-        if (info == null) {
-            throw new IllegalArgumentException("Invalid resource ID: " + itemId);
-        }
-        if (itemId == R.id.crop_menu_original) {
-            mImageCrop.applyOriginalAspect();
-        } else if (itemId == R.id.crop_menu_none) {
-            mImageCrop.applyFreeAspect();
-        } else {
-            mImageCrop.applyAspect(info.mAspectX, info.mAspectY);
-        }
-        setAspectString(mContext.getString(info.mStringId));
-    }
-
-    private void showPopupMenu(LinearLayout accessoryViewList) {
-        final Button button = (Button) accessoryViewList.findViewById(R.id.applyEffect);
-        final PopupMenu popupMenu = new PopupMenu(mImageShow.getActivity(), button);
-        popupMenu.getMenuInflater().inflate(R.menu.filtershow_menu_crop, popupMenu.getMenu());
-        popupMenu.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
-            @Override
-            public boolean onMenuItemClick(MenuItem item) {
-                changeCropAspect(item.getItemId());
-                return true;
-            }
-        });
-        popupMenu.show();
-    }
-
-    @Override
-    public boolean showsSeekBar() {
-        return false;
-    }
-
-    @Override
-    public int getTextId() {
-        return R.string.crop;
-    }
-
-    @Override
-    public int getOverlayId() {
-        return R.drawable.filtershow_button_geometry_crop;
-    }
-
-    @Override
-    public boolean getOverlayOnly() {
-        return true;
-    }
-
-    private void setAspectString(String s) {
-        mAspectString = s;
-    }
-}
diff --git a/src/com/android/gallery3d/filtershow/editors/EditorCurves.java b/src/com/android/gallery3d/filtershow/editors/EditorCurves.java
deleted file mode 100644
index 83fbced..0000000
--- a/src/com/android/gallery3d/filtershow/editors/EditorCurves.java
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * 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.gallery3d.filtershow.editors;
-
-import android.content.Context;
-import android.widget.FrameLayout;
-
-import com.android.gallery3d.R;
-import com.android.gallery3d.filtershow.filters.FilterCurvesRepresentation;
-import com.android.gallery3d.filtershow.filters.FilterRepresentation;
-import com.android.gallery3d.filtershow.imageshow.ImageCurves;
-
-public class EditorCurves extends Editor {
-    public static final int ID = R.id.imageCurves;
-    ImageCurves mImageCurves;
-
-    public EditorCurves() {
-        super(ID);
-    }
-
-    @Override
-    public void createEditor(Context context, FrameLayout frameLayout) {
-        super.createEditor(context, frameLayout);
-        mView = mImageShow = mImageCurves = new ImageCurves(context);
-        mImageCurves.setEditor(this);
-    }
-
-    @Override
-    public void reflectCurrentFilter() {
-        super.reflectCurrentFilter();
-        FilterRepresentation rep = getLocalRepresentation();
-        if (rep != null && getLocalRepresentation() instanceof FilterCurvesRepresentation) {
-            FilterCurvesRepresentation drawRep = (FilterCurvesRepresentation) rep;
-            mImageCurves.setFilterDrawRepresentation(drawRep);
-        }
-    }
-
-    @Override
-    public boolean showsSeekBar() {
-        return false;
-    }
-}
diff --git a/src/com/android/gallery3d/filtershow/editors/EditorDraw.java b/src/com/android/gallery3d/filtershow/editors/EditorDraw.java
deleted file mode 100644
index 4b09051..0000000
--- a/src/com/android/gallery3d/filtershow/editors/EditorDraw.java
+++ /dev/null
@@ -1,158 +0,0 @@
-/*
- * Copyright (C) 2013 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.gallery3d.filtershow.editors;
-
-import android.app.Dialog;
-import android.content.Context;
-import android.view.MenuItem;
-import android.view.View;
-import android.view.View.OnClickListener;
-import android.view.WindowManager.LayoutParams;
-import android.widget.Button;
-import android.widget.FrameLayout;
-import android.widget.LinearLayout;
-import android.widget.PopupMenu;
-import android.widget.SeekBar;
-
-import com.android.gallery3d.R;
-import com.android.gallery3d.filtershow.FilterShowActivity;
-import com.android.gallery3d.filtershow.colorpicker.ColorGridDialog;
-import com.android.gallery3d.filtershow.colorpicker.RGBListener;
-import com.android.gallery3d.filtershow.filters.FilterDrawRepresentation;
-import com.android.gallery3d.filtershow.filters.FilterRepresentation;
-import com.android.gallery3d.filtershow.filters.ImageFilterDraw;
-import com.android.gallery3d.filtershow.imageshow.ImageDraw;
-
-public class EditorDraw extends Editor {
-    private static final String LOGTAG = "EditorDraw";
-    public static final int ID = R.id.editorDraw;
-    public ImageDraw mImageDraw;
-
-    public EditorDraw() {
-        super(ID);
-    }
-
-    @Override
-    public void createEditor(Context context, FrameLayout frameLayout) {
-        super.createEditor(context, frameLayout);
-        mView = mImageShow = mImageDraw = new ImageDraw(context);
-        mImageDraw.setEditor(this);
-
-    }
-
-    @Override
-    public void reflectCurrentFilter() {
-        super.reflectCurrentFilter();
-        FilterRepresentation rep = getLocalRepresentation();
-
-        if (rep != null && getLocalRepresentation() instanceof FilterDrawRepresentation) {
-            FilterDrawRepresentation drawRep = (FilterDrawRepresentation) getLocalRepresentation();
-            mImageDraw.setFilterDrawRepresentation(drawRep);
-        }
-    }
-
-    @Override
-    public void openUtilityPanel(final LinearLayout accessoryViewList) {
-        Button view = (Button) accessoryViewList.findViewById(R.id.applyEffect);
-        view.setText(mContext.getString(R.string.draw_style));
-        view.setOnClickListener(new OnClickListener() {
-
-                @Override
-            public void onClick(View arg0) {
-                showPopupMenu(accessoryViewList);
-            }
-        });
-    }
-
-    @Override
-    public boolean showsSeekBar() {
-        return false;
-    }
-
-    private void showPopupMenu(LinearLayout accessoryViewList) {
-        final Button button = (Button) accessoryViewList.findViewById(
-                R.id.applyEffect);
-        if (button == null) {
-            return;
-        }
-        final PopupMenu popupMenu = new PopupMenu(mImageShow.getActivity(), button);
-        popupMenu.getMenuInflater().inflate(R.menu.filtershow_menu_draw, popupMenu.getMenu());
-        popupMenu.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
-
-            @Override
-            public boolean onMenuItemClick(MenuItem item) {
-                ImageFilterDraw filter = (ImageFilterDraw) mImageShow.getCurrentFilter();
-                if (item.getItemId() == R.id.draw_menu_color) {
-                    showColorGrid(item);
-                } else if (item.getItemId() == R.id.draw_menu_size) {
-                    showSizeDialog(item);
-                } else if (item.getItemId() == R.id.draw_menu_style_brush_marker) {
-                    ImageDraw idraw = (ImageDraw) mImageShow;
-                    idraw.setStyle(ImageFilterDraw.BRUSH_STYLE_MARKER);
-                } else if (item.getItemId() == R.id.draw_menu_style_brush_spatter) {
-                    ImageDraw idraw = (ImageDraw) mImageShow;
-                    idraw.setStyle(ImageFilterDraw.BRUSH_STYLE_SPATTER);
-                } else if (item.getItemId() == R.id.draw_menu_style_line) {
-                    ImageDraw idraw = (ImageDraw) mImageShow;
-                    idraw.setStyle(ImageFilterDraw.SIMPLE_STYLE);
-                } else if (item.getItemId() == R.id.draw_menu_clear) {
-                    ImageDraw idraw = (ImageDraw) mImageShow;
-                    idraw.resetParameter();
-                    commitLocalRepresentation();
-                }
-                mView.invalidate();
-                return true;
-            }
-        });
-        popupMenu.show();
-    }
-
-    public void showSizeDialog(final MenuItem item) {
-        FilterShowActivity ctx = mImageShow.getActivity();
-        final Dialog dialog = new Dialog(ctx);
-        dialog.setTitle(R.string.draw_size_title);
-        dialog.setContentView(R.layout.filtershow_draw_size);
-        final SeekBar bar = (SeekBar) dialog.findViewById(R.id.sizeSeekBar);
-        ImageDraw idraw = (ImageDraw) mImageShow;
-        bar.setProgress(idraw.getSize());
-        Button button = (Button) dialog.findViewById(R.id.sizeAcceptButton);
-        button.setOnClickListener(new OnClickListener() {
-
-            @Override
-            public void onClick(View arg0) {
-                int p = bar.getProgress();
-                ImageDraw idraw = (ImageDraw) mImageShow;
-                idraw.setSize(p + 1);
-                dialog.dismiss();
-            }
-        });
-        dialog.show();
-    }
-
-    public void showColorGrid(final MenuItem item) {
-        RGBListener cl = new RGBListener() {
-            @Override
-            public void setColor(int rgb) {
-                ImageDraw idraw = (ImageDraw) mImageShow;
-                idraw.setColor(rgb);
-            }
-        };
-        ColorGridDialog cpd = new ColorGridDialog(mImageShow.getActivity(), cl);
-        cpd.show();
-        LayoutParams params = cpd.getWindow().getAttributes();
-    }
-}
diff --git a/src/com/android/gallery3d/filtershow/editors/EditorGrad.java b/src/com/android/gallery3d/filtershow/editors/EditorGrad.java
deleted file mode 100644
index f427ccb..0000000
--- a/src/com/android/gallery3d/filtershow/editors/EditorGrad.java
+++ /dev/null
@@ -1,315 +0,0 @@
-/*
- * Copyright (C) 2013 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.gallery3d.filtershow.editors;
-
-import android.content.Context;
-import android.view.MenuItem;
-import android.view.View;
-import android.view.View.OnClickListener;
-import android.widget.Button;
-import android.widget.FrameLayout;
-import android.widget.LinearLayout;
-import android.widget.PopupMenu;
-import android.widget.SeekBar;
-import android.widget.SeekBar.OnSeekBarChangeListener;
-import android.widget.ToggleButton;
-
-import com.android.gallery3d.R;
-import com.android.gallery3d.filtershow.controller.Control;
-import com.android.gallery3d.filtershow.controller.FilterView;
-import com.android.gallery3d.filtershow.controller.Parameter;
-import com.android.gallery3d.filtershow.controller.ParameterActionAndInt;
-import com.android.gallery3d.filtershow.filters.FilterGradRepresentation;
-import com.android.gallery3d.filtershow.filters.FilterRepresentation;
-import com.android.gallery3d.filtershow.imageshow.ImageGrad;
-import com.android.gallery3d.filtershow.imageshow.MasterImage;
-
-public class EditorGrad extends ParametricEditor
-        implements OnSeekBarChangeListener, ParameterActionAndInt {
-    private static final String LOGTAG = "EditorGrad";
-    public static final int ID = R.id.editorGrad;
-    PopupMenu mPopupMenu;
-    ToggleButton mAddModeButton;
-    String mEffectName = "";
-    private static final int MODE_BRIGHTNESS = FilterGradRepresentation.PARAM_BRIGHTNESS;
-    private static final int MODE_SATURATION = FilterGradRepresentation.PARAM_SATURATION;
-    private static final int MODE_CONTRAST = FilterGradRepresentation.PARAM_CONTRAST;
-    private static final int ADD_ICON = R.drawable.ic_grad_add;
-    private static final int DEL_ICON = R.drawable.ic_grad_del;
-    private int mSliderMode = MODE_BRIGHTNESS;
-    ImageGrad mImageGrad;
-
-    public EditorGrad() {
-        super(ID, R.layout.filtershow_grad_editor, R.id.gradEditor);
-    }
-
-    @Override
-    public void createEditor(Context context, FrameLayout frameLayout) {
-        super.createEditor(context, frameLayout);
-        mImageGrad = (ImageGrad) mImageShow;
-        mImageGrad.setEditor(this);
-
-    }
-
-    public void clearAddMode() {
-        mAddModeButton.setChecked(false);
-        FilterRepresentation tmpRep = getLocalRepresentation();
-        if (tmpRep instanceof FilterGradRepresentation) {
-            updateMenuItems((FilterGradRepresentation) tmpRep);
-        }
-    }
-
-    @Override
-    public void reflectCurrentFilter() {
-        super.reflectCurrentFilter();
-        FilterRepresentation tmpRep = getLocalRepresentation();
-        if (tmpRep instanceof FilterGradRepresentation) {
-            FilterGradRepresentation rep = (FilterGradRepresentation) tmpRep;
-            boolean f = rep.showParameterValue();
-
-            mImageGrad.setRepresentation(rep);
-        }
-    }
-
-    public void updateSeekBar(FilterGradRepresentation rep) {
-        mControl.updateUI();
-    }
-
-    @Override
-    public void onProgressChanged(SeekBar sbar, int progress, boolean arg2) {
-        FilterRepresentation tmpRep = getLocalRepresentation();
-        if (tmpRep instanceof FilterGradRepresentation) {
-            FilterGradRepresentation rep = (FilterGradRepresentation) tmpRep;
-            int min = rep.getParameterMin(mSliderMode);
-            int value = progress + min;
-            rep.setParameter(mSliderMode, value);
-            mView.invalidate();
-            commitLocalRepresentation();
-        }
-    }
-
-    @Override
-    public void openUtilityPanel(final LinearLayout accessoryViewList) {
-        Button view = (Button) accessoryViewList.findViewById(R.id.applyEffect);
-        view.setText(mContext.getString(R.string.editor_grad_brightness));
-        view.setOnClickListener(new OnClickListener() {
-            @Override
-            public void onClick(View arg0) {
-                showPopupMenu(accessoryViewList);
-            }
-        });
-
-        setUpPopupMenu(view);
-        setEffectName();
-    }
-
-    private void updateMenuItems(FilterGradRepresentation rep) {
-        int n = rep.getNumberOfBands();
-    }
-
-    public void setEffectName() {
-        if (mPopupMenu != null) {
-            MenuItem item = mPopupMenu.getMenu().findItem(R.id.editor_grad_brightness);
-            mEffectName = item.getTitle().toString();
-        }
-    }
-
-    private void showPopupMenu(LinearLayout accessoryViewList) {
-        Button button = (Button) accessoryViewList.findViewById(R.id.applyEffect);
-        if (button == null) {
-            return;
-        }
-
-        if (mPopupMenu == null) {
-            setUpPopupMenu(button);
-        }
-        mPopupMenu.show();
-    }
-
-    private void setUpPopupMenu(Button button) {
-        mPopupMenu = new PopupMenu(mImageShow.getActivity(), button);
-        mPopupMenu.getMenuInflater()
-                .inflate(R.menu.filtershow_menu_grad, mPopupMenu.getMenu());
-        FilterGradRepresentation rep = (FilterGradRepresentation) getLocalRepresentation();
-        if (rep == null) {
-            return;
-        }
-        updateMenuItems(rep);
-        hackFixStrings(mPopupMenu.getMenu());
-        setEffectName();
-        updateText();
-
-        mPopupMenu.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
-            @Override
-            public boolean onMenuItemClick(MenuItem item) {
-                FilterRepresentation tmpRep = getLocalRepresentation();
-
-                if (tmpRep instanceof FilterGradRepresentation) {
-                    FilterGradRepresentation rep = (FilterGradRepresentation) tmpRep;
-                    int cmdID = item.getItemId();
-                    switch (cmdID) {
-                        case R.id.editor_grad_brightness:
-                            mSliderMode = MODE_BRIGHTNESS;
-                            mEffectName = item.getTitle().toString();
-                            break;
-                        case R.id.editor_grad_contrast:
-                            mSliderMode = MODE_CONTRAST;
-                            mEffectName = item.getTitle().toString();
-                            break;
-                        case R.id.editor_grad_saturation:
-                            mSliderMode = MODE_SATURATION;
-                            mEffectName = item.getTitle().toString();
-                            break;
-                    }
-                    updateMenuItems(rep);
-                    updateSeekBar(rep);
-
-                    commitLocalRepresentation();
-                    mView.invalidate();
-                }
-                return true;
-            }
-        });
-    }
-
-    @Override
-    public String calculateUserMessage(Context context, String effectName, Object parameterValue) {
-        FilterGradRepresentation rep = getGradRepresentation();
-        if (rep == null) {
-            return mEffectName;
-        }
-        int val = rep.getParameter(mSliderMode);
-        return mEffectName.toUpperCase() + ((val > 0) ? " +" : " ") + val;
-    }
-
-    private FilterGradRepresentation getGradRepresentation() {
-        FilterRepresentation tmpRep = getLocalRepresentation();
-        if (tmpRep instanceof FilterGradRepresentation) {
-            return (FilterGradRepresentation) tmpRep;
-        }
-        return null;
-    }
-
-    @Override
-    public int getMaximum() {
-        FilterGradRepresentation rep = getGradRepresentation();
-        if (rep == null) {
-            return 0;
-        }
-        return rep.getParameterMax(mSliderMode);
-    }
-
-    @Override
-    public int getMinimum() {
-        FilterGradRepresentation rep = getGradRepresentation();
-        if (rep == null) {
-            return 0;
-        }
-        return rep.getParameterMin(mSliderMode);
-    }
-
-    @Override
-    public int getDefaultValue() {
-        return 0;
-    }
-
-    @Override
-    public int getValue() {
-        FilterGradRepresentation rep = getGradRepresentation();
-        if (rep == null) {
-            return 0;
-        }
-        return rep.getParameter(mSliderMode);
-    }
-
-    @Override
-    public String getValueString() {
-        return null;
-    }
-
-    @Override
-    public void setValue(int value) {
-        FilterGradRepresentation rep = getGradRepresentation();
-        if (rep == null) {
-            return;
-        }
-        rep.setParameter(mSliderMode, value);
-    }
-
-    @Override
-    public String getParameterName() {
-        return mEffectName;
-    }
-
-    @Override
-    public String getParameterType() {
-        return sParameterType;
-    }
-
-    @Override
-    public void setController(Control c) {
-
-    }
-
-    @Override
-    public void fireLeftAction() {
-        FilterGradRepresentation rep = getGradRepresentation();
-        if (rep == null) {
-            return;
-        }
-        rep.addBand(MasterImage.getImage().getOriginalBounds());
-        updateMenuItems(rep);
-        updateSeekBar(rep);
-
-        commitLocalRepresentation();
-        mView.invalidate();
-    }
-
-    @Override
-    public int getLeftIcon() {
-        return ADD_ICON;
-    }
-
-    @Override
-    public void fireRightAction() {
-        FilterGradRepresentation rep = getGradRepresentation();
-        if (rep == null) {
-            return;
-        }
-        rep.deleteCurrentBand();
-
-        updateMenuItems(rep);
-        updateSeekBar(rep);
-        commitLocalRepresentation();
-        mView.invalidate();
-    }
-
-    @Override
-    public int getRightIcon() {
-        return DEL_ICON;
-    }
-
-    @Override
-    public void setFilterView(FilterView editor) {
-
-    }
-
-    @Override
-    public void copyFrom(Parameter src) {
-
-    }
-
-}
diff --git a/src/com/android/gallery3d/filtershow/editors/EditorInfo.java b/src/com/android/gallery3d/filtershow/editors/EditorInfo.java
deleted file mode 100644
index 75afe49..0000000
--- a/src/com/android/gallery3d/filtershow/editors/EditorInfo.java
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * Copyright (C) 2013 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.gallery3d.filtershow.editors;
-
-public interface EditorInfo {
-    public int getTextId();
-    public int getOverlayId();
-    public boolean getOverlayOnly();
-}
diff --git a/src/com/android/gallery3d/filtershow/editors/EditorMirror.java b/src/com/android/gallery3d/filtershow/editors/EditorMirror.java
deleted file mode 100644
index d6d9ee7..0000000
--- a/src/com/android/gallery3d/filtershow/editors/EditorMirror.java
+++ /dev/null
@@ -1,109 +0,0 @@
-/*
- * Copyright (C) 2013 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.gallery3d.filtershow.editors;
-
-import android.content.Context;
-import android.util.Log;
-import android.view.View;
-import android.view.View.OnClickListener;
-import android.widget.Button;
-import android.widget.FrameLayout;
-import android.widget.LinearLayout;
-
-import com.android.gallery3d.R;
-import com.android.gallery3d.filtershow.filters.FilterMirrorRepresentation;
-import com.android.gallery3d.filtershow.filters.FilterRepresentation;
-import com.android.gallery3d.filtershow.imageshow.ImageMirror;
-import com.android.gallery3d.filtershow.imageshow.MasterImage;
-
-public class EditorMirror extends Editor implements EditorInfo {
-    public static final String TAG = EditorMirror.class.getSimpleName();
-    public static final int ID = R.id.editorFlip;
-    ImageMirror mImageMirror;
-
-    public EditorMirror() {
-        super(ID);
-        mChangesGeometry = true;
-    }
-
-    @Override
-    public void createEditor(Context context, FrameLayout frameLayout) {
-        super.createEditor(context, frameLayout);
-        if (mImageMirror == null) {
-            mImageMirror = new ImageMirror(context);
-        }
-        mView = mImageShow = mImageMirror;
-        mImageMirror.setEditor(this);
-    }
-
-    @Override
-    public void reflectCurrentFilter() {
-        MasterImage master = MasterImage.getImage();
-        master.setCurrentFilterRepresentation(master.getPreset()
-                .getFilterWithSerializationName(FilterMirrorRepresentation.SERIALIZATION_NAME));
-        super.reflectCurrentFilter();
-        FilterRepresentation rep = getLocalRepresentation();
-        if (rep == null || rep instanceof FilterMirrorRepresentation) {
-            mImageMirror.setFilterMirrorRepresentation((FilterMirrorRepresentation) rep);
-        } else {
-            Log.w(TAG, "Could not reflect current filter, not of type: "
-                    + FilterMirrorRepresentation.class.getSimpleName());
-        }
-        mImageMirror.invalidate();
-    }
-
-    @Override
-    public void openUtilityPanel(final LinearLayout accessoryViewList) {
-        final Button button = (Button) accessoryViewList.findViewById(R.id.applyEffect);
-        button.setOnClickListener(new OnClickListener() {
-            @Override
-            public void onClick(View arg0) {
-                mImageMirror.flip();
-            }
-        });
-    }
-
-    @Override
-    public void finalApplyCalled() {
-        commitLocalRepresentation(mImageMirror.getFinalRepresentation());
-    }
-
-    @Override
-    public int getTextId() {
-        return R.string.mirror;
-    }
-
-    @Override
-    public int getOverlayId() {
-        return R.drawable.filtershow_button_geometry_flip;
-    }
-
-    @Override
-    public boolean getOverlayOnly() {
-        return true;
-    }
-
-    @Override
-    public boolean showsSeekBar() {
-        return false;
-    }
-
-    @Override
-    public boolean showsPopupIndicator() {
-        return false;
-    }
-}
diff --git a/src/com/android/gallery3d/filtershow/editors/EditorPanel.java b/src/com/android/gallery3d/filtershow/editors/EditorPanel.java
deleted file mode 100644
index bc4ca6a..0000000
--- a/src/com/android/gallery3d/filtershow/editors/EditorPanel.java
+++ /dev/null
@@ -1,143 +0,0 @@
-/*
- * Copyright (C) 2013 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.gallery3d.filtershow.editors;
-
-import android.app.Activity;
-import android.os.Bundle;
-import android.support.v4.app.Fragment;
-import android.support.v4.app.FragmentTransaction;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.Button;
-import android.widget.ImageButton;
-import android.widget.LinearLayout;
-import com.android.gallery3d.R;
-import com.android.gallery3d.filtershow.FilterShowActivity;
-import com.android.gallery3d.filtershow.history.HistoryManager;
-import com.android.gallery3d.filtershow.category.MainPanel;
-import com.android.gallery3d.filtershow.imageshow.MasterImage;
-import com.android.gallery3d.filtershow.state.StatePanel;
-
-public class EditorPanel extends Fragment {
-
-    private static final String LOGTAG = "EditorPanel";
-
-    private LinearLayout mMainView;
-    private Editor mEditor;
-    private int mEditorID;
-
-    public void setEditor(int editor) {
-        mEditorID = editor;
-    }
-
-    @Override
-    public void onAttach(Activity activity) {
-        super.onAttach(activity);
-        FilterShowActivity filterShowActivity = (FilterShowActivity) activity;
-        mEditor = filterShowActivity.getEditor(mEditorID);
-    }
-
-    public void cancelCurrentFilter() {
-        MasterImage masterImage = MasterImage.getImage();
-        HistoryManager adapter = masterImage.getHistory();
-
-        int position = adapter.undo();
-        masterImage.onHistoryItemClick(position);
-        ((FilterShowActivity)getActivity()).invalidateViews();
-    }
-
-    @Override
-    public View onCreateView(LayoutInflater inflater, ViewGroup container,
-                             Bundle savedInstanceState) {
-        FilterShowActivity activity = (FilterShowActivity) getActivity();
-        if (mMainView != null) {
-            if (mMainView.getParent() != null) {
-                ViewGroup parent = (ViewGroup) mMainView.getParent();
-                parent.removeView(mMainView);
-            }
-            showImageStatePanel(activity.isShowingImageStatePanel());
-            return mMainView;
-        }
-        mMainView = (LinearLayout) inflater.inflate(R.layout.filtershow_editor_panel, null);
-
-        View actionControl = mMainView.findViewById(R.id.panelAccessoryViewList);
-        View editControl = mMainView.findViewById(R.id.controlArea);
-        ImageButton cancelButton = (ImageButton) mMainView.findViewById(R.id.cancelFilter);
-        ImageButton applyButton = (ImageButton) mMainView.findViewById(R.id.applyFilter);
-        Button editTitle = (Button) mMainView.findViewById(R.id.applyEffect);
-        cancelButton.setOnClickListener(new View.OnClickListener() {
-            @Override
-            public void onClick(View v) {
-                cancelCurrentFilter();
-                FilterShowActivity activity = (FilterShowActivity) getActivity();
-                activity.backToMain();
-            }
-        });
-
-        Button toggleState = (Button) mMainView.findViewById(R.id.toggle_state);
-        mEditor = activity.getEditor(mEditorID);
-        if (mEditor != null) {
-            mEditor.setUpEditorUI(actionControl, editControl, editTitle, toggleState);
-            mEditor.reflectCurrentFilter();
-            if (mEditor.useUtilityPanel()) {
-                mEditor.openUtilityPanel((LinearLayout) actionControl);
-            }
-        }
-        applyButton.setOnClickListener(new View.OnClickListener() {
-            @Override
-            public void onClick(View v) {
-                FilterShowActivity activity = (FilterShowActivity) getActivity();
-                mEditor.finalApplyCalled();
-                activity.backToMain();
-            }
-        });
-
-        showImageStatePanel(activity.isShowingImageStatePanel());
-        return mMainView;
-    }
-
-    @Override
-    public void onDetach() {
-        if (mEditor != null) {
-            mEditor.detach();
-        }
-        super.onDetach();
-    }
-
-    public void showImageStatePanel(boolean show) {
-        if (mMainView.findViewById(R.id.state_panel_container) == null) {
-            return;
-        }
-        FragmentTransaction transaction = getChildFragmentManager().beginTransaction();
-        Fragment panel = getActivity().getSupportFragmentManager().findFragmentByTag(
-                MainPanel.FRAGMENT_TAG);
-        if (panel == null || panel instanceof MainPanel) {
-            transaction.setCustomAnimations(android.R.anim.fade_in, android.R.anim.fade_out);
-        }
-        if (show) {
-            StatePanel statePanel = new StatePanel();
-            transaction.replace(R.id.state_panel_container, statePanel, StatePanel.FRAGMENT_TAG);
-        } else {
-            Fragment statePanel = getChildFragmentManager().findFragmentByTag(StatePanel.FRAGMENT_TAG);
-            if (statePanel != null) {
-                transaction.remove(statePanel);
-            }
-        }
-        transaction.commit();
-    }
-}
diff --git a/src/com/android/gallery3d/filtershow/editors/EditorRedEye.java b/src/com/android/gallery3d/filtershow/editors/EditorRedEye.java
deleted file mode 100644
index b0e88dd..0000000
--- a/src/com/android/gallery3d/filtershow/editors/EditorRedEye.java
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * 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.gallery3d.filtershow.editors;
-
-import android.content.Context;
-import android.widget.FrameLayout;
-
-import com.android.gallery3d.R;
-import com.android.gallery3d.filtershow.filters.FilterRedEyeRepresentation;
-import com.android.gallery3d.filtershow.filters.FilterRepresentation;
-import com.android.gallery3d.filtershow.imageshow.ImageRedEye;
-
-/**
- * The editor with no slider for filters without UI
- */
-public class EditorRedEye extends Editor {
-    public static int ID = R.id.editorRedEye;
-    private final String LOGTAG = "EditorRedEye";
-    ImageRedEye mImageRedEyes;
-
-    public EditorRedEye() {
-        super(ID);
-    }
-
-    protected EditorRedEye(int id) {
-        super(id);
-    }
-
-    @Override
-    public void createEditor(Context context, FrameLayout frameLayout) {
-        super.createEditor(context, frameLayout);
-        mView = mImageShow = mImageRedEyes=  new ImageRedEye(context);
-        mImageRedEyes.setEditor(this);
-    }
-
-    @Override
-    public void reflectCurrentFilter() {
-        super.reflectCurrentFilter();
-        FilterRepresentation rep = getLocalRepresentation();
-        if (rep != null && getLocalRepresentation() instanceof FilterRedEyeRepresentation) {
-            FilterRedEyeRepresentation redEyeRep = (FilterRedEyeRepresentation) rep;
-
-            mImageRedEyes.setRepresentation(redEyeRep);
-        }
-    }
-
-    @Override
-    public boolean showsSeekBar() {
-        return false;
-    }
-}
diff --git a/src/com/android/gallery3d/filtershow/editors/EditorRotate.java b/src/com/android/gallery3d/filtershow/editors/EditorRotate.java
deleted file mode 100644
index 9452bf0..0000000
--- a/src/com/android/gallery3d/filtershow/editors/EditorRotate.java
+++ /dev/null
@@ -1,112 +0,0 @@
-/*
- * Copyright (C) 2013 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.gallery3d.filtershow.editors;
-
-import android.content.Context;
-import android.util.Log;
-import android.view.View;
-import android.view.View.OnClickListener;
-import android.widget.Button;
-import android.widget.FrameLayout;
-import android.widget.LinearLayout;
-
-import com.android.gallery3d.R;
-import com.android.gallery3d.filtershow.filters.FilterRepresentation;
-import com.android.gallery3d.filtershow.filters.FilterRotateRepresentation;
-import com.android.gallery3d.filtershow.imageshow.ImageRotate;
-import com.android.gallery3d.filtershow.imageshow.MasterImage;
-
-public class EditorRotate extends Editor implements EditorInfo {
-    public static final String TAG = EditorRotate.class.getSimpleName();
-    public static final int ID = R.id.editorRotate;
-    ImageRotate mImageRotate;
-
-    public EditorRotate() {
-        super(ID);
-        mChangesGeometry = true;
-    }
-
-    @Override
-    public void createEditor(Context context, FrameLayout frameLayout) {
-        super.createEditor(context, frameLayout);
-        if (mImageRotate == null) {
-            mImageRotate = new ImageRotate(context);
-        }
-        mView = mImageShow = mImageRotate;
-        mImageRotate.setEditor(this);
-    }
-
-    @Override
-    public void reflectCurrentFilter() {
-        MasterImage master = MasterImage.getImage();
-        master.setCurrentFilterRepresentation(master.getPreset()
-                .getFilterWithSerializationName(FilterRotateRepresentation.SERIALIZATION_NAME));
-        super.reflectCurrentFilter();
-        FilterRepresentation rep = getLocalRepresentation();
-        if (rep == null || rep instanceof FilterRotateRepresentation) {
-            mImageRotate.setFilterRotateRepresentation((FilterRotateRepresentation) rep);
-        } else {
-            Log.w(TAG, "Could not reflect current filter, not of type: "
-                    + FilterRotateRepresentation.class.getSimpleName());
-        }
-        mImageRotate.invalidate();
-    }
-
-    @Override
-    public void openUtilityPanel(final LinearLayout accessoryViewList) {
-        final Button button = (Button) accessoryViewList.findViewById(R.id.applyEffect);
-        button.setOnClickListener(new OnClickListener() {
-            @Override
-            public void onClick(View arg0) {
-                mImageRotate.rotate();
-                String displayVal = mContext.getString(getTextId()) + " "
-                        + mImageRotate.getLocalValue();
-                button.setText(displayVal);
-            }
-        });
-    }
-
-    @Override
-    public void finalApplyCalled() {
-        commitLocalRepresentation(mImageRotate.getFinalRepresentation());
-    }
-
-    @Override
-    public int getTextId() {
-        return R.string.rotate;
-    }
-
-    @Override
-    public int getOverlayId() {
-        return R.drawable.filtershow_button_geometry_rotate;
-    }
-
-    @Override
-    public boolean getOverlayOnly() {
-        return true;
-    }
-
-    @Override
-    public boolean showsSeekBar() {
-        return false;
-    }
-
-    @Override
-    public boolean showsPopupIndicator() {
-        return false;
-    }
-}
diff --git a/src/com/android/gallery3d/filtershow/editors/EditorStraighten.java b/src/com/android/gallery3d/filtershow/editors/EditorStraighten.java
deleted file mode 100644
index ff84ba8..0000000
--- a/src/com/android/gallery3d/filtershow/editors/EditorStraighten.java
+++ /dev/null
@@ -1,103 +0,0 @@
-/*
- * Copyright (C) 2013 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.gallery3d.filtershow.editors;
-
-import android.content.Context;
-import android.util.Log;
-import android.widget.FrameLayout;
-
-import com.android.gallery3d.R;
-import com.android.gallery3d.filtershow.filters.FilterRepresentation;
-import com.android.gallery3d.filtershow.filters.FilterStraightenRepresentation;
-import com.android.gallery3d.filtershow.imageshow.ImageStraighten;
-import com.android.gallery3d.filtershow.imageshow.MasterImage;
-
-public class EditorStraighten extends Editor implements EditorInfo {
-    public static final String TAG = EditorStraighten.class.getSimpleName();
-    public static final int ID = R.id.editorStraighten;
-    ImageStraighten mImageStraighten;
-
-    public EditorStraighten() {
-        super(ID);
-        mShowParameter = SHOW_VALUE_INT;
-        mChangesGeometry = true;
-    }
-
-    @Override
-    public String calculateUserMessage(Context context, String effectName, Object parameterValue) {
-        String apply = context.getString(R.string.apply_effect);
-        apply += " " + effectName;
-        return apply.toUpperCase();
-    }
-
-    @Override
-    public void createEditor(Context context, FrameLayout frameLayout) {
-        super.createEditor(context, frameLayout);
-        if (mImageStraighten == null) {
-            mImageStraighten = new ImageStraighten(context);
-        }
-        mView = mImageShow = mImageStraighten;
-        mImageStraighten.setEditor(this);
-    }
-
-    @Override
-    public void reflectCurrentFilter() {
-        MasterImage master = MasterImage.getImage();
-        master.setCurrentFilterRepresentation(master.getPreset().getFilterWithSerializationName(
-                FilterStraightenRepresentation.SERIALIZATION_NAME));
-        super.reflectCurrentFilter();
-        FilterRepresentation rep = getLocalRepresentation();
-        if (rep == null || rep instanceof FilterStraightenRepresentation) {
-            mImageStraighten
-                    .setFilterStraightenRepresentation((FilterStraightenRepresentation) rep);
-        } else {
-            Log.w(TAG, "Could not reflect current filter, not of type: "
-                    + FilterStraightenRepresentation.class.getSimpleName());
-        }
-        mImageStraighten.invalidate();
-    }
-
-    @Override
-    public void finalApplyCalled() {
-        commitLocalRepresentation(mImageStraighten.getFinalRepresentation());
-    }
-
-    @Override
-    public int getTextId() {
-        return R.string.straighten;
-    }
-
-    @Override
-    public int getOverlayId() {
-        return R.drawable.filtershow_button_geometry_straighten;
-    }
-
-    @Override
-    public boolean getOverlayOnly() {
-        return true;
-    }
-
-    @Override
-    public boolean showsSeekBar() {
-        return false;
-    }
-
-    @Override
-    public boolean showsPopupIndicator() {
-        return false;
-    }
-}
diff --git a/src/com/android/gallery3d/filtershow/editors/EditorTinyPlanet.java b/src/com/android/gallery3d/filtershow/editors/EditorTinyPlanet.java
deleted file mode 100644
index 9376fbe..0000000
--- a/src/com/android/gallery3d/filtershow/editors/EditorTinyPlanet.java
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * 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.gallery3d.filtershow.editors;
-
-import android.content.Context;
-import android.widget.FrameLayout;
-
-import com.android.gallery3d.R;
-import com.android.gallery3d.filtershow.filters.FilterRepresentation;
-import com.android.gallery3d.filtershow.filters.FilterTinyPlanetRepresentation;
-import com.android.gallery3d.filtershow.imageshow.ImageTinyPlanet;
-
-public class EditorTinyPlanet extends BasicEditor {
-    public static final int ID = R.id.tinyPlanetEditor;
-    private static final String LOGTAG = "EditorTinyPlanet";
-    ImageTinyPlanet mImageTinyPlanet;
-
-    public EditorTinyPlanet() {
-        super(ID, R.layout.filtershow_tiny_planet_editor, R.id.imageTinyPlanet);
-    }
-
-    @Override
-    public void createEditor(Context context, FrameLayout frameLayout) {
-        super.createEditor(context, frameLayout);
-        mImageTinyPlanet = (ImageTinyPlanet) mImageShow;
-        mImageTinyPlanet.setEditor(this);
-    }
-
-    @Override
-    public void reflectCurrentFilter() {
-        super.reflectCurrentFilter();
-        FilterRepresentation rep = getLocalRepresentation();
-        if (rep != null && rep instanceof FilterTinyPlanetRepresentation) {
-            FilterTinyPlanetRepresentation drawRep = (FilterTinyPlanetRepresentation) rep;
-            mImageTinyPlanet.setRepresentation(drawRep);
-        }
-    }
-
-    public void updateUI() {
-        if (mControl != null) {
-            mControl.updateUI();
-        }
-    }
-}
diff --git a/src/com/android/gallery3d/filtershow/editors/EditorVignette.java b/src/com/android/gallery3d/filtershow/editors/EditorVignette.java
deleted file mode 100644
index 7127b21..0000000
--- a/src/com/android/gallery3d/filtershow/editors/EditorVignette.java
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * 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.gallery3d.filtershow.editors;
-
-import android.content.Context;
-import android.widget.FrameLayout;
-
-import com.android.gallery3d.R;
-import com.android.gallery3d.filtershow.filters.FilterRepresentation;
-import com.android.gallery3d.filtershow.filters.FilterVignetteRepresentation;
-import com.android.gallery3d.filtershow.imageshow.ImageVignette;
-
-public class EditorVignette extends ParametricEditor {
-    public static final int ID = R.id.vignetteEditor;
-    private static final String LOGTAG = "EditorVignettePlanet";
-    ImageVignette mImageVignette;
-
-    public EditorVignette() {
-        super(ID, R.layout.filtershow_vignette_editor, R.id.imageVignette);
-    }
-
-    @Override
-    public void createEditor(Context context, FrameLayout frameLayout) {
-        super.createEditor(context, frameLayout);
-        mImageVignette = (ImageVignette) mImageShow;
-        mImageVignette.setEditor(this);
-    }
-
-    @Override
-    public void reflectCurrentFilter() {
-        super.reflectCurrentFilter();
-
-        FilterRepresentation rep = getLocalRepresentation();
-        if (rep != null && getLocalRepresentation() instanceof FilterVignetteRepresentation) {
-            FilterVignetteRepresentation drawRep = (FilterVignetteRepresentation) rep;
-            mImageVignette.setRepresentation(drawRep);
-        }
-    }
-}
diff --git a/src/com/android/gallery3d/filtershow/editors/EditorZoom.java b/src/com/android/gallery3d/filtershow/editors/EditorZoom.java
deleted file mode 100644
index ea8e3d1..0000000
--- a/src/com/android/gallery3d/filtershow/editors/EditorZoom.java
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * 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.gallery3d.filtershow.editors;
-
-import com.android.gallery3d.R;
-
-public class EditorZoom extends BasicEditor {
-    public static final int ID = R.id.imageZoom;
-
-    public EditorZoom() {
-        super(ID, R.layout.filtershow_zoom_editor,R.id.imageZoom);
-    }
-}
diff --git a/src/com/android/gallery3d/filtershow/editors/ImageOnlyEditor.java b/src/com/android/gallery3d/filtershow/editors/ImageOnlyEditor.java
deleted file mode 100644
index d4e66ed..0000000
--- a/src/com/android/gallery3d/filtershow/editors/ImageOnlyEditor.java
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * 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.gallery3d.filtershow.editors;
-
-import android.content.Context;
-import android.widget.FrameLayout;
-
-import com.android.gallery3d.R;
-import com.android.gallery3d.filtershow.imageshow.ImageShow;
-
-/**
- * The editor with no slider for filters without UI
- */
-public class ImageOnlyEditor extends Editor {
-    public final static int ID = R.id.imageOnlyEditor;
-    private final String LOGTAG = "ImageOnlyEditor";
-
-    public ImageOnlyEditor() {
-        super(ID);
-    }
-
-    protected ImageOnlyEditor(int id) {
-        super(id);
-    }
-
-    public boolean useUtilityPanel() {
-        return false;
-    }
-
-    @Override
-    public void createEditor(Context context, FrameLayout frameLayout) {
-        super.createEditor(context, frameLayout);
-        mView = mImageShow = new ImageShow(context);
-    }
-
-}
diff --git a/src/com/android/gallery3d/filtershow/editors/ParametricEditor.java b/src/com/android/gallery3d/filtershow/editors/ParametricEditor.java
deleted file mode 100644
index 9ec858c..0000000
--- a/src/com/android/gallery3d/filtershow/editors/ParametricEditor.java
+++ /dev/null
@@ -1,206 +0,0 @@
-/*
- * Copyright (C) 2013 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.gallery3d.filtershow.editors;
-
-import android.content.Context;
-import android.graphics.Point;
-import android.util.Log;
-import android.view.View;
-import android.view.ViewGroup;
-import android.view.ViewGroup.LayoutParams;
-import android.view.WindowManager;
-import android.widget.FrameLayout;
-import android.widget.LinearLayout;
-import android.widget.SeekBar;
-
-import com.android.gallery3d.R;
-import com.android.gallery3d.filtershow.controller.ActionSlider;
-import com.android.gallery3d.filtershow.controller.BasicSlider;
-import com.android.gallery3d.filtershow.controller.Control;
-import com.android.gallery3d.filtershow.controller.Parameter;
-import com.android.gallery3d.filtershow.controller.ParameterActionAndInt;
-import com.android.gallery3d.filtershow.controller.ParameterInteger;
-import com.android.gallery3d.filtershow.controller.ParameterStyles;
-import com.android.gallery3d.filtershow.controller.StyleChooser;
-import com.android.gallery3d.filtershow.controller.TitledSlider;
-import com.android.gallery3d.filtershow.filters.FilterBasicRepresentation;
-import com.android.gallery3d.filtershow.filters.FilterRepresentation;
-
-import java.lang.reflect.Constructor;
-import java.util.HashMap;
-
-public class ParametricEditor extends Editor {
-    private int mLayoutID;
-    private int mViewID;
-    public static int ID = R.id.editorParametric;
-    private final String LOGTAG = "ParametricEditor";
-    protected Control mControl;
-    public static final int MINIMUM_WIDTH = 600;
-    public static final int MINIMUM_HEIGHT = 800;
-    View mActionButton;
-    View mEditControl;
-    static HashMap<String, Class> portraitMap = new HashMap<String, Class>();
-    static HashMap<String, Class> landscapeMap = new HashMap<String, Class>();
-    static {
-        portraitMap.put(ParameterInteger.sParameterType, BasicSlider.class);
-        landscapeMap.put(ParameterInteger.sParameterType, TitledSlider.class);
-        portraitMap.put(ParameterActionAndInt.sParameterType, ActionSlider.class);
-        landscapeMap.put(ParameterActionAndInt.sParameterType, ActionSlider.class);
-        portraitMap.put(ParameterStyles.sParameterType, StyleChooser.class);
-        landscapeMap.put(ParameterStyles.sParameterType, StyleChooser.class);
-    }
-
-    static Constructor getConstructor(Class cl) {
-        try {
-            return cl.getConstructor(Context.class, ViewGroup.class);
-        } catch (Exception e) {
-            return null;
-        }
-    }
-
-    public ParametricEditor() {
-        super(ID);
-    }
-
-    protected ParametricEditor(int id) {
-        super(id);
-    }
-
-    protected ParametricEditor(int id, int layoutID, int viewID) {
-        super(id);
-        mLayoutID = layoutID;
-        mViewID = viewID;
-    }
-
-    @Override
-    public String calculateUserMessage(Context context, String effectName, Object parameterValue) {
-        String apply = "";
-
-        if (mShowParameter == SHOW_VALUE_INT & useCompact(context)) {
-           if (getLocalRepresentation() instanceof FilterBasicRepresentation) {
-            FilterBasicRepresentation interval = (FilterBasicRepresentation) getLocalRepresentation();
-                apply += " " + effectName.toUpperCase() + " " + interval.getStateRepresentation();
-           } else {
-                apply += " " + effectName.toUpperCase() + " " + parameterValue;
-           }
-        } else {
-            apply += " " + effectName.toUpperCase();
-        }
-        return apply;
-    }
-
-    @Override
-    public void createEditor(Context context, FrameLayout frameLayout) {
-        super.createEditor(context, frameLayout);
-        unpack(mViewID, mLayoutID);
-    }
-
-    @Override
-    public void reflectCurrentFilter() {
-        super.reflectCurrentFilter();
-        if (getLocalRepresentation() != null
-                && getLocalRepresentation() instanceof FilterBasicRepresentation) {
-            FilterBasicRepresentation interval = (FilterBasicRepresentation) getLocalRepresentation();
-            mControl.setPrameter(interval);
-        }
-    }
-
-    @Override
-    public Control[] getControls() {
-        BasicSlider slider = new BasicSlider();
-        return new Control[] {
-                slider
-        };
-    }
-
-    // TODO: need a better way to decide which representation
-    static boolean useCompact(Context context) {
-        WindowManager w = ((WindowManager) context.getSystemService(Context.WINDOW_SERVICE));
-        Point size = new Point();
-        w.getDefaultDisplay().getSize(size);
-        if (size.x < size.y) { // if tall than wider
-            return true;
-        }
-        if (size.x < MINIMUM_WIDTH) {
-            return true;
-        }
-        if (size.y < MINIMUM_HEIGHT) {
-            return true;
-        }
-        return false;
-    }
-
-    protected Parameter getParameterToEdit(FilterRepresentation rep) {
-        if (this instanceof Parameter) {
-            return (Parameter) this;
-        } else if (rep instanceof Parameter) {
-            return ((Parameter) rep);
-        }
-        return null;
-    }
-
-    @Override
-    public void setUtilityPanelUI(View actionButton, View editControl) {
-        mActionButton = actionButton;
-        mEditControl = editControl;
-        FilterRepresentation rep = getLocalRepresentation();
-        Parameter param = getParameterToEdit(rep);
-        if (param != null) {
-            control(param, editControl);
-        } else {
-            mSeekBar = new SeekBar(editControl.getContext());
-            LayoutParams lp = new LinearLayout.LayoutParams(
-                    LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
-            mSeekBar.setLayoutParams(lp);
-            ((LinearLayout) editControl).addView(mSeekBar);
-            mSeekBar.setOnSeekBarChangeListener(this);
-        }
-    }
-
-    protected void control(Parameter p, View editControl) {
-        String pType = p.getParameterType();
-        Context context = editControl.getContext();
-        Class c = ((useCompact(context)) ? portraitMap : landscapeMap).get(pType);
-
-        if (c != null) {
-            try {
-                mControl = (Control) c.newInstance();
-                p.setController(mControl);
-                mControl.setUp((ViewGroup) editControl, p, this);
-            } catch (Exception e) {
-                Log.e(LOGTAG, "Error in loading Control ", e);
-            }
-        } else {
-            Log.e(LOGTAG, "Unable to find class for " + pType);
-            for (String string : portraitMap.keySet()) {
-                Log.e(LOGTAG, "for " + string + " use " + portraitMap.get(string));
-            }
-        }
-    }
-
-    @Override
-    public void onProgressChanged(SeekBar sbar, int progress, boolean arg2) {
-    }
-
-    @Override
-    public void onStartTrackingTouch(SeekBar arg0) {
-    }
-
-    @Override
-    public void onStopTrackingTouch(SeekBar arg0) {
-    }
-}
diff --git a/src/com/android/gallery3d/filtershow/editors/SwapButton.java b/src/com/android/gallery3d/filtershow/editors/SwapButton.java
deleted file mode 100644
index bb4432e..0000000
--- a/src/com/android/gallery3d/filtershow/editors/SwapButton.java
+++ /dev/null
@@ -1,111 +0,0 @@
-/*
- * Copyright (C) 2013 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.gallery3d.filtershow.editors;
-
-import android.content.Context;
-import android.util.AttributeSet;
-import android.view.GestureDetector;
-import android.view.Menu;
-import android.view.MenuItem;
-import android.view.MotionEvent;
-import android.widget.Button;
-
-public class SwapButton extends Button implements GestureDetector.OnGestureListener {
-
-    public static int ANIM_DURATION = 200;
-
-    public interface SwapButtonListener {
-        public void swapLeft(MenuItem item);
-        public void swapRight(MenuItem item);
-    }
-
-    private GestureDetector mDetector;
-    private SwapButtonListener mListener;
-    private Menu mMenu;
-    private int mCurrentMenuIndex;
-
-    public SwapButton(Context context, AttributeSet attrs) {
-        super(context, attrs);
-        mDetector = new GestureDetector(context, this);
-    }
-
-    public SwapButtonListener getListener() {
-        return mListener;
-    }
-
-    public void setListener(SwapButtonListener listener) {
-        mListener = listener;
-    }
-
-    public boolean onTouchEvent(MotionEvent me) {
-        if (!mDetector.onTouchEvent(me)) {
-            return super.onTouchEvent(me);
-        }
-        return true;
-    }
-
-    @Override
-    public boolean onDown(MotionEvent e) {
-        return true;
-    }
-
-    @Override
-    public void onShowPress(MotionEvent e) {
-    }
-
-    @Override
-    public boolean onSingleTapUp(MotionEvent e) {
-        callOnClick();
-        return true;
-    }
-
-    @Override
-    public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
-        return false;
-    }
-
-    @Override
-    public void onLongPress(MotionEvent e) {
-    }
-
-    @Override
-    public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
-        if (mMenu == null) {
-            return false;
-        }
-        if (e1.getX() - e2.getX() > 0) {
-            // right to left
-            mCurrentMenuIndex++;
-            if (mCurrentMenuIndex == mMenu.size()) {
-                mCurrentMenuIndex = 0;
-            }
-            if (mListener != null) {
-                mListener.swapRight(mMenu.getItem(mCurrentMenuIndex));
-            }
-        } else {
-            // left to right
-            mCurrentMenuIndex--;
-            if (mCurrentMenuIndex < 0) {
-                mCurrentMenuIndex = mMenu.size() - 1;
-            }
-            if (mListener != null) {
-                mListener.swapLeft(mMenu.getItem(mCurrentMenuIndex));
-            }
-        }
-        return true;
-    }
-}
diff --git a/src/com/android/gallery3d/filtershow/filters/BaseFiltersManager.java b/src/com/android/gallery3d/filtershow/filters/BaseFiltersManager.java
deleted file mode 100644
index 3fa9191..0000000
--- a/src/com/android/gallery3d/filtershow/filters/BaseFiltersManager.java
+++ /dev/null
@@ -1,296 +0,0 @@
-/*
- * Copyright (C) 2013 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.gallery3d.filtershow.filters;
-
-import android.content.Context;
-import android.content.res.Resources;
-import android.util.Log;
-
-import com.android.gallery3d.R;
-import com.android.gallery3d.filtershow.editors.EditorCrop;
-import com.android.gallery3d.filtershow.editors.EditorMirror;
-import com.android.gallery3d.filtershow.editors.EditorRotate;
-import com.android.gallery3d.filtershow.editors.EditorStraighten;
-import com.android.gallery3d.filtershow.pipeline.ImagePreset;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.Vector;
-
-public abstract class BaseFiltersManager implements FiltersManagerInterface {
-    protected HashMap<Class, ImageFilter> mFilters = null;
-    protected HashMap<String, FilterRepresentation> mRepresentationLookup = null;
-    private static final String LOGTAG = "BaseFiltersManager";
-
-    protected ArrayList<FilterRepresentation> mLooks = new ArrayList<FilterRepresentation>();
-    protected ArrayList<FilterRepresentation> mBorders = new ArrayList<FilterRepresentation>();
-    protected ArrayList<FilterRepresentation> mTools = new ArrayList<FilterRepresentation>();
-    protected ArrayList<FilterRepresentation> mEffects = new ArrayList<FilterRepresentation>();
-
-    protected void init() {
-        mFilters = new HashMap<Class, ImageFilter>();
-        mRepresentationLookup = new HashMap<String, FilterRepresentation>();
-        Vector<Class> filters = new Vector<Class>();
-        addFilterClasses(filters);
-        for (Class filterClass : filters) {
-            try {
-                Object filterInstance = filterClass.newInstance();
-                if (filterInstance instanceof ImageFilter) {
-                    mFilters.put(filterClass, (ImageFilter) filterInstance);
-
-                    FilterRepresentation rep =
-                        ((ImageFilter) filterInstance).getDefaultRepresentation();
-                    if (rep != null) {
-                        addRepresentation(rep);
-                    }
-                }
-            } catch (InstantiationException e) {
-                e.printStackTrace();
-            } catch (IllegalAccessException e) {
-                e.printStackTrace();
-            }
-        }
-    }
-
-    public void addRepresentation(FilterRepresentation rep) {
-        mRepresentationLookup.put(rep.getSerializationName(), rep);
-    }
-
-    public FilterRepresentation createFilterFromName(String name) {
-        try {
-            return mRepresentationLookup.get(name).copy();
-        } catch (Exception e) {
-            Log.v(LOGTAG, "unable to generate a filter representation for \"" + name + "\"");
-            e.printStackTrace();
-        }
-        return null;
-    }
-
-    public ImageFilter getFilter(Class c) {
-        return mFilters.get(c);
-    }
-
-    @Override
-    public ImageFilter getFilterForRepresentation(FilterRepresentation representation) {
-        return mFilters.get(representation.getFilterClass());
-    }
-
-    public FilterRepresentation getRepresentation(Class c) {
-        ImageFilter filter = mFilters.get(c);
-        if (filter != null) {
-            return filter.getDefaultRepresentation();
-        }
-        return null;
-    }
-
-    public void freeFilterResources(ImagePreset preset) {
-        if (preset == null) {
-            return;
-        }
-        Vector<ImageFilter> usedFilters = preset.getUsedFilters(this);
-        for (Class c : mFilters.keySet()) {
-            ImageFilter filter = mFilters.get(c);
-            if (!usedFilters.contains(filter)) {
-                filter.freeResources();
-            }
-        }
-    }
-
-    public void freeRSFilterScripts() {
-        for (Class c : mFilters.keySet()) {
-            ImageFilter filter = mFilters.get(c);
-            if (filter != null && filter instanceof ImageFilterRS) {
-                ((ImageFilterRS) filter).resetScripts();
-            }
-        }
-    }
-
-    protected void addFilterClasses(Vector<Class> filters) {
-        filters.add(ImageFilterTinyPlanet.class);
-        filters.add(ImageFilterRedEye.class);
-        filters.add(ImageFilterWBalance.class);
-        filters.add(ImageFilterExposure.class);
-        filters.add(ImageFilterVignette.class);
-        filters.add(ImageFilterGrad.class);
-        filters.add(ImageFilterContrast.class);
-        filters.add(ImageFilterShadows.class);
-        filters.add(ImageFilterHighlights.class);
-        filters.add(ImageFilterVibrance.class);
-        filters.add(ImageFilterSharpen.class);
-        filters.add(ImageFilterCurves.class);
-        filters.add(ImageFilterDraw.class);
-        filters.add(ImageFilterHue.class);
-        filters.add(ImageFilterChanSat.class);
-        filters.add(ImageFilterSaturated.class);
-        filters.add(ImageFilterBwFilter.class);
-        filters.add(ImageFilterNegative.class);
-        filters.add(ImageFilterEdge.class);
-        filters.add(ImageFilterKMeans.class);
-        filters.add(ImageFilterFx.class);
-        filters.add(ImageFilterBorder.class);
-        filters.add(ImageFilterParametricBorder.class);
-    }
-
-    public ArrayList<FilterRepresentation> getLooks() {
-        return mLooks;
-    }
-
-    public ArrayList<FilterRepresentation> getBorders() {
-        return mBorders;
-    }
-
-    public ArrayList<FilterRepresentation> getTools() {
-        return mTools;
-    }
-
-    public ArrayList<FilterRepresentation> getEffects() {
-        return mEffects;
-    }
-
-    public void addBorders(Context context) {
-
-    }
-
-    public void addLooks(Context context) {
-        int[] drawid = {
-                R.drawable.filtershow_fx_0005_punch,
-                R.drawable.filtershow_fx_0000_vintage,
-                R.drawable.filtershow_fx_0004_bw_contrast,
-                R.drawable.filtershow_fx_0002_bleach,
-                R.drawable.filtershow_fx_0001_instant,
-                R.drawable.filtershow_fx_0007_washout,
-                R.drawable.filtershow_fx_0003_blue_crush,
-                R.drawable.filtershow_fx_0008_washout_color,
-                R.drawable.filtershow_fx_0006_x_process
-        };
-
-        int[] fxNameid = {
-                R.string.ffx_punch,
-                R.string.ffx_vintage,
-                R.string.ffx_bw_contrast,
-                R.string.ffx_bleach,
-                R.string.ffx_instant,
-                R.string.ffx_washout,
-                R.string.ffx_blue_crush,
-                R.string.ffx_washout_color,
-                R.string.ffx_x_process
-        };
-
-        // Do not localize.
-        String[] serializationNames = {
-                "LUT3D_PUNCH",
-                "LUT3D_VINTAGE",
-                "LUT3D_BW",
-                "LUT3D_BLEACH",
-                "LUT3D_INSTANT",
-                "LUT3D_WASHOUT",
-                "LUT3D_BLUECRUSH",
-                "LUT3D_WASHOUT",
-                "LUT3D_XPROCESS"
-        };
-
-        FilterFxRepresentation nullFx =
-                new FilterFxRepresentation(context.getString(R.string.none),
-                        0, R.string.none);
-        mLooks.add(nullFx);
-
-        for (int i = 0; i < drawid.length; i++) {
-            FilterFxRepresentation fx = new FilterFxRepresentation(
-                    context.getString(fxNameid[i]), drawid[i], fxNameid[i]);
-            fx.setSerializationName(serializationNames[i]);
-            ImagePreset preset = new ImagePreset();
-            preset.addFilter(fx);
-            FilterUserPresetRepresentation rep = new FilterUserPresetRepresentation(
-                    context.getString(fxNameid[i]), preset, -1);
-            mLooks.add(rep);
-            addRepresentation(fx);
-        }
-    }
-
-    public void addEffects() {
-        mEffects.add(getRepresentation(ImageFilterTinyPlanet.class));
-        mEffects.add(getRepresentation(ImageFilterWBalance.class));
-        mEffects.add(getRepresentation(ImageFilterExposure.class));
-        mEffects.add(getRepresentation(ImageFilterVignette.class));
-        mEffects.add(getRepresentation(ImageFilterGrad.class));
-        mEffects.add(getRepresentation(ImageFilterContrast.class));
-        mEffects.add(getRepresentation(ImageFilterShadows.class));
-        mEffects.add(getRepresentation(ImageFilterHighlights.class));
-        mEffects.add(getRepresentation(ImageFilterVibrance.class));
-        mEffects.add(getRepresentation(ImageFilterSharpen.class));
-        mEffects.add(getRepresentation(ImageFilterCurves.class));
-        mEffects.add(getRepresentation(ImageFilterHue.class));
-        mEffects.add(getRepresentation(ImageFilterChanSat.class));
-        mEffects.add(getRepresentation(ImageFilterBwFilter.class));
-        mEffects.add(getRepresentation(ImageFilterNegative.class));
-        mEffects.add(getRepresentation(ImageFilterEdge.class));
-        mEffects.add(getRepresentation(ImageFilterKMeans.class));
-    }
-
-    public void addTools(Context context) {
-
-        int[] editorsId = {
-                EditorCrop.ID,
-                EditorStraighten.ID,
-                EditorRotate.ID,
-                EditorMirror.ID
-        };
-
-        int[] textId = {
-                R.string.crop,
-                R.string.straighten,
-                R.string.rotate,
-                R.string.mirror
-        };
-
-        int[] overlayId = {
-                R.drawable.filtershow_button_geometry_crop,
-                R.drawable.filtershow_button_geometry_straighten,
-                R.drawable.filtershow_button_geometry_rotate,
-                R.drawable.filtershow_button_geometry_flip
-        };
-
-        FilterRepresentation[] geometryFilters = {
-                new FilterCropRepresentation(),
-                new FilterStraightenRepresentation(),
-                new FilterRotateRepresentation(),
-                new FilterMirrorRepresentation()
-        };
-
-        for (int i = 0; i < editorsId.length; i++) {
-            int editorId = editorsId[i];
-            FilterRepresentation geometry = geometryFilters[i];
-            geometry.setEditorId(editorId);
-            geometry.setTextId(textId[i]);
-            geometry.setOverlayId(overlayId[i]);
-            geometry.setOverlayOnly(true);
-            if (geometry.getTextId() != 0) {
-                geometry.setName(context.getString(geometry.getTextId()));
-            }
-            mTools.add(geometry);
-        }
-
-        mTools.add(getRepresentation(ImageFilterRedEye.class));
-        mTools.add(getRepresentation(ImageFilterDraw.class));
-    }
-
-    public void setFilterResources(Resources resources) {
-        ImageFilterBorder filterBorder = (ImageFilterBorder) getFilter(ImageFilterBorder.class);
-        filterBorder.setResources(resources);
-        ImageFilterFx filterFx = (ImageFilterFx) getFilter(ImageFilterFx.class);
-        filterFx.setResources(resources);
-    }
-}
diff --git a/src/com/android/gallery3d/filtershow/filters/ColorSpaceMatrix.java b/src/com/android/gallery3d/filtershow/filters/ColorSpaceMatrix.java
deleted file mode 100644
index 7c307a9..0000000
--- a/src/com/android/gallery3d/filtershow/filters/ColorSpaceMatrix.java
+++ /dev/null
@@ -1,225 +0,0 @@
-/*
- * 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.gallery3d.filtershow.filters;
-
-import java.util.Arrays;
-
-public class ColorSpaceMatrix {
-    private final float[] mMatrix = new float[16];
-    private static final float RLUM = 0.3086f;
-    private static final float GLUM = 0.6094f;
-    private static final float BLUM = 0.0820f;
-
-    public ColorSpaceMatrix() {
-        identity();
-    }
-
-    /**
-     * Copy constructor
-     *
-     * @param matrix
-     */
-    public ColorSpaceMatrix(ColorSpaceMatrix matrix) {
-        System.arraycopy(matrix.mMatrix, 0, mMatrix, 0, matrix.mMatrix.length);
-    }
-
-    /**
-     * get the matrix
-     *
-     * @return the internal matrix
-     */
-    public float[] getMatrix() {
-        return mMatrix;
-    }
-
-    /**
-     * set matrix to identity
-     */
-    public void identity() {
-        Arrays.fill(mMatrix, 0);
-        mMatrix[0] = mMatrix[5] = mMatrix[10] = mMatrix[15] = 1;
-    }
-
-    public void convertToLuminance() {
-        mMatrix[0] = mMatrix[1] = mMatrix[2] = 0.3086f;
-        mMatrix[4] = mMatrix[5] = mMatrix[6] = 0.6094f;
-        mMatrix[8] = mMatrix[9] = mMatrix[10] = 0.0820f;
-    }
-
-    private void multiply(float[] a)
-    {
-        int x, y;
-        float[] temp = new float[16];
-
-        for (y = 0; y < 4; y++) {
-            int y4 = y * 4;
-            for (x = 0; x < 4; x++) {
-                temp[y4 + x] = mMatrix[y4 + 0] * a[x]
-                        + mMatrix[y4 + 1] * a[4 + x]
-                        + mMatrix[y4 + 2] * a[8 + x]
-                        + mMatrix[y4 + 3] * a[12 + x];
-            }
-        }
-        for (int i = 0; i < 16; i++)
-            mMatrix[i] = temp[i];
-    }
-
-    private void xRotateMatrix(float rs, float rc)
-    {
-        ColorSpaceMatrix c = new ColorSpaceMatrix();
-        float[] tmp = c.mMatrix;
-
-        tmp[5] = rc;
-        tmp[6] = rs;
-        tmp[9] = -rs;
-        tmp[10] = rc;
-
-        multiply(tmp);
-    }
-
-    private void yRotateMatrix(float rs, float rc)
-    {
-        ColorSpaceMatrix c = new ColorSpaceMatrix();
-        float[] tmp = c.mMatrix;
-
-        tmp[0] = rc;
-        tmp[2] = -rs;
-        tmp[8] = rs;
-        tmp[10] = rc;
-
-        multiply(tmp);
-    }
-
-    private void zRotateMatrix(float rs, float rc)
-    {
-        ColorSpaceMatrix c = new ColorSpaceMatrix();
-        float[] tmp = c.mMatrix;
-
-        tmp[0] = rc;
-        tmp[1] = rs;
-        tmp[4] = -rs;
-        tmp[5] = rc;
-        multiply(tmp);
-    }
-
-    private void zShearMatrix(float dx, float dy)
-    {
-        ColorSpaceMatrix c = new ColorSpaceMatrix();
-        float[] tmp = c.mMatrix;
-
-        tmp[2] = dx;
-        tmp[6] = dy;
-        multiply(tmp);
-    }
-
-    /**
-     * sets the transform to a shift in Hue
-     *
-     * @param rot rotation in degrees
-     */
-    public void setHue(float rot)
-    {
-        float mag = (float) Math.sqrt(2.0);
-        float xrs = 1 / mag;
-        float xrc = 1 / mag;
-        xRotateMatrix(xrs, xrc);
-        mag = (float) Math.sqrt(3.0);
-        float yrs = -1 / mag;
-        float yrc = (float) Math.sqrt(2.0) / mag;
-        yRotateMatrix(yrs, yrc);
-
-        float lx = getRedf(RLUM, GLUM, BLUM);
-        float ly = getGreenf(RLUM, GLUM, BLUM);
-        float lz = getBluef(RLUM, GLUM, BLUM);
-        float zsx = lx / lz;
-        float zsy = ly / lz;
-        zShearMatrix(zsx, zsy);
-
-        float zrs = (float) Math.sin(rot * Math.PI / 180.0);
-        float zrc = (float) Math.cos(rot * Math.PI / 180.0);
-        zRotateMatrix(zrs, zrc);
-        zShearMatrix(-zsx, -zsy);
-        yRotateMatrix(-yrs, yrc);
-        xRotateMatrix(-xrs, xrc);
-    }
-
-    /**
-     * set it to a saturation matrix
-     *
-     * @param s
-     */
-    public void changeSaturation(float s) {
-        mMatrix[0] = (1 - s) * RLUM + s;
-        mMatrix[1] = (1 - s) * RLUM;
-        mMatrix[2] = (1 - s) * RLUM;
-        mMatrix[4] = (1 - s) * GLUM;
-        mMatrix[5] = (1 - s) * GLUM + s;
-        mMatrix[6] = (1 - s) * GLUM;
-        mMatrix[8] = (1 - s) * BLUM;
-        mMatrix[9] = (1 - s) * BLUM;
-        mMatrix[10] = (1 - s) * BLUM + s;
-    }
-
-    /**
-     * Transform RGB value
-     *
-     * @param r red pixel value
-     * @param g green pixel value
-     * @param b blue pixel value
-     * @return computed red pixel value
-     */
-    public float getRed(int r, int g, int b) {
-        return r * mMatrix[0] + g * mMatrix[4] + b * mMatrix[8] + mMatrix[12];
-    }
-
-    /**
-     * Transform RGB value
-     *
-     * @param r red pixel value
-     * @param g green pixel value
-     * @param b blue pixel value
-     * @return computed green pixel value
-     */
-    public float getGreen(int r, int g, int b) {
-        return r * mMatrix[1] + g * mMatrix[5] + b * mMatrix[9] + mMatrix[13];
-    }
-
-    /**
-     * Transform RGB value
-     *
-     * @param r red pixel value
-     * @param g green pixel value
-     * @param b blue pixel value
-     * @return computed blue pixel value
-     */
-    public float getBlue(int r, int g, int b) {
-        return r * mMatrix[2] + g * mMatrix[6] + b * mMatrix[10] + mMatrix[14];
-    }
-
-    private float getRedf(float r, float g, float b) {
-        return r * mMatrix[0] + g * mMatrix[4] + b * mMatrix[8] + mMatrix[12];
-    }
-
-    private float getGreenf(float r, float g, float b) {
-        return r * mMatrix[1] + g * mMatrix[5] + b * mMatrix[9] + mMatrix[13];
-    }
-
-    private float getBluef(float r, float g, float b) {
-        return r * mMatrix[2] + g * mMatrix[6] + b * mMatrix[10] + mMatrix[14];
-    }
-
-}
diff --git a/src/com/android/gallery3d/filtershow/filters/FilterBasicRepresentation.java b/src/com/android/gallery3d/filtershow/filters/FilterBasicRepresentation.java
deleted file mode 100644
index 1eebdb5..0000000
--- a/src/com/android/gallery3d/filtershow/filters/FilterBasicRepresentation.java
+++ /dev/null
@@ -1,196 +0,0 @@
-/*
- * Copyright (C) 2013 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.gallery3d.filtershow.filters;
-
-
-import android.util.Log;
-
-import com.android.gallery3d.filtershow.controller.Control;
-import com.android.gallery3d.filtershow.controller.FilterView;
-import com.android.gallery3d.filtershow.controller.Parameter;
-import com.android.gallery3d.filtershow.controller.ParameterInteger;
-
-public class FilterBasicRepresentation extends FilterRepresentation implements ParameterInteger {
-    private static final String LOGTAG = "FilterBasicRep";
-    private int mMinimum;
-    private int mValue;
-    private int mMaximum;
-    private int mDefaultValue;
-    private int mPreviewValue;
-    public static final String SERIAL_NAME = "Name";
-    public static final String SERIAL_VALUE = "Value";
-    private boolean mLogVerbose = Log.isLoggable(LOGTAG, Log.VERBOSE);
-
-    public FilterBasicRepresentation(String name, int minimum, int value, int maximum) {
-        super(name);
-        mMinimum = minimum;
-        mMaximum = maximum;
-        setValue(value);
-    }
-
-    @Override
-    public String toString() {
-        return getName() + " : " + mMinimum + " < " + mValue + " < " + mMaximum;
-    }
-
-    @Override
-    public FilterRepresentation copy() {
-        FilterBasicRepresentation representation = new FilterBasicRepresentation(getName(),0,0,0);
-        copyAllParameters(representation);
-        return representation;
-    }
-
-    @Override
-    protected void copyAllParameters(FilterRepresentation representation) {
-        super.copyAllParameters(representation);
-        representation.useParametersFrom(this);
-    }
-
-    @Override
-    public void useParametersFrom(FilterRepresentation a) {
-        if (a instanceof FilterBasicRepresentation) {
-            FilterBasicRepresentation representation = (FilterBasicRepresentation) a;
-            setMinimum(representation.getMinimum());
-            setMaximum(representation.getMaximum());
-            setValue(representation.getValue());
-            setDefaultValue(representation.getDefaultValue());
-            setPreviewValue(representation.getPreviewValue());
-        }
-    }
-
-    @Override
-    public boolean equals(FilterRepresentation representation) {
-        if (!super.equals(representation)) {
-            return false;
-        }
-        if (representation instanceof FilterBasicRepresentation) {
-            FilterBasicRepresentation basic = (FilterBasicRepresentation) representation;
-            if (basic.mMinimum == mMinimum
-                    && basic.mMaximum == mMaximum
-                    && basic.mValue == mValue
-                    && basic.mDefaultValue == mDefaultValue
-                    && basic.mPreviewValue == mPreviewValue) {
-                return true;
-            }
-        }
-        return false;
-    }
-
-    @Override
-    public int getMinimum() {
-        return mMinimum;
-    }
-
-    public void setMinimum(int minimum) {
-        mMinimum = minimum;
-    }
-
-    @Override
-    public int getValue() {
-        return mValue;
-    }
-
-    @Override
-    public void setValue(int value) {
-        mValue = value;
-        if (mValue < mMinimum) {
-            mValue = mMinimum;
-        }
-        if (mValue > mMaximum) {
-            mValue = mMaximum;
-        }
-    }
-
-    @Override
-    public int getMaximum() {
-        return mMaximum;
-    }
-
-    public void setMaximum(int maximum) {
-        mMaximum = maximum;
-    }
-
-    public void setDefaultValue(int defaultValue) {
-        mDefaultValue = defaultValue;
-    }
-
-    @Override
-    public int getDefaultValue() {
-        return mDefaultValue;
-    }
-
-    public int getPreviewValue() {
-        return mPreviewValue;
-    }
-
-    public void setPreviewValue(int previewValue) {
-        mPreviewValue = previewValue;
-    }
-
-    @Override
-    public String getStateRepresentation() {
-        int val = getValue();
-        return ((val > 0) ? "+" : "") + val;
-    }
-
-    @Override
-    public String getParameterType(){
-        return sParameterType;
-    }
-
-    @Override
-    public void setController(Control control) {
-    }
-
-    @Override
-    public String getValueString() {
-        return getStateRepresentation();
-    }
-
-    @Override
-    public String getParameterName() {
-        return getName();
-    }
-
-    @Override
-    public void setFilterView(FilterView editor) {
-    }
-
-    @Override
-    public void copyFrom(Parameter src) {
-        useParametersFrom((FilterBasicRepresentation) src);
-    }
-
-    @Override
-    public String[][] serializeRepresentation() {
-        String[][] ret = {
-                {SERIAL_NAME  , getName() },
-                {SERIAL_VALUE , Integer.toString(mValue)}};
-        return ret;
-    }
-
-    @Override
-    public void deSerializeRepresentation(String[][] rep) {
-        super.deSerializeRepresentation(rep);
-        for (int i = 0; i < rep.length; i++) {
-            if (SERIAL_VALUE.equals(rep[i][0])) {
-                mValue = Integer.parseInt(rep[i][1]);
-                break;
-            }
-        }
-    }
-}
diff --git a/src/com/android/gallery3d/filtershow/filters/FilterChanSatRepresentation.java b/src/com/android/gallery3d/filtershow/filters/FilterChanSatRepresentation.java
deleted file mode 100644
index 7ce67dd..0000000
--- a/src/com/android/gallery3d/filtershow/filters/FilterChanSatRepresentation.java
+++ /dev/null
@@ -1,211 +0,0 @@
-/*
- * Copyright (C) 2013 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.gallery3d.filtershow.filters;
-
-import android.util.JsonReader;
-import android.util.JsonWriter;
-
-import com.android.gallery3d.R;
-import com.android.gallery3d.filtershow.controller.BasicParameterInt;
-import com.android.gallery3d.filtershow.controller.Parameter;
-import com.android.gallery3d.filtershow.controller.ParameterSet;
-import com.android.gallery3d.filtershow.editors.EditorChanSat;
-import com.android.gallery3d.filtershow.imageshow.ControlPoint;
-import com.android.gallery3d.filtershow.imageshow.Spline;
-
-import java.io.IOException;
-import java.util.Vector;
-
-/**
- * Representation for a filter that has per channel & Master saturation
- */
-public class FilterChanSatRepresentation extends FilterRepresentation implements ParameterSet {
-    private static final String LOGTAG = "FilterChanSatRepresentation";
-    private static final String ARGS = "ARGS";
-    private static final String SERIALIZATION_NAME = "channelsaturation";
-
-    public static final int MODE_MASTER = 0;
-    public static final int MODE_RED = 1;
-    public static final int MODE_YELLOW = 2;
-    public static final int MODE_GREEN = 3;
-    public static final int MODE_CYAN = 4;
-    public static final int MODE_BLUE = 5;
-    public static final int MODE_MAGENTA = 6;
-    private int mParameterMode = MODE_MASTER;
-
-    private static int MINSAT = -100;
-    private static int MAXSAT = 100;
-    private BasicParameterInt mParamMaster = new BasicParameterInt(MODE_MASTER, 0, MINSAT, MAXSAT);
-    private BasicParameterInt mParamRed = new BasicParameterInt(MODE_RED, 0, MINSAT, MAXSAT);
-    private BasicParameterInt mParamYellow = new BasicParameterInt(MODE_YELLOW, 0, MINSAT, MAXSAT);
-    private BasicParameterInt mParamGreen = new BasicParameterInt(MODE_GREEN, 0, MINSAT, MAXSAT);
-    private BasicParameterInt mParamCyan = new BasicParameterInt(MODE_CYAN, 0, MINSAT, MAXSAT);
-    private BasicParameterInt mParamBlue = new BasicParameterInt(MODE_BLUE, 0, MINSAT, MAXSAT);
-    private BasicParameterInt mParamMagenta = new BasicParameterInt(MODE_MAGENTA, 0, MINSAT, MAXSAT);
-
-    private BasicParameterInt[] mAllParam = {
-            mParamMaster,
-            mParamRed,
-            mParamYellow,
-            mParamGreen,
-            mParamCyan,
-            mParamBlue,
-            mParamMagenta};
-
-    public FilterChanSatRepresentation() {
-        super("ChannelSaturation");
-        setTextId(R.string.saturation);
-        setFilterType(FilterRepresentation.TYPE_NORMAL);
-        setSerializationName(SERIALIZATION_NAME);
-        setFilterClass(ImageFilterChanSat.class);
-        setEditorId(EditorChanSat.ID);
-    }
-
-    public String toString() {
-        return getName() + " : " + mParamRed + ", " + mParamCyan + ", " + mParamRed
-                + ", " + mParamGreen + ", " + mParamMaster + ", " + mParamYellow;
-    }
-
-    @Override
-    public FilterRepresentation copy() {
-        FilterChanSatRepresentation representation = new FilterChanSatRepresentation();
-        copyAllParameters(representation);
-        return representation;
-    }
-
-    @Override
-    protected void copyAllParameters(FilterRepresentation representation) {
-        super.copyAllParameters(representation);
-        representation.useParametersFrom(this);
-    }
-
-    public void useParametersFrom(FilterRepresentation a) {
-        if (a instanceof FilterChanSatRepresentation) {
-            FilterChanSatRepresentation representation = (FilterChanSatRepresentation) a;
-
-            for (int i = 0; i < mAllParam.length; i++) {
-                mAllParam[i].copyFrom(representation.mAllParam[i]);
-            }
-        }
-    }
-
-    @Override
-    public boolean equals(FilterRepresentation representation) {
-        if (!super.equals(representation)) {
-            return false;
-        }
-        if (representation instanceof FilterChanSatRepresentation) {
-            FilterChanSatRepresentation rep = (FilterChanSatRepresentation) representation;
-            for (int i = 0; i < mAllParam.length; i++) {
-                if (rep.getValue(i) != getValue(i))
-                    return false;
-            }
-            return true;
-        }
-        return false;
-    }
-
-    public int getValue(int mode) {
-        return mAllParam[mode].getValue();
-    }
-
-    public void setValue(int mode, int value) {
-        mAllParam[mode].setValue(value);
-    }
-
-    public int getMinimum() {
-        return mParamMaster.getMinimum();
-    }
-
-    public int getMaximum() {
-        return mParamMaster.getMaximum();
-    }
-
-    public int getParameterMode() {
-        return mParameterMode;
-    }
-
-    public void setParameterMode(int parameterMode) {
-        mParameterMode = parameterMode;
-    }
-
-    public int getCurrentParameter() {
-        return getValue(mParameterMode);
-    }
-
-    public void setCurrentParameter(int value) {
-        setValue(mParameterMode, value);
-    }
-
-    @Override
-    public int getNumberOfParameters() {
-        return 6;
-    }
-
-    @Override
-    public Parameter getFilterParameter(int index) {
-        return mAllParam[index];
-    }
-
-    @Override
-    public void serializeRepresentation(JsonWriter writer) throws IOException {
-        writer.beginObject();
-
-        writer.name(ARGS);
-        writer.beginArray();
-        writer.value(getValue(MODE_MASTER));
-        writer.value(getValue(MODE_RED));
-        writer.value(getValue(MODE_YELLOW));
-        writer.value(getValue(MODE_GREEN));
-        writer.value(getValue(MODE_CYAN));
-        writer.value(getValue(MODE_BLUE));
-        writer.value(getValue(MODE_MAGENTA));
-        writer.endArray();
-        writer.endObject();
-    }
-
-    @Override
-    public void deSerializeRepresentation(JsonReader sreader) throws IOException {
-        sreader.beginObject();
-
-        while (sreader.hasNext()) {
-            String name = sreader.nextName();
-            if (name.startsWith(ARGS)) {
-                sreader.beginArray();
-                sreader.hasNext();
-                setValue(MODE_MASTER, sreader.nextInt());
-                sreader.hasNext();
-                setValue(MODE_RED, sreader.nextInt());
-                sreader.hasNext();
-                setValue(MODE_YELLOW, sreader.nextInt());
-                sreader.hasNext();
-                setValue(MODE_GREEN, sreader.nextInt());
-                sreader.hasNext();
-                setValue(MODE_CYAN, sreader.nextInt());
-                sreader.hasNext();
-                setValue(MODE_BLUE, sreader.nextInt());
-                sreader.hasNext();
-                setValue(MODE_MAGENTA, sreader.nextInt());
-                sreader.hasNext();
-                sreader.endArray();
-            } else {
-                sreader.skipValue();
-            }
-        }
-        sreader.endObject();
-    }
-}
\ No newline at end of file
diff --git a/src/com/android/gallery3d/filtershow/filters/FilterColorBorderRepresentation.java b/src/com/android/gallery3d/filtershow/filters/FilterColorBorderRepresentation.java
deleted file mode 100644
index 94eb206..0000000
--- a/src/com/android/gallery3d/filtershow/filters/FilterColorBorderRepresentation.java
+++ /dev/null
@@ -1,113 +0,0 @@
-/*
- * Copyright (C) 2013 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.gallery3d.filtershow.filters;
-
-import com.android.gallery3d.R;
-import com.android.gallery3d.filtershow.editors.ImageOnlyEditor;
-
-public class FilterColorBorderRepresentation extends FilterRepresentation {
-    private int mColor;
-    private int mBorderSize;
-    private int mBorderRadius;
-
-    public FilterColorBorderRepresentation(int color, int size, int radius) {
-        super("ColorBorder");
-        mColor = color;
-        mBorderSize = size;
-        mBorderRadius = radius;
-        setFilterType(FilterRepresentation.TYPE_BORDER);
-        setTextId(R.string.borders);
-        setEditorId(ImageOnlyEditor.ID);
-        setShowParameterValue(false);
-    }
-
-    public String toString() {
-        return "FilterBorder: " + getName();
-    }
-
-    @Override
-    public FilterRepresentation copy() {
-        FilterColorBorderRepresentation representation = new FilterColorBorderRepresentation(0,0,0);
-        copyAllParameters(representation);
-        return representation;
-    }
-
-    @Override
-    protected void copyAllParameters(FilterRepresentation representation) {
-        super.copyAllParameters(representation);
-        representation.useParametersFrom(this);
-    }
-
-    public void useParametersFrom(FilterRepresentation a) {
-        if (a instanceof FilterColorBorderRepresentation) {
-            FilterColorBorderRepresentation representation = (FilterColorBorderRepresentation) a;
-            setName(representation.getName());
-            setColor(representation.getColor());
-            setBorderSize(representation.getBorderSize());
-            setBorderRadius(representation.getBorderRadius());
-        }
-    }
-
-    @Override
-    public boolean equals(FilterRepresentation representation) {
-        if (!super.equals(representation)) {
-            return false;
-        }
-        if (representation instanceof FilterColorBorderRepresentation) {
-            FilterColorBorderRepresentation border = (FilterColorBorderRepresentation) representation;
-            if (border.mColor == mColor
-                    && border.mBorderSize == mBorderSize
-                    && border.mBorderRadius == mBorderRadius) {
-                return true;
-            }
-        }
-        return false;
-    }
-
-    public boolean allowsSingleInstanceOnly() {
-        return true;
-    }
-
-    @Override
-    public int getTextId() {
-        return R.string.borders;
-    }
-
-    public int getColor() {
-        return mColor;
-    }
-
-    public void setColor(int color) {
-        mColor = color;
-    }
-
-    public int getBorderSize() {
-        return mBorderSize;
-    }
-
-    public void setBorderSize(int borderSize) {
-        mBorderSize = borderSize;
-    }
-
-    public int getBorderRadius() {
-        return mBorderRadius;
-    }
-
-    public void setBorderRadius(int borderRadius) {
-        mBorderRadius = borderRadius;
-    }
-}
diff --git a/src/com/android/gallery3d/filtershow/filters/FilterCropRepresentation.java b/src/com/android/gallery3d/filtershow/filters/FilterCropRepresentation.java
deleted file mode 100644
index c1bd7b3..0000000
--- a/src/com/android/gallery3d/filtershow/filters/FilterCropRepresentation.java
+++ /dev/null
@@ -1,179 +0,0 @@
-/*
- * Copyright (C) 2013 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.gallery3d.filtershow.filters;
-
-import android.graphics.RectF;
-import android.util.JsonReader;
-import android.util.JsonWriter;
-
-import com.android.gallery3d.R;
-import com.android.gallery3d.filtershow.editors.EditorCrop;
-
-import java.io.IOException;
-
-public class FilterCropRepresentation extends FilterRepresentation {
-    public static final String SERIALIZATION_NAME = "CROP";
-    public static final String[] BOUNDS = {
-            "C0", "C1", "C2", "C3"
-    };
-    private static final String TAG = FilterCropRepresentation.class.getSimpleName();
-
-    RectF mCrop = getNil();
-
-    public FilterCropRepresentation(RectF crop) {
-        super(FilterCropRepresentation.class.getSimpleName());
-        setSerializationName(SERIALIZATION_NAME);
-        setShowParameterValue(true);
-        setFilterClass(FilterCropRepresentation.class);
-        setFilterType(FilterRepresentation.TYPE_GEOMETRY);
-        setTextId(R.string.crop);
-        setEditorId(EditorCrop.ID);
-        setCrop(crop);
-    }
-
-    public FilterCropRepresentation(FilterCropRepresentation m) {
-        this(m.mCrop);
-    }
-
-    public FilterCropRepresentation() {
-        this(sNilRect);
-    }
-
-    public void set(FilterCropRepresentation r) {
-        mCrop.set(r.mCrop);
-    }
-
-    @Override
-    public boolean equals(FilterRepresentation rep) {
-        if (!(rep instanceof FilterCropRepresentation)) {
-            return false;
-        }
-        FilterCropRepresentation crop = (FilterCropRepresentation) rep;
-        if (mCrop.bottom != crop.mCrop.bottom
-            || mCrop.left != crop.mCrop.left
-            || mCrop.right != crop.mCrop.right
-            || mCrop.top != crop.mCrop.top) {
-            return false;
-        }
-        return true;
-    }
-
-    public RectF getCrop() {
-        return new RectF(mCrop);
-    }
-
-    public void getCrop(RectF r) {
-        r.set(mCrop);
-    }
-
-    public void setCrop(RectF crop) {
-        if (crop == null) {
-            throw new IllegalArgumentException("Argument to setCrop is null");
-        }
-        mCrop.set(crop);
-    }
-
-    /**
-     * Takes a crop rect contained by [0, 0, 1, 1] and scales it by the height
-     * and width of the image rect.
-     */
-    public static void findScaledCrop(RectF crop, int bitmapWidth, int bitmapHeight) {
-        crop.left *= bitmapWidth;
-        crop.top *= bitmapHeight;
-        crop.right *= bitmapWidth;
-        crop.bottom *= bitmapHeight;
-    }
-
-    /**
-     * Takes crop rect and normalizes it by scaling down by the height and width
-     * of the image rect.
-     */
-    public static void findNormalizedCrop(RectF crop, int bitmapWidth, int bitmapHeight) {
-        crop.left /= bitmapWidth;
-        crop.top /= bitmapHeight;
-        crop.right /= bitmapWidth;
-        crop.bottom /= bitmapHeight;
-    }
-
-    @Override
-    public boolean allowsSingleInstanceOnly() {
-        return true;
-    }
-
-    @Override
-    public FilterRepresentation copy() {
-        return new FilterCropRepresentation(this);
-    }
-
-    @Override
-    protected void copyAllParameters(FilterRepresentation representation) {
-        if (!(representation instanceof FilterCropRepresentation)) {
-            throw new IllegalArgumentException("calling copyAllParameters with incompatible types!");
-        }
-        super.copyAllParameters(representation);
-        representation.useParametersFrom(this);
-    }
-
-    @Override
-    public void useParametersFrom(FilterRepresentation a) {
-        if (!(a instanceof FilterCropRepresentation)) {
-            throw new IllegalArgumentException("calling useParametersFrom with incompatible types!");
-        }
-        setCrop(((FilterCropRepresentation) a).mCrop);
-    }
-
-    private static final RectF sNilRect = new RectF(0, 0, 1, 1);
-
-    @Override
-    public boolean isNil() {
-        return mCrop.equals(sNilRect);
-    }
-
-    public static RectF getNil() {
-        return new RectF(sNilRect);
-    }
-
-    @Override
-    public void serializeRepresentation(JsonWriter writer) throws IOException {
-        writer.beginObject();
-        writer.name(BOUNDS[0]).value(mCrop.left);
-        writer.name(BOUNDS[1]).value(mCrop.top);
-        writer.name(BOUNDS[2]).value(mCrop.right);
-        writer.name(BOUNDS[3]).value(mCrop.bottom);
-        writer.endObject();
-    }
-
-    @Override
-    public void deSerializeRepresentation(JsonReader reader) throws IOException {
-        reader.beginObject();
-        while (reader.hasNext()) {
-            String name = reader.nextName();
-            if (BOUNDS[0].equals(name)) {
-                mCrop.left = (float) reader.nextDouble();
-            } else if (BOUNDS[1].equals(name)) {
-                mCrop.top = (float) reader.nextDouble();
-            } else if (BOUNDS[2].equals(name)) {
-                mCrop.right = (float) reader.nextDouble();
-            } else if (BOUNDS[3].equals(name)) {
-                mCrop.bottom = (float) reader.nextDouble();
-            } else {
-                reader.skipValue();
-            }
-        }
-        reader.endObject();
-    }
-}
diff --git a/src/com/android/gallery3d/filtershow/filters/FilterCurvesRepresentation.java b/src/com/android/gallery3d/filtershow/filters/FilterCurvesRepresentation.java
deleted file mode 100644
index edab2a0..0000000
--- a/src/com/android/gallery3d/filtershow/filters/FilterCurvesRepresentation.java
+++ /dev/null
@@ -1,170 +0,0 @@
-package com.android.gallery3d.filtershow.filters;
-
-import android.util.JsonReader;
-import android.util.JsonWriter;
-import android.util.Log;
-
-import com.android.gallery3d.R;
-import com.android.gallery3d.filtershow.imageshow.ControlPoint;
-import com.android.gallery3d.filtershow.imageshow.Spline;
-
-import java.io.IOException;
-
-/**
- * TODO: Insert description here. (generated by hoford)
- */
-public class FilterCurvesRepresentation extends FilterRepresentation {
-    private static final String LOGTAG = "FilterCurvesRepresentation";
-    public static final String SERIALIZATION_NAME = "Curve";
-    private static final int MAX_SPLINE_NUMBER = 4;
-
-    private Spline[] mSplines = new Spline[MAX_SPLINE_NUMBER];
-
-    public FilterCurvesRepresentation() {
-        super("Curves");
-        setSerializationName("CURVES");
-        setFilterClass(ImageFilterCurves.class);
-        setTextId(R.string.curvesRGB);
-        setOverlayId(R.drawable.filtershow_button_colors_curve);
-        setEditorId(R.id.imageCurves);
-        setShowParameterValue(false);
-        setSupportsPartialRendering(true);
-        reset();
-    }
-
-    @Override
-    public FilterRepresentation copy() {
-        FilterCurvesRepresentation representation = new FilterCurvesRepresentation();
-        copyAllParameters(representation);
-        return representation;
-    }
-
-    @Override
-    protected void copyAllParameters(FilterRepresentation representation) {
-        super.copyAllParameters(representation);
-        representation.useParametersFrom(this);
-    }
-
-    @Override
-    public void useParametersFrom(FilterRepresentation a) {
-        if (!(a instanceof FilterCurvesRepresentation)) {
-            Log.v(LOGTAG, "cannot use parameters from " + a);
-            return;
-        }
-        FilterCurvesRepresentation representation = (FilterCurvesRepresentation) a;
-        Spline[] spline = new Spline[MAX_SPLINE_NUMBER];
-        for (int i = 0; i < spline.length; i++) {
-            Spline sp = representation.mSplines[i];
-            if (sp != null) {
-                spline[i] = new Spline(sp);
-            } else {
-                spline[i] = new Spline();
-            }
-        }
-        mSplines = spline;
-    }
-
-    @Override
-    public boolean isNil() {
-        for (int i = 0; i < MAX_SPLINE_NUMBER; i++) {
-            if (getSpline(i) != null && !getSpline(i).isOriginal()) {
-                return false;
-            }
-        }
-        return true;
-    }
-
-    @Override
-    public boolean equals(FilterRepresentation representation) {
-        if (!super.equals(representation)) {
-            return false;
-        }
-
-        if (!(representation instanceof FilterCurvesRepresentation)) {
-            return false;
-        } else {
-            FilterCurvesRepresentation curve =
-                    (FilterCurvesRepresentation) representation;
-            for (int i = 0; i < MAX_SPLINE_NUMBER; i++) {
-                if (!getSpline(i).sameValues(curve.getSpline(i))) {
-                    return false;
-                }
-            }
-        }
-        // Every spline matches, therefore they are the same.
-        return true;
-    }
-
-    public void reset() {
-        Spline spline = new Spline();
-
-        spline.addPoint(0.0f, 1.0f);
-        spline.addPoint(1.0f, 0.0f);
-
-        for (int i = 0; i < MAX_SPLINE_NUMBER; i++) {
-            mSplines[i] = new Spline(spline);
-        }
-    }
-
-    public void setSpline(int splineIndex, Spline s) {
-        mSplines[splineIndex] = s;
-    }
-
-    public Spline getSpline(int splineIndex) {
-        return mSplines[splineIndex];
-    }
-
-    @Override
-    public void serializeRepresentation(JsonWriter writer) throws IOException {
-        writer.beginObject();
-        {
-            writer.name(NAME_TAG);
-            writer.value(getName());
-            for (int i = 0; i < mSplines.length; i++) {
-                writer.name(SERIALIZATION_NAME + i);
-                writer.beginArray();
-                int nop = mSplines[i].getNbPoints();
-                for (int j = 0; j < nop; j++) {
-                    ControlPoint p = mSplines[i].getPoint(j);
-                    writer.beginArray();
-                    writer.value(p.x);
-                    writer.value(p.y);
-                    writer.endArray();
-                }
-                writer.endArray();
-            }
-
-        }
-        writer.endObject();
-    }
-
-    @Override
-    public void deSerializeRepresentation(JsonReader sreader) throws IOException {
-        sreader.beginObject();
-        Spline[] spline = new Spline[MAX_SPLINE_NUMBER];
-        while (sreader.hasNext()) {
-            String name = sreader.nextName();
-            if (NAME_TAG.equals(name)) {
-                setName(sreader.nextString());
-            } else if (name.startsWith(SERIALIZATION_NAME)) {
-                int curveNo = Integer.parseInt(name.substring(SERIALIZATION_NAME.length()));
-                spline[curveNo] = new Spline();
-                sreader.beginArray();
-                while (sreader.hasNext()) {
-                    sreader.beginArray();
-                    sreader.hasNext();
-                    float x = (float) sreader.nextDouble();
-                    sreader.hasNext();
-                    float y = (float) sreader.nextDouble();
-                    sreader.endArray();
-                    spline[curveNo].addPoint(x, y);
-                }
-                sreader.endArray();
-
-            }
-        }
-        mSplines = spline;
-        sreader.endObject();
-    }
-
-}
diff --git a/src/com/android/gallery3d/filtershow/filters/FilterDirectRepresentation.java b/src/com/android/gallery3d/filtershow/filters/FilterDirectRepresentation.java
deleted file mode 100644
index ac0cb74..0000000
--- a/src/com/android/gallery3d/filtershow/filters/FilterDirectRepresentation.java
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright (C) 2013 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.gallery3d.filtershow.filters;
-
-public class FilterDirectRepresentation extends FilterRepresentation {
-
-    @Override
-    public FilterRepresentation copy() {
-        FilterDirectRepresentation representation = new FilterDirectRepresentation(getName());
-        copyAllParameters(representation);
-        return representation;
-    }
-
-    @Override
-    protected void copyAllParameters(FilterRepresentation representation) {
-        super.copyAllParameters(representation);
-        representation.useParametersFrom(this);
-    }
-
-    public FilterDirectRepresentation(String name) {
-        super(name);
-    }
-
-}
diff --git a/src/com/android/gallery3d/filtershow/filters/FilterDrawRepresentation.java b/src/com/android/gallery3d/filtershow/filters/FilterDrawRepresentation.java
deleted file mode 100644
index 977dbea..0000000
--- a/src/com/android/gallery3d/filtershow/filters/FilterDrawRepresentation.java
+++ /dev/null
@@ -1,171 +0,0 @@
-/*
- * Copyright (C) 2013 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.gallery3d.filtershow.filters;
-
-import android.graphics.Path;
-import android.util.Log;
-
-import com.android.gallery3d.R;
-import com.android.gallery3d.filtershow.editors.EditorDraw;
-
-import java.util.Vector;
-
-public class FilterDrawRepresentation extends FilterRepresentation {
-    private static final String LOGTAG = "FilterDrawRepresentation";
-
-    public static class StrokeData implements Cloneable {
-        public byte mType;
-        public Path mPath;
-        public float mRadius;
-        public int mColor;
-        public int noPoints = 0;
-        @Override
-        public String toString() {
-            return "stroke(" + mType + ", path(" + (mPath) + "), " + mRadius + " , "
-                    + Integer.toHexString(mColor) + ")";
-        }
-        @Override
-        public StrokeData clone() throws CloneNotSupportedException {
-            return (StrokeData) super.clone();
-        }
-    }
-
-    private Vector<StrokeData> mDrawing = new Vector<StrokeData>();
-    private StrokeData mCurrent; // used in the currently drawing style
-
-    public FilterDrawRepresentation() {
-        super("Draw");
-        setFilterClass(ImageFilterDraw.class);
-        setSerializationName("DRAW");
-        setFilterType(FilterRepresentation.TYPE_VIGNETTE);
-        setTextId(R.string.imageDraw);
-        setEditorId(EditorDraw.ID);
-        setOverlayId(R.drawable.filtershow_drawing);
-        setOverlayOnly(true);
-    }
-
-    @Override
-    public String toString() {
-        return getName() + " : strokes=" + mDrawing.size()
-                + ((mCurrent == null) ? " no current "
-                        : ("draw=" + mCurrent.mType + " " + mCurrent.noPoints));
-    }
-
-    public Vector<StrokeData> getDrawing() {
-        return mDrawing;
-    }
-
-    public StrokeData getCurrentDrawing() {
-        return mCurrent;
-    }
-
-    @Override
-    public FilterRepresentation copy() {
-        FilterDrawRepresentation representation = new FilterDrawRepresentation();
-        copyAllParameters(representation);
-        return representation;
-    }
-
-    @Override
-    protected void copyAllParameters(FilterRepresentation representation) {
-        super.copyAllParameters(representation);
-        representation.useParametersFrom(this);
-    }
-
-    @Override
-    public boolean isNil() {
-        return getDrawing().isEmpty();
-    }
-
-    @Override
-    public void useParametersFrom(FilterRepresentation a) {
-        if (a instanceof FilterDrawRepresentation) {
-            FilterDrawRepresentation representation = (FilterDrawRepresentation) a;
-            try {
-                if (representation.mCurrent != null) {
-                    mCurrent = (StrokeData) representation.mCurrent.clone();
-                } else {
-                    mCurrent = null;
-                }
-                if (representation.mDrawing != null) {
-                    mDrawing = (Vector<StrokeData>) representation.mDrawing.clone();
-                } else {
-                    mDrawing = null;
-                }
-
-            } catch (CloneNotSupportedException e) {
-                e.printStackTrace();
-            }
-        } else {
-            Log.v(LOGTAG, "cannot use parameters from " + a);
-        }
-    }
-
-    @Override
-    public boolean equals(FilterRepresentation representation) {
-        if (!super.equals(representation)) {
-            return false;
-        }
-        if (representation instanceof FilterDrawRepresentation) {
-            FilterDrawRepresentation fdRep = (FilterDrawRepresentation) representation;
-            if (fdRep.mDrawing.size() != mDrawing.size())
-                return false;
-            if (fdRep.mCurrent == null && mCurrent.mPath == null) {
-                return true;
-            }
-            if (fdRep.mCurrent != null && mCurrent.mPath != null) {
-                if (fdRep.mCurrent.noPoints == mCurrent.noPoints) {
-                    return true;
-                }
-                return false;
-            }
-        }
-        return false;
-    }
-
-    public void startNewSection(byte type, int color, float size, float x, float y) {
-        mCurrent = new StrokeData();
-        mCurrent.mColor = color;
-        mCurrent.mRadius = size;
-        mCurrent.mType = type;
-        mCurrent.mPath = new Path();
-        mCurrent.mPath.moveTo(x, y);
-        mCurrent.noPoints = 0;
-    }
-
-    public void addPoint(float x, float y) {
-        mCurrent.noPoints++;
-        mCurrent.mPath.lineTo(x, y);
-    }
-
-    public void endSection(float x, float y) {
-        mCurrent.mPath.lineTo(x, y);
-        mCurrent.noPoints++;
-        mDrawing.add(mCurrent);
-        mCurrent = null;
-    }
-
-    public void clearCurrentSection() {
-        mCurrent = null;
-    }
-
-    public void clear() {
-        mCurrent = null;
-        mDrawing.clear();
-    }
-
-}
diff --git a/src/com/android/gallery3d/filtershow/filters/FilterFxRepresentation.java b/src/com/android/gallery3d/filtershow/filters/FilterFxRepresentation.java
deleted file mode 100644
index e5a6fdd..0000000
--- a/src/com/android/gallery3d/filtershow/filters/FilterFxRepresentation.java
+++ /dev/null
@@ -1,112 +0,0 @@
-/*
- * Copyright (C) 2013 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.gallery3d.filtershow.filters;
-
-import com.android.gallery3d.filtershow.editors.ImageOnlyEditor;
-
-public class FilterFxRepresentation extends FilterRepresentation {
-   private static final String LOGTAG = "FilterFxRepresentation";
-    // TODO: When implementing serialization, we should find a unique way of
-    // specifying bitmaps / names (the resource IDs being random)
-    private int mBitmapResource = 0;
-    private int mNameResource = 0;
-
-    public FilterFxRepresentation(String name, int bitmapResource, int nameResource) {
-        super(name);
-        setFilterClass(ImageFilterFx.class);
-        mBitmapResource = bitmapResource;
-        mNameResource = nameResource;
-        setFilterType(FilterRepresentation.TYPE_FX);
-        setTextId(nameResource);
-        setEditorId(ImageOnlyEditor.ID);
-        setShowParameterValue(false);
-        setSupportsPartialRendering(true);
-    }
-
-    @Override
-    public String toString() {
-        return "FilterFx: " + hashCode() + " : " + getName() + " bitmap rsc: " + mBitmapResource;
-    }
-
-    @Override
-    public FilterRepresentation copy() {
-        FilterFxRepresentation representation = new FilterFxRepresentation(getName(),0,0);
-        copyAllParameters(representation);
-        return representation;
-    }
-
-    @Override
-    protected void copyAllParameters(FilterRepresentation representation) {
-        super.copyAllParameters(representation);
-        representation.useParametersFrom(this);
-    }
-
-    @Override
-    public synchronized void useParametersFrom(FilterRepresentation a) {
-        if (a instanceof FilterFxRepresentation) {
-            FilterFxRepresentation representation = (FilterFxRepresentation) a;
-            setName(representation.getName());
-            setSerializationName(representation.getSerializationName());
-            setBitmapResource(representation.getBitmapResource());
-            setNameResource(representation.getNameResource());
-        }
-    }
-
-    @Override
-    public boolean equals(FilterRepresentation representation) {
-        if (!super.equals(representation)) {
-            return false;
-        }
-        if (representation instanceof FilterFxRepresentation) {
-            FilterFxRepresentation fx = (FilterFxRepresentation) representation;
-            if (fx.mNameResource == mNameResource
-                    && fx.mBitmapResource == mBitmapResource) {
-                return true;
-            }
-        }
-        return false;
-    }
-
-    @Override
-    public boolean same(FilterRepresentation representation) {
-        if (!super.same(representation)) {
-            return false;
-        }
-        return equals(representation);
-    }
-
-    @Override
-    public boolean allowsSingleInstanceOnly() {
-        return true;
-    }
-
-    public int getNameResource() {
-        return mNameResource;
-    }
-
-    public void setNameResource(int nameResource) {
-        mNameResource = nameResource;
-    }
-
-    public int getBitmapResource() {
-        return mBitmapResource;
-    }
-
-    public void setBitmapResource(int bitmapResource) {
-        mBitmapResource = bitmapResource;
-    }
-}
diff --git a/src/com/android/gallery3d/filtershow/filters/FilterGradRepresentation.java b/src/com/android/gallery3d/filtershow/filters/FilterGradRepresentation.java
deleted file mode 100644
index 0c272d4..0000000
--- a/src/com/android/gallery3d/filtershow/filters/FilterGradRepresentation.java
+++ /dev/null
@@ -1,497 +0,0 @@
-/*
- * Copyright (C) 2013 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.gallery3d.filtershow.filters;
-
-import android.graphics.Rect;
-import android.util.JsonReader;
-import android.util.JsonWriter;
-
-import com.android.gallery3d.R;
-import com.android.gallery3d.filtershow.editors.EditorGrad;
-import com.android.gallery3d.filtershow.imageshow.MasterImage;
-import com.android.gallery3d.filtershow.imageshow.Line;
-
-import java.io.IOException;
-import java.util.Vector;
-
-public class FilterGradRepresentation extends FilterRepresentation
-        implements Line {
-    private static final String LOGTAG = "FilterGradRepresentation";
-    public static final int MAX_POINTS = 16;
-    public static final int PARAM_BRIGHTNESS = 0;
-    public static final int PARAM_SATURATION = 1;
-    public static final int PARAM_CONTRAST = 2;
-    private static final double ADD_MIN_DIST = .05;
-    private static String LINE_NAME = "Point";
-    private static final  String SERIALIZATION_NAME = "grad";
-
-    public FilterGradRepresentation() {
-        super("Grad");
-        setSerializationName(SERIALIZATION_NAME);
-        creatExample();
-        setOverlayId(R.drawable.filtershow_button_grad);
-        setFilterClass(ImageFilterGrad.class);
-        setTextId(R.string.grad);
-        setEditorId(EditorGrad.ID);
-    }
-
-    public void trimVector(){
-        int n = mBands.size();
-        for (int i = n; i < MAX_POINTS; i++) {
-            mBands.add(new Band());
-        }
-        for (int i = MAX_POINTS; i <  n; i++) {
-            mBands.remove(i);
-        }
-    }
-
-    Vector<Band> mBands = new Vector<Band>();
-    Band mCurrentBand;
-
-    static class Band {
-        private boolean mask = true;
-
-        private int xPos1 = -1;
-        private int yPos1 = 100;
-        private int xPos2 = -1;
-        private int yPos2 = 100;
-        private int brightness = 40;
-        private int contrast = 0;
-        private int saturation = 0;
-
-
-        public Band() {
-        }
-
-        public Band(int x, int y) {
-            xPos1 = x;
-            yPos1 = y+30;
-            xPos2 = x;
-            yPos2 = y-30;
-        }
-
-        public Band(Band copy) {
-            mask = copy.mask;
-            xPos1 = copy.xPos1;
-            yPos1 = copy.yPos1;
-            xPos2 = copy.xPos2;
-            yPos2 = copy.yPos2;
-            brightness = copy.brightness;
-            contrast = copy.contrast;
-            saturation = copy.saturation;
-        }
-
-    }
-
-    @Override
-    public String toString() {
-        int count = 0;
-        for (Band point : mBands) {
-            if (!point.mask) {
-                count++;
-            }
-        }
-        return "c=" + mBands.indexOf(mBands) + "[" + mBands.size() + "]" + count;
-    }
-
-    private void creatExample() {
-        Band p = new Band();
-        p.mask = false;
-        p.xPos1 = -1;
-        p.yPos1 = 100;
-        p.xPos2 = -1;
-        p.yPos2 = 100;
-        p.brightness = 40;
-        p.contrast = 0;
-        p.saturation = 0;
-        mBands.add(0, p);
-        mCurrentBand = p;
-        trimVector();
-    }
-
-    @Override
-    public void useParametersFrom(FilterRepresentation a) {
-            FilterGradRepresentation rep = (FilterGradRepresentation) a;
-            Vector<Band> tmpBands = new Vector<Band>();
-            int n = (rep.mCurrentBand == null) ? 0 : rep.mBands.indexOf(rep.mCurrentBand);
-            for (Band band : rep.mBands) {
-                tmpBands.add(new Band(band));
-            }
-            mCurrentBand = null;
-            mBands = tmpBands;
-            mCurrentBand = mBands.elementAt(n);
-    }
-
-    @Override
-    public FilterRepresentation copy() {
-        FilterGradRepresentation representation = new FilterGradRepresentation();
-        copyAllParameters(representation);
-        return representation;
-    }
-
-    @Override
-    protected void copyAllParameters(FilterRepresentation representation) {
-        super.copyAllParameters(representation);
-        representation.useParametersFrom(this);
-    }
-
-    @Override
-    public boolean equals(FilterRepresentation representation) {
-        if (representation instanceof FilterGradRepresentation) {
-            FilterGradRepresentation rep = (FilterGradRepresentation) representation;
-            int n = getNumberOfBands();
-            if (rep.getNumberOfBands() != n) {
-                return false;
-            }
-            for (int i = 0; i < mBands.size(); i++) {
-                Band b1 = mBands.get(i);
-                Band b2 = rep.mBands.get(i);
-                if (b1.mask != b2.mask
-                        || b1.brightness != b2.brightness
-                        || b1.contrast != b2.contrast
-                        || b1.saturation != b2.saturation
-                        || b1.xPos1 != b2.xPos1
-                        || b1.xPos2 != b2.xPos2
-                        || b1.yPos1 != b2.yPos1
-                        || b1.yPos2 != b2.yPos2) {
-                    return false;
-                }
-            }
-            return true;
-        }
-        return false;
-    }
-
-    public int getNumberOfBands() {
-        int count = 0;
-        for (Band point : mBands) {
-            if (!point.mask) {
-                count++;
-            }
-        }
-        return count;
-    }
-
-    public int addBand(Rect rect) {
-        mBands.add(0, mCurrentBand = new Band(rect.centerX(), rect.centerY()));
-        mCurrentBand.mask = false;
-        int x = (mCurrentBand.xPos1 + mCurrentBand.xPos2)/2;
-        int y = (mCurrentBand.yPos1 + mCurrentBand.yPos2)/2;
-        double addDelta = ADD_MIN_DIST * Math.max(rect.width(), rect.height());
-        boolean moved = true;
-        int count = 0;
-        int toMove =  mBands.indexOf(mCurrentBand);
-
-        while (moved) {
-            moved = false;
-            count++;
-            if (count > 14) {
-                break;
-            }
-
-            for (Band point : mBands) {
-                if (point.mask) {
-                    break;
-                }
-            }
-
-            for (Band point : mBands) {
-                if (point.mask) {
-                    break;
-                }
-                int index = mBands.indexOf(point);
-
-                if (toMove != index) {
-                    double dist = Math.hypot(point.xPos1 - x, point.yPos1 - y);
-                    if (dist < addDelta) {
-                        moved = true;
-                        mCurrentBand.xPos1 += addDelta;
-                        mCurrentBand.yPos1 += addDelta;
-                        mCurrentBand.xPos2 += addDelta;
-                        mCurrentBand.yPos2 += addDelta;
-                        x = (mCurrentBand.xPos1 + mCurrentBand.xPos2)/2;
-                        y = (mCurrentBand.yPos1 + mCurrentBand.yPos2)/2;
-
-                        if (mCurrentBand.yPos1 > rect.bottom) {
-                            mCurrentBand.yPos1 = (int) (rect.top + addDelta);
-                        }
-                        if (mCurrentBand.xPos1 > rect.right) {
-                            mCurrentBand.xPos1 = (int) (rect.left + addDelta);
-                        }
-                    }
-                }
-            }
-        }
-        trimVector();
-        return 0;
-    }
-
-    public void deleteCurrentBand() {
-        int index = mBands.indexOf(mCurrentBand);
-        mBands.remove(mCurrentBand);
-        trimVector();
-        if (getNumberOfBands() == 0) {
-            addBand(MasterImage.getImage().getOriginalBounds());
-        }
-        mCurrentBand = mBands.get(0);
-    }
-
-    public void  nextPoint(){
-        int index = mBands.indexOf(mCurrentBand);
-        int tmp = index;
-        Band point;
-        int k = 0;
-        do  {
-            index =   (index+1)% mBands.size();
-            point = mBands.get(index);
-            if (k++ >= mBands.size()) {
-                break;
-            }
-        }
-        while (point.mask == true);
-        mCurrentBand = mBands.get(index);
-    }
-
-    public void setSelectedPoint(int pos) {
-        mCurrentBand = mBands.get(pos);
-    }
-
-    public int getSelectedPoint() {
-        return mBands.indexOf(mCurrentBand);
-    }
-
-    public boolean[] getMask() {
-        boolean[] ret = new boolean[mBands.size()];
-        int i = 0;
-        for (Band point : mBands) {
-            ret[i++] = !point.mask;
-        }
-        return ret;
-    }
-
-    public int[] getXPos1() {
-        int[] ret = new int[mBands.size()];
-        int i = 0;
-        for (Band point : mBands) {
-            ret[i++] = point.xPos1;
-        }
-        return ret;
-    }
-
-    public int[] getYPos1() {
-        int[] ret = new int[mBands.size()];
-        int i = 0;
-        for (Band point : mBands) {
-            ret[i++] = point.yPos1;
-        }
-        return ret;
-    }
-
-    public int[] getXPos2() {
-        int[] ret = new int[mBands.size()];
-        int i = 0;
-        for (Band point : mBands) {
-            ret[i++] = point.xPos2;
-        }
-        return ret;
-    }
-
-    public int[] getYPos2() {
-        int[] ret = new int[mBands.size()];
-        int i = 0;
-        for (Band point : mBands) {
-            ret[i++] = point.yPos2;
-        }
-        return ret;
-    }
-
-    public int[] getBrightness() {
-        int[] ret = new int[mBands.size()];
-        int i = 0;
-        for (Band point : mBands) {
-            ret[i++] = point.brightness;
-        }
-        return ret;
-    }
-
-    public int[] getContrast() {
-        int[] ret = new int[mBands.size()];
-        int i = 0;
-        for (Band point : mBands) {
-            ret[i++] = point.contrast;
-        }
-        return ret;
-    }
-
-    public int[] getSaturation() {
-        int[] ret = new int[mBands.size()];
-        int i = 0;
-        for (Band point : mBands) {
-            ret[i++] = point.saturation;
-        }
-        return ret;
-    }
-
-    public int getParameter(int type) {
-        switch (type){
-            case PARAM_BRIGHTNESS:
-                return mCurrentBand.brightness;
-            case PARAM_SATURATION:
-                return mCurrentBand.saturation;
-            case PARAM_CONTRAST:
-                return mCurrentBand.contrast;
-        }
-        throw new IllegalArgumentException("no such type " + type);
-    }
-
-    public int getParameterMax(int type) {
-        switch (type) {
-            case PARAM_BRIGHTNESS:
-                return 100;
-            case PARAM_SATURATION:
-                return 100;
-            case PARAM_CONTRAST:
-                return 100;
-        }
-        throw new IllegalArgumentException("no such type " + type);
-    }
-
-    public int getParameterMin(int type) {
-        switch (type) {
-            case PARAM_BRIGHTNESS:
-                return -100;
-            case PARAM_SATURATION:
-                return -100;
-            case PARAM_CONTRAST:
-                return -100;
-        }
-        throw new IllegalArgumentException("no such type " + type);
-    }
-
-    public void setParameter(int type, int value) {
-        mCurrentBand.mask = false;
-        switch (type) {
-            case PARAM_BRIGHTNESS:
-                mCurrentBand.brightness = value;
-                break;
-            case PARAM_SATURATION:
-                mCurrentBand.saturation = value;
-                break;
-            case PARAM_CONTRAST:
-                mCurrentBand.contrast = value;
-                break;
-            default:
-                throw new IllegalArgumentException("no such type " + type);
-        }
-    }
-
-    @Override
-    public void setPoint1(float x, float y) {
-        mCurrentBand.xPos1 = (int)x;
-        mCurrentBand.yPos1 = (int)y;
-    }
-
-    @Override
-    public void setPoint2(float x, float y) {
-        mCurrentBand.xPos2 = (int)x;
-        mCurrentBand.yPos2 = (int)y;
-    }
-
-    @Override
-    public float getPoint1X() {
-        return mCurrentBand.xPos1;
-    }
-
-    @Override
-    public float getPoint1Y() {
-        return mCurrentBand.yPos1;
-    }
-    @Override
-    public float getPoint2X() {
-        return mCurrentBand.xPos2;
-    }
-
-    @Override
-    public float getPoint2Y() {
-        return mCurrentBand.yPos2;
-    }
-
-    @Override
-    public void serializeRepresentation(JsonWriter writer) throws IOException {
-        writer.beginObject();
-        int len = mBands.size();
-        int count = 0;
-
-        for (int i = 0; i < len; i++) {
-            Band point = mBands.get(i);
-            if (point.mask) {
-                continue;
-            }
-            writer.name(LINE_NAME + count);
-            count++;
-            writer.beginArray();
-            writer.value(point.xPos1);
-            writer.value(point.yPos1);
-            writer.value(point.xPos2);
-            writer.value(point.yPos2);
-            writer.value(point.brightness);
-            writer.value(point.contrast);
-            writer.value(point.saturation);
-            writer.endArray();
-        }
-        writer.endObject();
-    }
-
-    @Override
-    public void deSerializeRepresentation(JsonReader sreader) throws IOException {
-        sreader.beginObject();
-        Vector<Band> points = new Vector<Band>();
-
-        while (sreader.hasNext()) {
-            String name = sreader.nextName();
-            if (name.startsWith(LINE_NAME)) {
-                int pointNo = Integer.parseInt(name.substring(LINE_NAME.length()));
-                sreader.beginArray();
-                Band p = new Band();
-                p.mask = false;
-                sreader.hasNext();
-                p.xPos1 = sreader.nextInt();
-                sreader.hasNext();
-                p.yPos1 = sreader.nextInt();
-                sreader.hasNext();
-                p.xPos2 = sreader.nextInt();
-                sreader.hasNext();
-                p.yPos2 = sreader.nextInt();
-                sreader.hasNext();
-                p.brightness = sreader.nextInt();
-                sreader.hasNext();
-                p.contrast = sreader.nextInt();
-                sreader.hasNext();
-                p.saturation = sreader.nextInt();
-                sreader.hasNext();
-                sreader.endArray();
-                points.add(p);
-
-            } else {
-                sreader.skipValue();
-            }
-        }
-        mBands = points;
-        trimVector();
-        mCurrentBand = mBands.get(0);
-        sreader.endObject();
-    }
-}
diff --git a/src/com/android/gallery3d/filtershow/filters/FilterImageBorderRepresentation.java b/src/com/android/gallery3d/filtershow/filters/FilterImageBorderRepresentation.java
deleted file mode 100644
index f310a2b..0000000
--- a/src/com/android/gallery3d/filtershow/filters/FilterImageBorderRepresentation.java
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- * Copyright (C) 2013 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.gallery3d.filtershow.filters;
-
-import com.android.gallery3d.R;
-import com.android.gallery3d.filtershow.editors.ImageOnlyEditor;
-
-public class FilterImageBorderRepresentation extends FilterRepresentation {
-    private int mDrawableResource = 0;
-
-    public FilterImageBorderRepresentation(int drawableResource) {
-        super("ImageBorder");
-        setFilterClass(ImageFilterBorder.class);
-        mDrawableResource = drawableResource;
-        setFilterType(FilterRepresentation.TYPE_BORDER);
-        setTextId(R.string.borders);
-        setEditorId(ImageOnlyEditor.ID);
-        setShowParameterValue(false);
-    }
-
-    public String toString() {
-        return "FilterBorder: " + getName();
-    }
-
-    @Override
-    public FilterRepresentation copy() {
-        FilterImageBorderRepresentation representation =
-                new FilterImageBorderRepresentation(mDrawableResource);
-        copyAllParameters(representation);
-        return representation;
-    }
-
-    @Override
-    protected void copyAllParameters(FilterRepresentation representation) {
-        super.copyAllParameters(representation);
-        representation.useParametersFrom(this);
-    }
-
-    public void useParametersFrom(FilterRepresentation a) {
-        if (a instanceof FilterImageBorderRepresentation) {
-            FilterImageBorderRepresentation representation = (FilterImageBorderRepresentation) a;
-            setName(representation.getName());
-            setDrawableResource(representation.getDrawableResource());
-        }
-    }
-
-    @Override
-    public boolean equals(FilterRepresentation representation) {
-        if (!super.equals(representation)) {
-            return false;
-        }
-        if (representation instanceof FilterImageBorderRepresentation) {
-            FilterImageBorderRepresentation border = (FilterImageBorderRepresentation) representation;
-            if (border.mDrawableResource == mDrawableResource) {
-                return true;
-            }
-        }
-        return false;
-    }
-
-    @Override
-    public int getTextId() {
-        return R.string.none;
-    }
-
-    public boolean allowsSingleInstanceOnly() {
-        return true;
-    }
-
-    public int getDrawableResource() {
-        return mDrawableResource;
-    }
-
-    public void setDrawableResource(int drawableResource) {
-        mDrawableResource = drawableResource;
-    }
-}
diff --git a/src/com/android/gallery3d/filtershow/filters/FilterMirrorRepresentation.java b/src/com/android/gallery3d/filtershow/filters/FilterMirrorRepresentation.java
deleted file mode 100644
index 8dcff0d..0000000
--- a/src/com/android/gallery3d/filtershow/filters/FilterMirrorRepresentation.java
+++ /dev/null
@@ -1,190 +0,0 @@
-/*
- * Copyright (C) 2013 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.gallery3d.filtershow.filters;
-
-import android.util.JsonReader;
-import android.util.JsonWriter;
-import android.util.Log;
-
-import com.android.gallery3d.R;
-import com.android.gallery3d.filtershow.editors.EditorMirror;
-
-import java.io.IOException;
-
-public class FilterMirrorRepresentation extends FilterRepresentation {
-    public static final String SERIALIZATION_NAME = "MIRROR";
-    private static final String SERIALIZATION_MIRROR_VALUE = "value";
-    private static final String TAG = FilterMirrorRepresentation.class.getSimpleName();
-
-    Mirror mMirror;
-
-    public enum Mirror {
-        NONE('N'), VERTICAL('V'), HORIZONTAL('H'), BOTH('B');
-        char mValue;
-
-        private Mirror(char value) {
-            mValue = value;
-        }
-
-        public char value() {
-            return mValue;
-        }
-
-        public static Mirror fromValue(char value) {
-            switch (value) {
-                case 'N':
-                    return NONE;
-                case 'V':
-                    return VERTICAL;
-                case 'H':
-                    return HORIZONTAL;
-                case 'B':
-                    return BOTH;
-                default:
-                    return null;
-            }
-        }
-    }
-
-    public FilterMirrorRepresentation(Mirror mirror) {
-        super(FilterMirrorRepresentation.class.getSimpleName());
-        setSerializationName(SERIALIZATION_NAME);
-        setShowParameterValue(true);
-        setFilterClass(FilterMirrorRepresentation.class);
-        setFilterType(FilterRepresentation.TYPE_GEOMETRY);
-        setTextId(R.string.mirror);
-        setEditorId(EditorMirror.ID);
-        setMirror(mirror);
-    }
-
-    public FilterMirrorRepresentation(FilterMirrorRepresentation m) {
-        this(m.getMirror());
-    }
-
-    public FilterMirrorRepresentation() {
-        this(getNil());
-    }
-
-    @Override
-    public boolean equals(FilterRepresentation rep) {
-        if (!(rep instanceof FilterMirrorRepresentation)) {
-            return false;
-        }
-        FilterMirrorRepresentation mirror = (FilterMirrorRepresentation) rep;
-        if (mMirror != mirror.mMirror) {
-            return false;
-        }
-        return true;
-    }
-
-    public Mirror getMirror() {
-        return mMirror;
-    }
-
-    public void set(FilterMirrorRepresentation r) {
-        mMirror = r.mMirror;
-    }
-
-    public void setMirror(Mirror mirror) {
-        if (mirror == null) {
-            throw new IllegalArgumentException("Argument to setMirror is null");
-        }
-        mMirror = mirror;
-    }
-
-    public void cycle() {
-        switch (mMirror) {
-            case NONE:
-                mMirror = Mirror.HORIZONTAL;
-                break;
-            case HORIZONTAL:
-                mMirror = Mirror.VERTICAL;
-                break;
-            case VERTICAL:
-                mMirror = Mirror.BOTH;
-                break;
-            case BOTH:
-                mMirror = Mirror.NONE;
-                break;
-        }
-    }
-
-    @Override
-    public boolean allowsSingleInstanceOnly() {
-        return true;
-    }
-
-    @Override
-    public FilterRepresentation copy() {
-        return new FilterMirrorRepresentation(this);
-    }
-
-    @Override
-    protected void copyAllParameters(FilterRepresentation representation) {
-        if (!(representation instanceof FilterMirrorRepresentation)) {
-            throw new IllegalArgumentException("calling copyAllParameters with incompatible types!");
-        }
-        super.copyAllParameters(representation);
-        representation.useParametersFrom(this);
-    }
-
-    @Override
-    public void useParametersFrom(FilterRepresentation a) {
-        if (!(a instanceof FilterMirrorRepresentation)) {
-            throw new IllegalArgumentException("calling useParametersFrom with incompatible types!");
-        }
-        setMirror(((FilterMirrorRepresentation) a).getMirror());
-    }
-
-    @Override
-    public boolean isNil() {
-        return mMirror == getNil();
-    }
-
-    public static Mirror getNil() {
-        return Mirror.NONE;
-    }
-
-    @Override
-    public void serializeRepresentation(JsonWriter writer) throws IOException {
-        writer.beginObject();
-        writer.name(SERIALIZATION_MIRROR_VALUE).value(mMirror.value());
-        writer.endObject();
-    }
-
-    @Override
-    public void deSerializeRepresentation(JsonReader reader) throws IOException {
-        boolean unset = true;
-        reader.beginObject();
-        while (reader.hasNext()) {
-            String name = reader.nextName();
-            if (SERIALIZATION_MIRROR_VALUE.equals(name)) {
-                Mirror r = Mirror.fromValue((char) reader.nextInt());
-                if (r != null) {
-                    setMirror(r);
-                    unset = false;
-                }
-            } else {
-                reader.skipValue();
-            }
-        }
-        if (unset) {
-            Log.w(TAG, "WARNING: bad value when deserializing " + SERIALIZATION_NAME);
-        }
-        reader.endObject();
-    }
-}
diff --git a/src/com/android/gallery3d/filtershow/filters/FilterPoint.java b/src/com/android/gallery3d/filtershow/filters/FilterPoint.java
deleted file mode 100644
index 4520717..0000000
--- a/src/com/android/gallery3d/filtershow/filters/FilterPoint.java
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- * Copyright (C) 2013 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.gallery3d.filtershow.filters;
-
-public interface FilterPoint {
-
-}
diff --git a/src/com/android/gallery3d/filtershow/filters/FilterPointRepresentation.java b/src/com/android/gallery3d/filtershow/filters/FilterPointRepresentation.java
deleted file mode 100644
index 9bd1699..0000000
--- a/src/com/android/gallery3d/filtershow/filters/FilterPointRepresentation.java
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- * Copyright (C) 2013 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.gallery3d.filtershow.filters;
-
-import java.util.Vector;
-
-public abstract class FilterPointRepresentation extends FilterRepresentation {
-    private static final String LOGTAG = "FilterPointRepresentation";
-    private Vector<FilterPoint> mCandidates = new Vector<FilterPoint>();
-
-    public FilterPointRepresentation(String type, int textid, int editorID) {
-        super(type);
-        setFilterClass(ImageFilterRedEye.class);
-        setFilterType(FilterRepresentation.TYPE_NORMAL);
-        setTextId(textid);
-        setEditorId(editorID);
-    }
-
-    @Override
-    public abstract FilterRepresentation copy();
-
-    @Override
-    protected void copyAllParameters(FilterRepresentation representation) {
-        super.copyAllParameters(representation);
-        representation.useParametersFrom(this);
-    }
-
-    public boolean hasCandidates() {
-        return mCandidates != null;
-    }
-
-    public Vector<FilterPoint> getCandidates() {
-        return mCandidates;
-    }
-
-    @Override
-    public boolean isNil() {
-        if (getCandidates() != null && getCandidates().size() > 0) {
-            return false;
-        }
-        return true;
-    }
-
-    public Object getCandidate(int index) {
-        return this.mCandidates.get(index);
-    }
-
-    public void addCandidate(FilterPoint c) {
-        this.mCandidates.add(c);
-    }
-
-    @Override
-    public void useParametersFrom(FilterRepresentation a) {
-        if (a instanceof FilterPointRepresentation) {
-            FilterPointRepresentation representation = (FilterPointRepresentation) a;
-            mCandidates.clear();
-            for (FilterPoint redEyeCandidate : representation.mCandidates) {
-                mCandidates.add(redEyeCandidate);
-            }
-        }
-    }
-
-    public void removeCandidate(RedEyeCandidate c) {
-        this.mCandidates.remove(c);
-    }
-
-    public void clearCandidates() {
-        this.mCandidates.clear();
-    }
-
-    public int getNumberOfCandidates() {
-        return mCandidates.size();
-    }
-}
diff --git a/src/com/android/gallery3d/filtershow/filters/FilterRedEyeRepresentation.java b/src/com/android/gallery3d/filtershow/filters/FilterRedEyeRepresentation.java
deleted file mode 100644
index dd06a97..0000000
--- a/src/com/android/gallery3d/filtershow/filters/FilterRedEyeRepresentation.java
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * Copyright (C) 2013 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.gallery3d.filtershow.filters;
-
-import android.graphics.RectF;
-
-import com.android.gallery3d.R;
-import com.android.gallery3d.filtershow.editors.EditorRedEye;
-
-import java.util.Vector;
-
-public class FilterRedEyeRepresentation extends FilterPointRepresentation {
-    private static final String LOGTAG = "FilterRedEyeRepresentation";
-
-    public FilterRedEyeRepresentation() {
-        super("RedEye",R.string.redeye,EditorRedEye.ID);
-        setSerializationName("REDEYE");
-        setFilterClass(ImageFilterRedEye.class);
-        setOverlayId(R.drawable.photoeditor_effect_redeye);
-        setOverlayOnly(true);
-    }
-
-    @Override
-    public FilterRepresentation copy() {
-        FilterRedEyeRepresentation representation = new FilterRedEyeRepresentation();
-        copyAllParameters(representation);
-        return representation;
-    }
-
-    @Override
-    protected void copyAllParameters(FilterRepresentation representation) {
-        super.copyAllParameters(representation);
-        representation.useParametersFrom(this);
-    }
-
-    public void addRect(RectF rect, RectF bounds) {
-        Vector<RedEyeCandidate> intersects = new Vector<RedEyeCandidate>();
-        for (int i = 0; i < getCandidates().size(); i++) {
-            RedEyeCandidate r = (RedEyeCandidate) getCandidate(i);
-            if (r.intersect(rect)) {
-                intersects.add(r);
-            }
-        }
-        for (int i = 0; i < intersects.size(); i++) {
-            RedEyeCandidate r = intersects.elementAt(i);
-            rect.union(r.mRect);
-            bounds.union(r.mBounds);
-            removeCandidate(r);
-        }
-        addCandidate(new RedEyeCandidate(rect, bounds));
-    }
-
-}
diff --git a/src/com/android/gallery3d/filtershow/filters/FilterRepresentation.java b/src/com/android/gallery3d/filtershow/filters/FilterRepresentation.java
deleted file mode 100644
index 5b33ffb..0000000
--- a/src/com/android/gallery3d/filtershow/filters/FilterRepresentation.java
+++ /dev/null
@@ -1,262 +0,0 @@
-/*
- * Copyright (C) 2013 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.gallery3d.filtershow.filters;
-
-import android.util.JsonReader;
-import android.util.JsonWriter;
-import android.util.Log;
-
-import com.android.gallery3d.filtershow.editors.BasicEditor;
-
-import java.io.IOException;
-import java.util.ArrayList;
-
-public class FilterRepresentation {
-    private static final String LOGTAG = "FilterRepresentation";
-    private static final boolean DEBUG = false;
-    private String mName;
-    private int mPriority = TYPE_NORMAL;
-    private Class<?> mFilterClass;
-    private boolean mSupportsPartialRendering = false;
-    private int mTextId = 0;
-    private int mEditorId = BasicEditor.ID;
-    private int mButtonId = 0;
-    private int mOverlayId = 0;
-    private boolean mOverlayOnly = false;
-    private boolean mShowParameterValue = true;
-    private String mSerializationName;
-    public static final byte TYPE_BORDER = 1;
-    public static final byte TYPE_FX = 2;
-    public static final byte TYPE_WBALANCE = 3;
-    public static final byte TYPE_VIGNETTE = 4;
-    public static final byte TYPE_NORMAL = 5;
-    public static final byte TYPE_TINYPLANET = 6;
-    public static final byte TYPE_GEOMETRY = 7;
-    protected static final String NAME_TAG = "Name";
-
-    public FilterRepresentation(String name) {
-        mName = name;
-    }
-
-    public FilterRepresentation copy(){
-        FilterRepresentation representation = new FilterRepresentation(mName);
-        representation.useParametersFrom(this);
-        return representation;
-    }
-
-    protected void copyAllParameters(FilterRepresentation representation) {
-        representation.setName(getName());
-        representation.setFilterClass(getFilterClass());
-        representation.setFilterType(getFilterType());
-        representation.setSupportsPartialRendering(supportsPartialRendering());
-        representation.setTextId(getTextId());
-        representation.setEditorId(getEditorId());
-        representation.setOverlayId(getOverlayId());
-        representation.setOverlayOnly(getOverlayOnly());
-        representation.setShowParameterValue(showParameterValue());
-        representation.mSerializationName = mSerializationName;
-
-    }
-
-    public boolean equals(FilterRepresentation representation) {
-        if (representation == null) {
-            return false;
-        }
-        if (representation.mFilterClass == mFilterClass
-                && representation.mName.equalsIgnoreCase(mName)
-                && representation.mPriority == mPriority
-                // TODO: After we enable partial rendering, we can switch back
-                // to use member variable here.
-                && representation.supportsPartialRendering() == supportsPartialRendering()
-                && representation.mTextId == mTextId
-                && representation.mEditorId == mEditorId
-                && representation.mButtonId == mButtonId
-                && representation.mOverlayId == mOverlayId
-                && representation.mOverlayOnly == mOverlayOnly
-                && representation.mShowParameterValue == mShowParameterValue) {
-            return true;
-        }
-        return false;
-    }
-
-    @Override
-    public String toString() {
-        return mName;
-    }
-
-    public void setName(String name) {
-        mName = name;
-    }
-
-    public String getName() {
-        return mName;
-    }
-
-    public void setSerializationName(String sname) {
-        mSerializationName = sname;
-    }
-
-    public String getSerializationName() {
-        return mSerializationName;
-    }
-
-    public void setFilterType(int priority) {
-        mPriority = priority;
-    }
-
-    public int getFilterType() {
-        return mPriority;
-    }
-
-    public boolean isNil() {
-        return false;
-    }
-
-    public boolean supportsPartialRendering() {
-        return false && mSupportsPartialRendering; // disable for now
-    }
-
-    public void setSupportsPartialRendering(boolean value) {
-        mSupportsPartialRendering = value;
-    }
-
-    public void useParametersFrom(FilterRepresentation a) {
-    }
-
-    public boolean allowsSingleInstanceOnly() {
-        return false;
-    }
-
-    public Class<?> getFilterClass() {
-        return mFilterClass;
-    }
-
-    public void setFilterClass(Class<?> filterClass) {
-        mFilterClass = filterClass;
-    }
-
-    // This same() function is different from equals(), basically it checks
-    // whether 2 FilterRepresentations are the same type. It doesn't care about
-    // the values.
-    public boolean same(FilterRepresentation b) {
-        if (b == null) {
-            return false;
-        }
-        return getFilterClass() == b.getFilterClass();
-    }
-
-    public int getTextId() {
-        return mTextId;
-    }
-
-    public void setTextId(int textId) {
-        mTextId = textId;
-    }
-
-    public int getOverlayId() {
-        return mOverlayId;
-    }
-
-    public void setOverlayId(int overlayId) {
-        mOverlayId = overlayId;
-    }
-
-    public boolean getOverlayOnly() {
-        return mOverlayOnly;
-    }
-
-    public void setOverlayOnly(boolean value) {
-        mOverlayOnly = value;
-    }
-
-    final public int getEditorId() {
-        return mEditorId;
-    }
-
-    public int[] getEditorIds() {
-        return new int[] {
-        mEditorId };
-    }
-
-    public void setEditorId(int editorId) {
-        mEditorId = editorId;
-    }
-
-    public boolean showParameterValue() {
-        return mShowParameterValue;
-    }
-
-    public void setShowParameterValue(boolean showParameterValue) {
-        mShowParameterValue = showParameterValue;
-    }
-
-    public String getStateRepresentation() {
-        return "";
-    }
-
-    /**
-     * Method must "beginObject()" add its info and "endObject()"
-     * @param writer
-     * @throws IOException
-     */
-    public void serializeRepresentation(JsonWriter writer) throws IOException {
-        writer.beginObject();
-        {
-            String[][] rep = serializeRepresentation();
-            for (int k = 0; k < rep.length; k++) {
-                writer.name(rep[k][0]);
-                writer.value(rep[k][1]);
-            }
-        }
-        writer.endObject();
-    }
-
-    // this is the old way of doing this and will be removed soon
-    public String[][] serializeRepresentation() {
-        String[][] ret = {{NAME_TAG, getName()}};
-        return ret;
-    }
-
-    public void deSerializeRepresentation(JsonReader reader) throws IOException {
-        ArrayList<String[]> al = new ArrayList<String[]>();
-        reader.beginObject();
-        while (reader.hasNext()) {
-            String[] kv = {reader.nextName(), reader.nextString()};
-            al.add(kv);
-
-        }
-        reader.endObject();
-        String[][] oldFormat = al.toArray(new String[al.size()][]);
-
-        deSerializeRepresentation(oldFormat);
-    }
-
-    // this is the old way of doing this and will be removed soon
-    public void deSerializeRepresentation(String[][] rep) {
-        for (int i = 0; i < rep.length; i++) {
-            if (NAME_TAG.equals(rep[i][0])) {
-                mName = rep[i][1];
-                break;
-            }
-        }
-    }
-
-    // Override this in subclasses
-    public int getStyle() {
-        return -1;
-    }
-}
diff --git a/src/com/android/gallery3d/filtershow/filters/FilterRotateRepresentation.java b/src/com/android/gallery3d/filtershow/filters/FilterRotateRepresentation.java
deleted file mode 100644
index eb89de0..0000000
--- a/src/com/android/gallery3d/filtershow/filters/FilterRotateRepresentation.java
+++ /dev/null
@@ -1,190 +0,0 @@
-/*
- * Copyright (C) 2013 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.gallery3d.filtershow.filters;
-
-import android.util.JsonReader;
-import android.util.JsonWriter;
-import android.util.Log;
-
-import com.android.gallery3d.R;
-import com.android.gallery3d.filtershow.editors.EditorRotate;
-
-import java.io.IOException;
-
-public class FilterRotateRepresentation extends FilterRepresentation {
-    public static final String SERIALIZATION_NAME = "ROTATION";
-    public static final String SERIALIZATION_ROTATE_VALUE = "value";
-    private static final String TAG = FilterRotateRepresentation.class.getSimpleName();
-
-    Rotation mRotation;
-
-    public enum Rotation {
-        ZERO(0), NINETY(90), ONE_EIGHTY(180), TWO_SEVENTY(270);
-        private final int mValue;
-
-        private Rotation(int value) {
-            mValue = value;
-        }
-
-        public int value() {
-            return mValue;
-        }
-
-        public static Rotation fromValue(int value) {
-            switch (value) {
-                case 0:
-                    return ZERO;
-                case 90:
-                    return NINETY;
-                case 180:
-                    return ONE_EIGHTY;
-                case 270:
-                    return TWO_SEVENTY;
-                default:
-                    return null;
-            }
-        }
-    }
-
-    public FilterRotateRepresentation(Rotation rotation) {
-        super(FilterRotateRepresentation.class.getSimpleName());
-        setSerializationName(SERIALIZATION_NAME);
-        setShowParameterValue(true);
-        setFilterClass(FilterRotateRepresentation.class);
-        setFilterType(FilterRepresentation.TYPE_GEOMETRY);
-        setTextId(R.string.rotate);
-        setEditorId(EditorRotate.ID);
-        setRotation(rotation);
-    }
-
-    public FilterRotateRepresentation(FilterRotateRepresentation r) {
-        this(r.getRotation());
-    }
-
-    public FilterRotateRepresentation() {
-        this(getNil());
-    }
-
-    public Rotation getRotation() {
-        return mRotation;
-    }
-
-    public void rotateCW() {
-        switch(mRotation) {
-            case ZERO:
-                mRotation = Rotation.NINETY;
-                break;
-            case NINETY:
-                mRotation = Rotation.ONE_EIGHTY;
-                break;
-            case ONE_EIGHTY:
-                mRotation = Rotation.TWO_SEVENTY;
-                break;
-            case TWO_SEVENTY:
-                mRotation = Rotation.ZERO;
-                break;
-        }
-    }
-
-    public void set(FilterRotateRepresentation r) {
-        mRotation = r.mRotation;
-    }
-
-    public void setRotation(Rotation rotation) {
-        if (rotation == null) {
-            throw new IllegalArgumentException("Argument to setRotation is null");
-        }
-        mRotation = rotation;
-    }
-
-    @Override
-    public boolean allowsSingleInstanceOnly() {
-        return true;
-    }
-
-    @Override
-    public FilterRepresentation copy() {
-        return new FilterRotateRepresentation(this);
-    }
-
-    @Override
-    protected void copyAllParameters(FilterRepresentation representation) {
-        if (!(representation instanceof FilterRotateRepresentation)) {
-            throw new IllegalArgumentException("calling copyAllParameters with incompatible types!");
-        }
-        super.copyAllParameters(representation);
-        representation.useParametersFrom(this);
-    }
-
-    @Override
-    public void useParametersFrom(FilterRepresentation a) {
-        if (!(a instanceof FilterRotateRepresentation)) {
-            throw new IllegalArgumentException("calling useParametersFrom with incompatible types!");
-        }
-        setRotation(((FilterRotateRepresentation) a).getRotation());
-    }
-
-    @Override
-    public boolean isNil() {
-        return mRotation == getNil();
-    }
-
-    public static Rotation getNil() {
-        return Rotation.ZERO;
-    }
-
-    @Override
-    public void serializeRepresentation(JsonWriter writer) throws IOException {
-        writer.beginObject();
-        writer.name(SERIALIZATION_ROTATE_VALUE).value(mRotation.value());
-        writer.endObject();
-    }
-
-    @Override
-    public boolean equals(FilterRepresentation rep) {
-        if (!(rep instanceof FilterRotateRepresentation)) {
-            return false;
-        }
-        FilterRotateRepresentation rotate = (FilterRotateRepresentation) rep;
-        if (rotate.mRotation.value() != mRotation.value()) {
-            return false;
-        }
-        return true;
-    }
-
-    @Override
-    public void deSerializeRepresentation(JsonReader reader) throws IOException {
-        boolean unset = true;
-        reader.beginObject();
-        while (reader.hasNext()) {
-            String name = reader.nextName();
-            if (SERIALIZATION_ROTATE_VALUE.equals(name)) {
-                Rotation r = Rotation.fromValue(reader.nextInt());
-                if (r != null) {
-                    setRotation(r);
-                    unset = false;
-                }
-            } else {
-                reader.skipValue();
-            }
-        }
-        if (unset) {
-            Log.w(TAG, "WARNING: bad value when deserializing " + SERIALIZATION_NAME);
-        }
-        reader.endObject();
-    }
-}
diff --git a/src/com/android/gallery3d/filtershow/filters/FilterStraightenRepresentation.java b/src/com/android/gallery3d/filtershow/filters/FilterStraightenRepresentation.java
deleted file mode 100644
index 94c9497..0000000
--- a/src/com/android/gallery3d/filtershow/filters/FilterStraightenRepresentation.java
+++ /dev/null
@@ -1,154 +0,0 @@
-/*
- * Copyright (C) 2013 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.gallery3d.filtershow.filters;
-
-import android.util.JsonReader;
-import android.util.JsonWriter;
-import android.util.Log;
-
-import com.android.gallery3d.R;
-import com.android.gallery3d.filtershow.editors.EditorStraighten;
-
-import java.io.IOException;
-
-public class FilterStraightenRepresentation extends FilterRepresentation {
-    public static final String SERIALIZATION_NAME = "STRAIGHTEN";
-    public static final String SERIALIZATION_STRAIGHTEN_VALUE = "value";
-    private static final String TAG = FilterStraightenRepresentation.class.getSimpleName();
-    public static final int MAX_STRAIGHTEN_ANGLE = 45;
-    public static final int MIN_STRAIGHTEN_ANGLE = -45;
-
-    float mStraighten;
-
-    public FilterStraightenRepresentation(float straighten) {
-        super(FilterStraightenRepresentation.class.getSimpleName());
-        setSerializationName(SERIALIZATION_NAME);
-        setShowParameterValue(true);
-        setFilterClass(FilterStraightenRepresentation.class);
-        setFilterType(FilterRepresentation.TYPE_GEOMETRY);
-        setTextId(R.string.straighten);
-        setEditorId(EditorStraighten.ID);
-        setStraighten(straighten);
-    }
-
-    public FilterStraightenRepresentation(FilterStraightenRepresentation s) {
-        this(s.getStraighten());
-    }
-
-    public FilterStraightenRepresentation() {
-        this(getNil());
-    }
-
-    public void set(FilterStraightenRepresentation r) {
-        mStraighten = r.mStraighten;
-    }
-
-    @Override
-    public boolean equals(FilterRepresentation rep) {
-        if (!(rep instanceof FilterStraightenRepresentation)) {
-            return false;
-        }
-        FilterStraightenRepresentation straighten = (FilterStraightenRepresentation) rep;
-        if (straighten.mStraighten != mStraighten) {
-            return false;
-        }
-        return true;
-    }
-
-    public float getStraighten() {
-        return mStraighten;
-    }
-
-    public void setStraighten(float straighten) {
-        if (!rangeCheck(straighten)) {
-            straighten = Math.min(Math.max(straighten, MIN_STRAIGHTEN_ANGLE), MAX_STRAIGHTEN_ANGLE);
-        }
-        mStraighten = straighten;
-    }
-
-    @Override
-    public boolean allowsSingleInstanceOnly() {
-        return true;
-    }
-
-    @Override
-    public FilterRepresentation copy() {
-        return new FilterStraightenRepresentation(this);
-    }
-
-    @Override
-    protected void copyAllParameters(FilterRepresentation representation) {
-        if (!(representation instanceof FilterStraightenRepresentation)) {
-            throw new IllegalArgumentException("calling copyAllParameters with incompatible types!");
-        }
-        super.copyAllParameters(representation);
-        representation.useParametersFrom(this);
-    }
-
-    @Override
-    public void useParametersFrom(FilterRepresentation a) {
-        if (!(a instanceof FilterStraightenRepresentation)) {
-            throw new IllegalArgumentException("calling useParametersFrom with incompatible types!");
-        }
-        setStraighten(((FilterStraightenRepresentation) a).getStraighten());
-    }
-
-    @Override
-    public boolean isNil() {
-        return mStraighten == getNil();
-    }
-
-    public static float getNil() {
-        return 0;
-    }
-
-    @Override
-    public void serializeRepresentation(JsonWriter writer) throws IOException {
-        writer.beginObject();
-        writer.name(SERIALIZATION_STRAIGHTEN_VALUE).value(mStraighten);
-        writer.endObject();
-    }
-
-    @Override
-    public void deSerializeRepresentation(JsonReader reader) throws IOException {
-        boolean unset = true;
-        reader.beginObject();
-        while (reader.hasNext()) {
-            String name = reader.nextName();
-            if (SERIALIZATION_STRAIGHTEN_VALUE.equals(name)) {
-                float s = (float) reader.nextDouble();
-                if (rangeCheck(s)) {
-                    setStraighten(s);
-                    unset = false;
-                }
-            } else {
-                reader.skipValue();
-            }
-        }
-        if (unset) {
-            Log.w(TAG, "WARNING: bad value when deserializing " + SERIALIZATION_NAME);
-        }
-        reader.endObject();
-    }
-
-    private boolean rangeCheck(double s) {
-        if (s < -45 || s > 45) {
-            return false;
-        }
-        return true;
-    }
-}
diff --git a/src/com/android/gallery3d/filtershow/filters/FilterTinyPlanetRepresentation.java b/src/com/android/gallery3d/filtershow/filters/FilterTinyPlanetRepresentation.java
deleted file mode 100644
index be18129..0000000
--- a/src/com/android/gallery3d/filtershow/filters/FilterTinyPlanetRepresentation.java
+++ /dev/null
@@ -1,101 +0,0 @@
-/*
- * 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.gallery3d.filtershow.filters;
-
-import com.android.gallery3d.R;
-import com.android.gallery3d.filtershow.editors.EditorTinyPlanet;
-
-public class FilterTinyPlanetRepresentation extends FilterBasicRepresentation {
-    private static final String SERIALIZATION_NAME = "TINYPLANET";
-    private static final String LOGTAG = "FilterTinyPlanetRepresentation";
-    private static final String SERIAL_ANGLE = "Angle";
-    private float mAngle = 0;
-
-    public FilterTinyPlanetRepresentation() {
-        super("TinyPlanet", 0, 50, 100);
-        setSerializationName(SERIALIZATION_NAME);
-        setShowParameterValue(true);
-        setFilterClass(ImageFilterTinyPlanet.class);
-        setFilterType(FilterRepresentation.TYPE_TINYPLANET);
-        setTextId(R.string.tinyplanet);
-        setEditorId(EditorTinyPlanet.ID);
-        setMinimum(1);
-    }
-
-    @Override
-    public FilterRepresentation copy() {
-        FilterTinyPlanetRepresentation representation = new FilterTinyPlanetRepresentation();
-        copyAllParameters(representation);
-        return representation;
-    }
-
-    @Override
-    protected void copyAllParameters(FilterRepresentation representation) {
-        super.copyAllParameters(representation);
-        representation.useParametersFrom(this);
-    }
-
-    @Override
-    public void useParametersFrom(FilterRepresentation a) {
-        FilterTinyPlanetRepresentation representation = (FilterTinyPlanetRepresentation) a;
-        super.useParametersFrom(a);
-        mAngle = representation.mAngle;
-        setZoom(representation.getZoom());
-    }
-
-    public void setAngle(float angle) {
-        mAngle = angle;
-    }
-
-    public float getAngle() {
-        return mAngle;
-    }
-
-    public int getZoom() {
-        return getValue();
-    }
-
-    public void setZoom(int zoom) {
-        setValue(zoom);
-    }
-
-    public boolean isNil() {
-        // TinyPlanet always has an effect
-        return false;
-    }
-
-    @Override
-    public String[][] serializeRepresentation() {
-        String[][] ret = {
-                {SERIAL_NAME  , getName() },
-                {SERIAL_VALUE , Integer.toString(getValue())},
-                {SERIAL_ANGLE , Float.toString(mAngle)}};
-        return ret;
-    }
-
-    @Override
-    public void deSerializeRepresentation(String[][] rep) {
-        super.deSerializeRepresentation(rep);
-        for (int i = 0; i < rep.length; i++) {
-            if (SERIAL_VALUE.equals(rep[i][0])) {
-                setValue(Integer.parseInt(rep[i][1]));
-            } else if (SERIAL_ANGLE.equals(rep[i][0])) {
-                setAngle(Float.parseFloat(rep[i][1]));
-            }
-        }
-    }
-}
diff --git a/src/com/android/gallery3d/filtershow/filters/FilterUserPresetRepresentation.java b/src/com/android/gallery3d/filtershow/filters/FilterUserPresetRepresentation.java
deleted file mode 100644
index dfdb6fc..0000000
--- a/src/com/android/gallery3d/filtershow/filters/FilterUserPresetRepresentation.java
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Copyright (C) 2013 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.gallery3d.filtershow.filters;
-
-import com.android.gallery3d.filtershow.editors.ImageOnlyEditor;
-import com.android.gallery3d.filtershow.pipeline.ImagePreset;
-
-public class FilterUserPresetRepresentation extends FilterRepresentation {
-
-    private ImagePreset mPreset;
-    private int mId;
-
-    public FilterUserPresetRepresentation(String name, ImagePreset preset, int id) {
-        super(name);
-        setEditorId(ImageOnlyEditor.ID);
-        setFilterType(FilterRepresentation.TYPE_FX);
-        mPreset = preset;
-        mId = id;
-    }
-
-    public ImagePreset getImagePreset() {
-        return mPreset;
-    }
-
-    public int getId() {
-        return mId;
-    }
-
-    public FilterRepresentation copy(){
-        FilterRepresentation representation = new FilterUserPresetRepresentation(getName(),
-                new ImagePreset(mPreset), mId);
-        return representation;
-    }
-
-    @Override
-    public boolean allowsSingleInstanceOnly() {
-        return true;
-    }
-}
diff --git a/src/com/android/gallery3d/filtershow/filters/FilterVignetteRepresentation.java b/src/com/android/gallery3d/filtershow/filters/FilterVignetteRepresentation.java
deleted file mode 100644
index 42a7406..0000000
--- a/src/com/android/gallery3d/filtershow/filters/FilterVignetteRepresentation.java
+++ /dev/null
@@ -1,173 +0,0 @@
-/*
- * 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.gallery3d.filtershow.filters;
-
-import com.android.gallery3d.R;
-import com.android.gallery3d.filtershow.editors.EditorVignette;
-import com.android.gallery3d.filtershow.imageshow.Oval;
-
-public class FilterVignetteRepresentation extends FilterBasicRepresentation implements Oval {
-    private static final String LOGTAG = "FilterVignetteRepresentation";
-    private float mCenterX = Float.NaN;
-    private float mCenterY;
-    private float mRadiusX = Float.NaN;
-    private float mRadiusY;
-
-    public FilterVignetteRepresentation() {
-        super("Vignette", -100, 50, 100);
-        setSerializationName("VIGNETTE");
-        setShowParameterValue(true);
-        setFilterType(FilterRepresentation.TYPE_VIGNETTE);
-        setTextId(R.string.vignette);
-        setEditorId(EditorVignette.ID);
-        setName("Vignette");
-        setFilterClass(ImageFilterVignette.class);
-        setMinimum(-100);
-        setMaximum(100);
-        setDefaultValue(0);
-    }
-
-    @Override
-    public void useParametersFrom(FilterRepresentation a) {
-        super.useParametersFrom(a);
-        mCenterX = ((FilterVignetteRepresentation) a).mCenterX;
-        mCenterY = ((FilterVignetteRepresentation) a).mCenterY;
-        mRadiusX = ((FilterVignetteRepresentation) a).mRadiusX;
-        mRadiusY = ((FilterVignetteRepresentation) a).mRadiusY;
-    }
-
-    @Override
-    public FilterRepresentation copy() {
-        FilterVignetteRepresentation representation = new FilterVignetteRepresentation();
-        copyAllParameters(representation);
-        return representation;
-    }
-
-    @Override
-    protected void copyAllParameters(FilterRepresentation representation) {
-        super.copyAllParameters(representation);
-        representation.useParametersFrom(this);
-    }
-
-    @Override
-    public void setCenter(float centerX, float centerY) {
-        mCenterX = centerX;
-        mCenterY = centerY;
-    }
-
-    @Override
-    public float getCenterX() {
-        return mCenterX;
-    }
-
-    @Override
-    public float getCenterY() {
-        return mCenterY;
-    }
-
-    @Override
-    public void setRadius(float radiusX, float radiusY) {
-        mRadiusX = radiusX;
-        mRadiusY = radiusY;
-    }
-
-    @Override
-    public void setRadiusX(float radiusX) {
-        mRadiusX = radiusX;
-    }
-
-    @Override
-    public void setRadiusY(float radiusY) {
-        mRadiusY = radiusY;
-    }
-
-    @Override
-    public float getRadiusX() {
-        return mRadiusX;
-    }
-
-    @Override
-    public float getRadiusY() {
-        return mRadiusY;
-    }
-
-    public boolean isCenterSet() {
-        return mCenterX != Float.NaN;
-    }
-
-    @Override
-    public boolean isNil() {
-        return getValue() == 0;
-    }
-
-    @Override
-    public boolean equals(FilterRepresentation representation) {
-        if (!super.equals(representation)) {
-            return false;
-        }
-        if (representation instanceof FilterVignetteRepresentation) {
-            FilterVignetteRepresentation rep = (FilterVignetteRepresentation) representation;
-            if (rep.getCenterX() == getCenterX()
-                    && rep.getCenterY() == getCenterY()
-                    && rep.getRadiusX() == getRadiusX()
-                    && rep.getRadiusY() == getRadiusY()) {
-                return true;
-            }
-        }
-        return false;
-    }
-
-    private static final String[] sParams = {
-            "Name", "value", "mCenterX", "mCenterY", "mRadiusX",
-            "mRadiusY"
-    };
-
-    @Override
-    public String[][] serializeRepresentation() {
-        String[][] ret = {
-                { sParams[0], getName() },
-                { sParams[1], Integer.toString(getValue()) },
-                { sParams[2], Float.toString(mCenterX) },
-                { sParams[3], Float.toString(mCenterY) },
-                { sParams[4], Float.toString(mRadiusX) },
-                { sParams[5], Float.toString(mRadiusY) }
-        };
-        return ret;
-    }
-
-    @Override
-    public void deSerializeRepresentation(String[][] rep) {
-        super.deSerializeRepresentation(rep);
-        for (int i = 0; i < rep.length; i++) {
-            String key = rep[i][0];
-            String value = rep[i][1];
-            if (sParams[0].equals(key)) {
-                setName(value);
-            } else if (sParams[1].equals(key)) {
-               setValue(Integer.parseInt(value));
-            } else if (sParams[2].equals(key)) {
-                mCenterX = Float.parseFloat(value);
-            } else if (sParams[3].equals(key)) {
-                mCenterY = Float.parseFloat(value);
-            } else if (sParams[4].equals(key)) {
-                mRadiusX = Float.parseFloat(value);
-            } else if (sParams[5].equals(key)) {
-                mRadiusY = Float.parseFloat(value);
-            }
-        }
-    }
-}
diff --git a/src/com/android/gallery3d/filtershow/filters/FiltersManagerInterface.java b/src/com/android/gallery3d/filtershow/filters/FiltersManagerInterface.java
deleted file mode 100644
index 710128f..0000000
--- a/src/com/android/gallery3d/filtershow/filters/FiltersManagerInterface.java
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- * Copyright (C) 2013 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.gallery3d.filtershow.filters;
-
-public interface FiltersManagerInterface {
-   ImageFilter getFilterForRepresentation(FilterRepresentation representation);
-}
diff --git a/src/com/android/gallery3d/filtershow/filters/IconUtilities.java b/src/com/android/gallery3d/filtershow/filters/IconUtilities.java
deleted file mode 100644
index e2a0147..0000000
--- a/src/com/android/gallery3d/filtershow/filters/IconUtilities.java
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * Copyright (C) 2013 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.gallery3d.filtershow.filters;
-
-import android.content.res.Resources;
-import android.graphics.Bitmap;
-import android.graphics.BitmapFactory;
-
-import com.android.gallery3d.R;
-
-public class IconUtilities {
-    public static final int PUNCH = R.drawable.filtershow_fx_0005_punch;
-    public static final int VINTAGE = R.drawable.filtershow_fx_0000_vintage;
-    public static final int BW_CONTRAST = R.drawable.filtershow_fx_0004_bw_contrast;
-    public static final int BLEACH = R.drawable.filtershow_fx_0002_bleach;
-    public static final int INSTANT = R.drawable.filtershow_fx_0001_instant;
-    public static final int WASHOUT = R.drawable.filtershow_fx_0007_washout;
-    public static final int BLUECRUSH = R.drawable.filtershow_fx_0003_blue_crush;
-    public static final int WASHOUT_COLOR = R.drawable.filtershow_fx_0008_washout_color;
-    public static final int X_PROCESS = R.drawable.filtershow_fx_0006_x_process;
-
-    public static Bitmap getFXBitmap(Resources res, int id) {
-        Bitmap ret;
-        BitmapFactory.Options o = new BitmapFactory.Options();
-        o.inScaled = false;
-
-        if (id != 0) {
-            return BitmapFactory.decodeResource(res, id, o);
-        }
-        return null;
-    }
-
-    public static Bitmap loadBitmap(Resources res, int resource) {
-
-        final BitmapFactory.Options options = new BitmapFactory.Options();
-        options.inPreferredConfig = Bitmap.Config.ARGB_8888;
-        Bitmap bitmap = BitmapFactory.decodeResource(
-                res,
-                resource, options);
-
-        return bitmap;
-    }
-
-    public static Bitmap applyFX(Bitmap bitmap, final Bitmap fxBitmap) {
-        ImageFilterFx fx = new ImageFilterFx() {
-            @Override
-            public Bitmap apply(Bitmap bitmap, float scaleFactor, int quality) {
-
-                int w = bitmap.getWidth();
-                int h = bitmap.getHeight();
-                int fxw = fxBitmap.getWidth();
-                int fxh = fxBitmap.getHeight();
-                int start = 0;
-                int end = w * h * 4;
-                nativeApplyFilter(bitmap, w, h, fxBitmap, fxw, fxh, start, end);
-                return bitmap;
-            }
-        };
-        return fx.apply(bitmap, 0, 0);
-    }
-}
diff --git a/src/com/android/gallery3d/filtershow/filters/ImageFilter.java b/src/com/android/gallery3d/filtershow/filters/ImageFilter.java
deleted file mode 100644
index 4371374..0000000
--- a/src/com/android/gallery3d/filtershow/filters/ImageFilter.java
+++ /dev/null
@@ -1,109 +0,0 @@
-/*
- * 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.gallery3d.filtershow.filters;
-
-import android.app.Activity;
-import android.graphics.Bitmap;
-import android.graphics.Matrix;
-import android.support.v8.renderscript.Allocation;
-import android.widget.Toast;
-
-import com.android.gallery3d.filtershow.imageshow.GeometryMathUtils;
-import com.android.gallery3d.filtershow.imageshow.MasterImage;
-import com.android.gallery3d.filtershow.pipeline.FilterEnvironment;
-
-public abstract class ImageFilter implements Cloneable {
-    private FilterEnvironment mEnvironment = null;
-
-    protected String mName = "Original";
-    private final String LOGTAG = "ImageFilter";
-    protected static final boolean SIMPLE_ICONS = true;
-    // TODO: Temporary, for dogfood note memory issues with toasts for better
-    // feedback. Remove this when filters actually work in low memory
-    // situations.
-    private static Activity sActivity = null;
-
-    public static void setActivityForMemoryToasts(Activity activity) {
-        sActivity = activity;
-    }
-
-    public static void resetStatics() {
-        sActivity = null;
-    }
-
-    public void freeResources() {}
-
-    public void displayLowMemoryToast() {
-        if (sActivity != null) {
-            sActivity.runOnUiThread(new Runnable() {
-                public void run() {
-                    Toast.makeText(sActivity, "Memory too low for filter " + getName() +
-                            ", please file a bug report", Toast.LENGTH_SHORT).show();
-                }
-            });
-        }
-    }
-
-    public void setName(String name) {
-        mName = name;
-    }
-
-    public String getName() {
-        return mName;
-    }
-
-    public boolean supportsAllocationInput() { return false; }
-
-    public void apply(Allocation in, Allocation out) {
-        setGeneralParameters();
-    }
-
-    public Bitmap apply(Bitmap bitmap, float scaleFactor, int quality) {
-        // do nothing here, subclasses will implement filtering here
-        setGeneralParameters();
-        return bitmap;
-    }
-
-    public abstract void useRepresentation(FilterRepresentation representation);
-
-    native protected void nativeApplyGradientFilter(Bitmap bitmap, int w, int h,
-            int[] redGradient, int[] greenGradient, int[] blueGradient);
-
-    public FilterRepresentation getDefaultRepresentation() {
-        return null;
-    }
-
-    protected Matrix getOriginalToScreenMatrix(int w, int h) {
-        return GeometryMathUtils.getImageToScreenMatrix(getEnvironment().getImagePreset()
-                .getGeometryFilters(), true, MasterImage.getImage().getOriginalBounds(), w, h);
-    }
-
-    public void setEnvironment(FilterEnvironment environment) {
-        mEnvironment = environment;
-    }
-
-    public FilterEnvironment getEnvironment() {
-        return mEnvironment;
-    }
-
-    public void setGeneralParameters() {
-        // should implement in subclass which like to transport
-        // some information to other filters. (like the style setting from RetroLux
-        // and Film to FixedFrame)
-        mEnvironment.clearGeneralParameters();
-    }
-}
diff --git a/src/com/android/gallery3d/filtershow/filters/ImageFilterBorder.java b/src/com/android/gallery3d/filtershow/filters/ImageFilterBorder.java
deleted file mode 100644
index a7286f0..0000000
--- a/src/com/android/gallery3d/filtershow/filters/ImageFilterBorder.java
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- * 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.gallery3d.filtershow.filters;
-
-import android.content.res.Resources;
-import android.graphics.Bitmap;
-import android.graphics.BitmapFactory;
-import android.graphics.Canvas;
-import android.graphics.Rect;
-import android.graphics.drawable.BitmapDrawable;
-import android.graphics.drawable.Drawable;
-
-import java.util.HashMap;
-
-public class ImageFilterBorder extends ImageFilter {
-    private static final float NINEPATCH_ICON_SCALING = 10;
-    private static final float BITMAP_ICON_SCALING = 1 / 3.0f;
-    private FilterImageBorderRepresentation mParameters = null;
-    private Resources mResources = null;
-
-    private HashMap<Integer, Drawable> mDrawables = new HashMap<Integer, Drawable>();
-
-    public ImageFilterBorder() {
-        mName = "Border";
-    }
-
-    public void useRepresentation(FilterRepresentation representation) {
-        FilterImageBorderRepresentation parameters = (FilterImageBorderRepresentation) representation;
-        mParameters = parameters;
-    }
-
-    public FilterImageBorderRepresentation getParameters() {
-        return mParameters;
-    }
-
-    public void freeResources() {
-       mDrawables.clear();
-    }
-
-    public Bitmap applyHelper(Bitmap bitmap, float scale1, float scale2 ) {
-        int w = bitmap.getWidth();
-        int h = bitmap.getHeight();
-        Rect bounds = new Rect(0, 0, (int) (w * scale1), (int) (h * scale1));
-        Canvas canvas = new Canvas(bitmap);
-        canvas.scale(scale2, scale2);
-        Drawable drawable = getDrawable(getParameters().getDrawableResource());
-        drawable.setBounds(bounds);
-        drawable.draw(canvas);
-        return bitmap;
-    }
-
-    @Override
-    public Bitmap apply(Bitmap bitmap, float scaleFactor, int quality) {
-        if (getParameters() == null || getParameters().getDrawableResource() == 0) {
-            return bitmap;
-        }
-        float scale2 = scaleFactor * 2.0f;
-        float scale1 = 1 / scale2;
-        return applyHelper(bitmap, scale1, scale2);
-    }
-
-    public void setResources(Resources resources) {
-        if (mResources != resources) {
-            mResources = resources;
-            mDrawables.clear();
-        }
-    }
-
-    public Drawable getDrawable(int rsc) {
-        Drawable drawable = mDrawables.get(rsc);
-        if (drawable == null && mResources != null && rsc != 0) {
-            drawable = new BitmapDrawable(mResources, BitmapFactory.decodeResource(mResources, rsc));
-            mDrawables.put(rsc, drawable);
-        }
-        return drawable;
-    }
-
-}
diff --git a/src/com/android/gallery3d/filtershow/filters/ImageFilterBwFilter.java b/src/com/android/gallery3d/filtershow/filters/ImageFilterBwFilter.java
deleted file mode 100644
index 50837ca..0000000
--- a/src/com/android/gallery3d/filtershow/filters/ImageFilterBwFilter.java
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * 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.gallery3d.filtershow.filters;
-
-import com.android.gallery3d.R;
-
-import android.graphics.Bitmap;
-import android.graphics.Color;
-
-
-public class ImageFilterBwFilter extends SimpleImageFilter {
-    private static final String SERIALIZATION_NAME = "BWFILTER";
-
-    public ImageFilterBwFilter() {
-        mName = "BW Filter";
-    }
-
-    public FilterRepresentation getDefaultRepresentation() {
-        FilterBasicRepresentation representation = (FilterBasicRepresentation) super.getDefaultRepresentation();
-        representation.setName("BW Filter");
-        representation.setSerializationName(SERIALIZATION_NAME);
-
-        representation.setFilterClass(ImageFilterBwFilter.class);
-        representation.setMaximum(180);
-        representation.setMinimum(-180);
-        representation.setTextId(R.string.bwfilter);
-        representation.setSupportsPartialRendering(true);
-        return representation;
-    }
-
-    native protected void nativeApplyFilter(Bitmap bitmap, int w, int h, int r, int g, int b);
-
-    @Override
-    public Bitmap apply(Bitmap bitmap, float scaleFactor, int quality) {
-        if (getParameters() == null) {
-            return bitmap;
-        }
-        int w = bitmap.getWidth();
-        int h = bitmap.getHeight();
-        float[] hsv = new float[] {
-                180 + getParameters().getValue(), 1, 1
-        };
-        int rgb = Color.HSVToColor(hsv);
-        int r = 0xFF & (rgb >> 16);
-        int g = 0xFF & (rgb >> 8);
-        int b = 0xFF & (rgb >> 0);
-        nativeApplyFilter(bitmap, w, h, r, g, b);
-        return bitmap;
-    }
-}
diff --git a/src/com/android/gallery3d/filtershow/filters/ImageFilterChanSat.java b/src/com/android/gallery3d/filtershow/filters/ImageFilterChanSat.java
deleted file mode 100644
index 1ea8edf..0000000
--- a/src/com/android/gallery3d/filtershow/filters/ImageFilterChanSat.java
+++ /dev/null
@@ -1,161 +0,0 @@
-/*
- * Copyright (C) 2013 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.gallery3d.filtershow.filters;
-
-import android.graphics.Bitmap;
-import android.graphics.Matrix;
-import android.support.v8.renderscript.Allocation;
-import android.support.v8.renderscript.Element;
-import android.support.v8.renderscript.RenderScript;
-import android.support.v8.renderscript.Script.LaunchOptions;
-import android.support.v8.renderscript.Type;
-
-import com.android.gallery3d.R;
-import com.android.gallery3d.filtershow.pipeline.FilterEnvironment;
-
-public class ImageFilterChanSat extends ImageFilterRS {
-    private static final String LOGTAG = "ImageFilterChanSat";
-    private ScriptC_saturation mScript;
-    private Bitmap mSourceBitmap;
-
-    private static final int STRIP_SIZE = 64;
-
-    FilterChanSatRepresentation mParameters = new FilterChanSatRepresentation();
-    private Bitmap mOverlayBitmap;
-
-    public ImageFilterChanSat() {
-        mName = "ChannelSat";
-    }
-
-    @Override
-    public FilterRepresentation getDefaultRepresentation() {
-        return new FilterChanSatRepresentation();
-    }
-
-    @Override
-    public void useRepresentation(FilterRepresentation representation) {
-        mParameters = (FilterChanSatRepresentation) representation;
-    }
-
-    @Override
-    protected void resetAllocations() {
-
-    }
-
-    @Override
-    public void resetScripts() {
-        if (mScript != null) {
-            mScript.destroy();
-            mScript = null;
-        }
-    }
-    @Override
-    protected void createFilter(android.content.res.Resources res, float scaleFactor,
-                                int quality) {
-        createFilter(res, scaleFactor, quality, getInPixelsAllocation());
-    }
-
-    @Override
-    protected void createFilter(android.content.res.Resources res, float scaleFactor,
-                                int quality, Allocation in) {
-        RenderScript rsCtx = getRenderScriptContext();
-
-        Type.Builder tb_float = new Type.Builder(rsCtx, Element.F32_4(rsCtx));
-        tb_float.setX(in.getType().getX());
-        tb_float.setY(in.getType().getY());
-        mScript = new ScriptC_saturation(rsCtx, res, R.raw.saturation);
-    }
-
-
-    private Bitmap getSourceBitmap() {
-        assert (mSourceBitmap != null);
-        return mSourceBitmap;
-    }
-
-    @Override
-    public Bitmap apply(Bitmap bitmap, float scaleFactor, int quality) {
-        if (SIMPLE_ICONS && FilterEnvironment.QUALITY_ICON == quality) {
-            return bitmap;
-        }
-
-        mSourceBitmap = bitmap;
-        Bitmap ret = super.apply(bitmap, scaleFactor, quality);
-        mSourceBitmap = null;
-
-        return ret;
-    }
-
-    @Override
-    protected void bindScriptValues() {
-        int width = getInPixelsAllocation().getType().getX();
-        int height = getInPixelsAllocation().getType().getY();
-    }
-
-
-
-    @Override
-    protected void runFilter() {
-        int []sat = new int[7];
-        for(int i = 0;i<sat.length ;i ++){
-          sat[i] =   mParameters.getValue(i);
-        }
-
-
-        int width = getInPixelsAllocation().getType().getX();
-        int height = getInPixelsAllocation().getType().getY();
-        Matrix m = getOriginalToScreenMatrix(width, height);
-
-
-        mScript.set_saturation(sat);
-
-        mScript.invoke_setupGradParams();
-        runSelectiveAdjust(
-                getInPixelsAllocation(), getOutPixelsAllocation());
-
-    }
-
-    private void runSelectiveAdjust(Allocation in, Allocation out) {
-        int width = in.getType().getX();
-        int height = in.getType().getY();
-
-        LaunchOptions options = new LaunchOptions();
-        int ty;
-        options.setX(0, width);
-
-        for (ty = 0; ty < height; ty += STRIP_SIZE) {
-            int endy = ty + STRIP_SIZE;
-            if (endy > height) {
-                endy = height;
-            }
-            options.setY(ty, endy);
-            mScript.forEach_selectiveAdjust(in, out, options);
-            if (checkStop()) {
-                return;
-            }
-        }
-    }
-
-    private boolean checkStop() {
-        RenderScript rsCtx = getRenderScriptContext();
-        rsCtx.finish();
-        if (getEnvironment().needsStop()) {
-            return true;
-        }
-        return false;
-    }
-}
-
diff --git a/src/com/android/gallery3d/filtershow/filters/ImageFilterContrast.java b/src/com/android/gallery3d/filtershow/filters/ImageFilterContrast.java
deleted file mode 100644
index 27c0e08..0000000
--- a/src/com/android/gallery3d/filtershow/filters/ImageFilterContrast.java
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * 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.gallery3d.filtershow.filters;
-
-import com.android.gallery3d.R;
-
-import android.graphics.Bitmap;
-
-public class ImageFilterContrast extends SimpleImageFilter {
-    private static final String SERIALIZATION_NAME = "CONTRAST";
-
-    public ImageFilterContrast() {
-        mName = "Contrast";
-    }
-
-    public FilterRepresentation getDefaultRepresentation() {
-        FilterBasicRepresentation representation =
-                (FilterBasicRepresentation) super.getDefaultRepresentation();
-        representation.setName("Contrast");
-        representation.setSerializationName(SERIALIZATION_NAME);
-
-        representation.setFilterClass(ImageFilterContrast.class);
-        representation.setTextId(R.string.contrast);
-        representation.setMinimum(-100);
-        representation.setMaximum(100);
-        representation.setDefaultValue(0);
-        representation.setSupportsPartialRendering(true);
-        return representation;
-    }
-
-    native protected void nativeApplyFilter(Bitmap bitmap, int w, int h, float strength);
-
-    @Override
-    public Bitmap apply(Bitmap bitmap, float scaleFactor, int quality) {
-        if (getParameters() == null) {
-            return bitmap;
-        }
-        int w = bitmap.getWidth();
-        int h = bitmap.getHeight();
-        float value = getParameters().getValue();
-        nativeApplyFilter(bitmap, w, h, value);
-        return bitmap;
-    }
-}
diff --git a/src/com/android/gallery3d/filtershow/filters/ImageFilterCurves.java b/src/com/android/gallery3d/filtershow/filters/ImageFilterCurves.java
deleted file mode 100644
index 61b60d2..0000000
--- a/src/com/android/gallery3d/filtershow/filters/ImageFilterCurves.java
+++ /dev/null
@@ -1,112 +0,0 @@
-/*
- * 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.gallery3d.filtershow.filters;
-
-import android.graphics.Bitmap;
-
-import com.android.gallery3d.filtershow.imageshow.Spline;
-
-public class ImageFilterCurves extends ImageFilter {
-
-    private static final String LOGTAG = "ImageFilterCurves";
-    FilterCurvesRepresentation mParameters = new FilterCurvesRepresentation();
-
-    @Override
-    public FilterRepresentation getDefaultRepresentation() {
-        return new FilterCurvesRepresentation();
-    }
-
-    @Override
-    public void useRepresentation(FilterRepresentation representation) {
-        FilterCurvesRepresentation parameters = (FilterCurvesRepresentation) representation;
-        mParameters = parameters;
-    }
-
-    public ImageFilterCurves() {
-        mName = "Curves";
-        reset();
-    }
-
-    public void populateArray(int[] array, int curveIndex) {
-        Spline spline = mParameters.getSpline(curveIndex);
-        if (spline == null) {
-            return;
-        }
-        float[] curve = spline.getAppliedCurve();
-        for (int i = 0; i < 256; i++) {
-            array[i] = (int) (curve[i] * 255);
-        }
-    }
-
-    @Override
-    public Bitmap apply(Bitmap bitmap, float scaleFactor, int quality) {
-        if (!mParameters.getSpline(Spline.RGB).isOriginal()) {
-            int[] rgbGradient = new int[256];
-            populateArray(rgbGradient, Spline.RGB);
-            nativeApplyGradientFilter(bitmap, bitmap.getWidth(), bitmap.getHeight(),
-                    rgbGradient, rgbGradient, rgbGradient);
-        }
-
-        int[] redGradient = null;
-        if (!mParameters.getSpline(Spline.RED).isOriginal()) {
-            redGradient = new int[256];
-            populateArray(redGradient, Spline.RED);
-        }
-        int[] greenGradient = null;
-        if (!mParameters.getSpline(Spline.GREEN).isOriginal()) {
-            greenGradient = new int[256];
-            populateArray(greenGradient, Spline.GREEN);
-        }
-        int[] blueGradient = null;
-        if (!mParameters.getSpline(Spline.BLUE).isOriginal()) {
-            blueGradient = new int[256];
-            populateArray(blueGradient, Spline.BLUE);
-        }
-
-        nativeApplyGradientFilter(bitmap, bitmap.getWidth(), bitmap.getHeight(),
-                redGradient, greenGradient, blueGradient);
-        return bitmap;
-    }
-
-    public void setSpline(Spline spline, int splineIndex) {
-        mParameters.setSpline(splineIndex, new Spline(spline));
-    }
-
-    public Spline getSpline(int splineIndex) {
-        return mParameters.getSpline(splineIndex);
-    }
-
-    public void reset() {
-        Spline spline = new Spline();
-
-        spline.addPoint(0.0f, 1.0f);
-        spline.addPoint(1.0f, 0.0f);
-
-        for (int i = 0; i < 4; i++) {
-            mParameters.setSpline(i, new Spline(spline));
-        }
-    }
-
-    public void useFilter(ImageFilter a) {
-        ImageFilterCurves c = (ImageFilterCurves) a;
-        for (int i = 0; i < 4; i++) {
-            if (c.mParameters.getSpline(i) != null) {
-                setSpline(c.mParameters.getSpline(i), i);
-            }
-        }
-    }
-}
diff --git a/src/com/android/gallery3d/filtershow/filters/ImageFilterDownsample.java b/src/com/android/gallery3d/filtershow/filters/ImageFilterDownsample.java
deleted file mode 100644
index efb9cde..0000000
--- a/src/com/android/gallery3d/filtershow/filters/ImageFilterDownsample.java
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * 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.gallery3d.filtershow.filters;
-
-import android.graphics.Bitmap;
-import android.graphics.Canvas;
-import android.graphics.Rect;
-
-import com.android.gallery3d.R;
-import com.android.gallery3d.filtershow.cache.ImageLoader;
-import com.android.gallery3d.filtershow.imageshow.MasterImage;
-
-public class ImageFilterDownsample extends SimpleImageFilter {
-    private static final String SERIALIZATION_NAME = "DOWNSAMPLE";
-    private static final int ICON_DOWNSAMPLE_FRACTION = 8;
-    private ImageLoader mImageLoader;
-
-    public ImageFilterDownsample(ImageLoader loader) {
-        mName = "Downsample";
-        mImageLoader = loader;
-    }
-
-    public FilterRepresentation getDefaultRepresentation() {
-        FilterBasicRepresentation representation = (FilterBasicRepresentation) super.getDefaultRepresentation();
-        representation.setName("Downsample");
-        representation.setSerializationName(SERIALIZATION_NAME);
-
-        representation.setFilterClass(ImageFilterDownsample.class);
-        representation.setMaximum(100);
-        representation.setMinimum(1);
-        representation.setValue(50);
-        representation.setDefaultValue(50);
-        representation.setPreviewValue(3);
-        representation.setTextId(R.string.downsample);
-        return representation;
-    }
-
-    @Override
-    public Bitmap apply(Bitmap bitmap, float scaleFactor, int quality) {
-        if (getParameters() == null) {
-            return bitmap;
-        }
-        int w = bitmap.getWidth();
-        int h = bitmap.getHeight();
-        int p = getParameters().getValue();
-
-        // size of original precached image
-        Rect size = MasterImage.getImage().getOriginalBounds();
-        int orig_w = size.width();
-        int orig_h = size.height();
-
-        if (p > 0 && p < 100) {
-            // scale preview to same size as the resulting bitmap from a "save"
-            int newWidth = orig_w * p / 100;
-            int newHeight = orig_h * p / 100;
-
-            // only scale preview if preview isn't already scaled enough
-            if (newWidth <= 0 || newHeight <= 0 || newWidth >= w || newHeight >= h) {
-                return bitmap;
-            }
-            Bitmap ret = Bitmap.createScaledBitmap(bitmap, newWidth, newHeight, true);
-            if (ret != bitmap) {
-                bitmap.recycle();
-            }
-            return ret;
-        }
-        return bitmap;
-    }
-}
diff --git a/src/com/android/gallery3d/filtershow/filters/ImageFilterDraw.java b/src/com/android/gallery3d/filtershow/filters/ImageFilterDraw.java
deleted file mode 100644
index 7df5ffb..0000000
--- a/src/com/android/gallery3d/filtershow/filters/ImageFilterDraw.java
+++ /dev/null
@@ -1,278 +0,0 @@
-/*
- * 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.gallery3d.filtershow.filters;
-
-import android.graphics.Bitmap;
-import android.graphics.BitmapFactory;
-import android.graphics.Canvas;
-import android.graphics.Color;
-import android.graphics.Matrix;
-import android.graphics.Paint;
-import android.graphics.Paint.Style;
-import android.graphics.Path;
-import android.graphics.PathMeasure;
-import android.graphics.PorterDuff;
-import android.graphics.PorterDuffColorFilter;
-
-import com.android.gallery3d.R;
-import com.android.gallery3d.filtershow.cache.ImageLoader;
-import com.android.gallery3d.filtershow.filters.FilterDrawRepresentation.StrokeData;
-import com.android.gallery3d.filtershow.imageshow.MasterImage;
-import com.android.gallery3d.filtershow.pipeline.FilterEnvironment;
-
-import java.util.Vector;
-
-public class ImageFilterDraw extends ImageFilter {
-    private static final String LOGTAG = "ImageFilterDraw";
-    public final static byte SIMPLE_STYLE = 0;
-    public final static byte BRUSH_STYLE_SPATTER = 1;
-    public final static byte BRUSH_STYLE_MARKER = 2;
-    public final static int NUMBER_OF_STYLES = 3;
-    Bitmap mOverlayBitmap; // this accelerates interaction
-    int mCachedStrokes = -1;
-    int mCurrentStyle = 0;
-
-    FilterDrawRepresentation mParameters = new FilterDrawRepresentation();
-
-    public ImageFilterDraw() {
-        mName = "Image Draw";
-    }
-
-    DrawStyle[] mDrawingsTypes = new DrawStyle[] {
-            new SimpleDraw(),
-            new Brush(R.drawable.brush_marker),
-            new Brush(R.drawable.brush_spatter)
-    };
-    {
-        for (int i = 0; i < mDrawingsTypes.length; i++) {
-            mDrawingsTypes[i].setType((byte) i);
-        }
-
-    }
-
-    @Override
-    public FilterRepresentation getDefaultRepresentation() {
-        return new FilterDrawRepresentation();
-    }
-
-    @Override
-    public void useRepresentation(FilterRepresentation representation) {
-        FilterDrawRepresentation parameters = (FilterDrawRepresentation) representation;
-        mParameters = parameters;
-    }
-
-    public void setStyle(byte style) {
-        mCurrentStyle = style % mDrawingsTypes.length;
-    }
-
-    public int getStyle() {
-        return mCurrentStyle;
-    }
-
-    public static interface DrawStyle {
-        public void setType(byte type);
-        public void paint(FilterDrawRepresentation.StrokeData sd, Canvas canvas, Matrix toScrMatrix,
-                int quality);
-    }
-
-    class SimpleDraw implements DrawStyle {
-        byte mType;
-
-        @Override
-        public void setType(byte type) {
-            mType = type;
-        }
-
-        @Override
-        public void paint(FilterDrawRepresentation.StrokeData sd, Canvas canvas, Matrix toScrMatrix,
-                int quality) {
-            if (sd == null) {
-                return;
-            }
-            if (sd.mPath == null) {
-                return;
-            }
-            Paint paint = new Paint();
-
-            paint.setStyle(Style.STROKE);
-            paint.setColor(sd.mColor);
-            paint.setStrokeWidth(toScrMatrix.mapRadius(sd.mRadius));
-
-            // done this way because of a bug in path.transform(matrix)
-            Path mCacheTransPath = new Path();
-            mCacheTransPath.addPath(sd.mPath, toScrMatrix);
-
-            canvas.drawPath(mCacheTransPath, paint);
-        }
-    }
-
-    class Brush implements DrawStyle {
-        int mBrushID;
-        Bitmap mBrush;
-        byte mType;
-
-        public Brush(int brushID) {
-            mBrushID = brushID;
-        }
-
-        public Bitmap getBrush() {
-            if (mBrush == null) {
-                BitmapFactory.Options opt = new BitmapFactory.Options();
-                opt.inPreferredConfig = Bitmap.Config.ALPHA_8;
-                mBrush = BitmapFactory.decodeResource(MasterImage.getImage().getActivity()
-                        .getResources(), mBrushID, opt);
-                mBrush = mBrush.extractAlpha();
-            }
-            return mBrush;
-        }
-
-        @Override
-        public void paint(FilterDrawRepresentation.StrokeData sd, Canvas canvas,
-                Matrix toScrMatrix,
-                int quality) {
-            if (sd == null || sd.mPath == null) {
-                return;
-            }
-            Paint paint = new Paint();
-            paint.setStyle(Style.STROKE);
-            paint.setAntiAlias(true);
-            Path mCacheTransPath = new Path();
-            mCacheTransPath.addPath(sd.mPath, toScrMatrix);
-            draw(canvas, paint, sd.mColor, toScrMatrix.mapRadius(sd.mRadius) * 2,
-                    mCacheTransPath);
-        }
-
-        public Bitmap createScaledBitmap(Bitmap src, int dstWidth, int dstHeight, boolean filter)
-        {
-            Matrix m = new Matrix();
-            m.setScale(dstWidth / (float) src.getWidth(), dstHeight / (float) src.getHeight());
-            Bitmap result = Bitmap.createBitmap(dstWidth, dstHeight, src.getConfig());
-            Canvas canvas = new Canvas(result);
-
-            Paint paint = new Paint();
-            paint.setFilterBitmap(filter);
-            canvas.drawBitmap(src, m, paint);
-
-            return result;
-
-        }
-        void draw(Canvas canvas, Paint paint, int color, float size, Path path) {
-            PathMeasure mPathMeasure = new PathMeasure();
-            float[] mPosition = new float[2];
-            float[] mTan = new float[2];
-
-            mPathMeasure.setPath(path, false);
-
-            paint.setAntiAlias(true);
-            paint.setColor(color);
-
-            paint.setColorFilter(new PorterDuffColorFilter(color, PorterDuff.Mode.MULTIPLY));
-            Bitmap brush;
-            // done this way because of a bug in
-            // Bitmap.createScaledBitmap(getBrush(),(int) size,(int) size,true);
-            brush = createScaledBitmap(getBrush(), (int) size, (int) size, true);
-            float len = mPathMeasure.getLength();
-            float s2 = size / 2;
-            float step = s2 / 8;
-            for (float i = 0; i < len; i += step) {
-                mPathMeasure.getPosTan(i, mPosition, mTan);
-                //                canvas.drawCircle(pos[0], pos[1], size, paint);
-                canvas.drawBitmap(brush, mPosition[0] - s2, mPosition[1] - s2, paint);
-            }
-        }
-
-        @Override
-        public void setType(byte type) {
-            mType = type;
-        }
-    }
-
-    void paint(FilterDrawRepresentation.StrokeData sd, Canvas canvas, Matrix toScrMatrix,
-            int quality) {
-        mDrawingsTypes[sd.mType].paint(sd, canvas, toScrMatrix, quality);
-    }
-
-    public void drawData(Canvas canvas, Matrix originalRotateToScreen, int quality) {
-        Paint paint = new Paint();
-        if (quality == FilterEnvironment.QUALITY_FINAL) {
-            paint.setAntiAlias(true);
-        }
-        paint.setStyle(Style.STROKE);
-        paint.setColor(Color.RED);
-        paint.setStrokeWidth(40);
-
-        if (mParameters.getDrawing().isEmpty() && mParameters.getCurrentDrawing() == null) {
-            return;
-        }
-        if (quality == FilterEnvironment.QUALITY_FINAL) {
-            for (FilterDrawRepresentation.StrokeData strokeData : mParameters.getDrawing()) {
-                paint(strokeData, canvas, originalRotateToScreen, quality);
-            }
-            return;
-        }
-
-        if (mOverlayBitmap == null ||
-                mOverlayBitmap.getWidth() != canvas.getWidth() ||
-                mOverlayBitmap.getHeight() != canvas.getHeight() ||
-                mParameters.getDrawing().size() < mCachedStrokes) {
-
-            mOverlayBitmap = Bitmap.createBitmap(
-                    canvas.getWidth(), canvas.getHeight(), Bitmap.Config.ARGB_8888);
-            mCachedStrokes = 0;
-        }
-
-        if (mCachedStrokes < mParameters.getDrawing().size()) {
-            fillBuffer(originalRotateToScreen);
-        }
-        canvas.drawBitmap(mOverlayBitmap, 0, 0, paint);
-
-        StrokeData stroke = mParameters.getCurrentDrawing();
-        if (stroke != null) {
-            paint(stroke, canvas, originalRotateToScreen, quality);
-        }
-    }
-
-    public void fillBuffer(Matrix originalRotateToScreen) {
-        Canvas drawCache = new Canvas(mOverlayBitmap);
-        Vector<FilterDrawRepresentation.StrokeData> v = mParameters.getDrawing();
-        int n = v.size();
-
-        for (int i = mCachedStrokes; i < n; i++) {
-            paint(v.get(i), drawCache, originalRotateToScreen, FilterEnvironment.QUALITY_PREVIEW);
-        }
-        mCachedStrokes = n;
-    }
-
-    public void draw(Canvas canvas, Matrix originalRotateToScreen) {
-        for (FilterDrawRepresentation.StrokeData strokeData : mParameters.getDrawing()) {
-            paint(strokeData, canvas, originalRotateToScreen, FilterEnvironment.QUALITY_PREVIEW);
-        }
-        mDrawingsTypes[mCurrentStyle].paint(
-                null, canvas, originalRotateToScreen, FilterEnvironment.QUALITY_PREVIEW);
-    }
-
-    @Override
-    public Bitmap apply(Bitmap bitmap, float scaleFactor, int quality) {
-        int w = bitmap.getWidth();
-        int h = bitmap.getHeight();
-
-        Matrix m = getOriginalToScreenMatrix(w, h);
-        drawData(new Canvas(bitmap), m, quality);
-        return bitmap;
-    }
-
-}
diff --git a/src/com/android/gallery3d/filtershow/filters/ImageFilterEdge.java b/src/com/android/gallery3d/filtershow/filters/ImageFilterEdge.java
deleted file mode 100644
index 2d0d765..0000000
--- a/src/com/android/gallery3d/filtershow/filters/ImageFilterEdge.java
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * 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.gallery3d.filtershow.filters;
-
-import android.graphics.Bitmap;
-
-import com.android.gallery3d.R;
-
-public class ImageFilterEdge extends SimpleImageFilter {
-    private static final String SERIALIZATION_NAME = "EDGE";
-    public ImageFilterEdge() {
-        mName = "Edge";
-    }
-
-    public FilterRepresentation getDefaultRepresentation() {
-        FilterRepresentation representation = super.getDefaultRepresentation();
-        representation.setName("Edge");
-        representation.setSerializationName(SERIALIZATION_NAME);
-        representation.setFilterClass(ImageFilterEdge.class);
-        representation.setTextId(R.string.edge);
-        representation.setSupportsPartialRendering(true);
-        return representation;
-    }
-
-    native protected void nativeApplyFilter(Bitmap bitmap, int w, int h, float p);
-
-    @Override
-    public Bitmap apply(Bitmap bitmap, float scaleFactor, int quality) {
-        if (getParameters() == null) {
-            return bitmap;
-        }
-        int w = bitmap.getWidth();
-        int h = bitmap.getHeight();
-        float p = getParameters().getValue() + 101;
-        p = (float) p / 100;
-        nativeApplyFilter(bitmap, w, h, p);
-        return bitmap;
-    }
-}
diff --git a/src/com/android/gallery3d/filtershow/filters/ImageFilterExposure.java b/src/com/android/gallery3d/filtershow/filters/ImageFilterExposure.java
deleted file mode 100644
index 69eab73..0000000
--- a/src/com/android/gallery3d/filtershow/filters/ImageFilterExposure.java
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * 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.gallery3d.filtershow.filters;
-
-import com.android.gallery3d.R;
-
-import android.graphics.Bitmap;
-
-public class ImageFilterExposure extends SimpleImageFilter {
-    private static final String SERIALIZATION_NAME = "EXPOSURE";
-    public ImageFilterExposure() {
-        mName = "Exposure";
-    }
-
-    public FilterRepresentation getDefaultRepresentation() {
-        FilterBasicRepresentation representation =
-                (FilterBasicRepresentation) super.getDefaultRepresentation();
-        representation.setName("Exposure");
-        representation.setSerializationName(SERIALIZATION_NAME);
-        representation.setFilterClass(ImageFilterExposure.class);
-        representation.setTextId(R.string.exposure);
-        representation.setMinimum(-100);
-        representation.setMaximum(100);
-        representation.setDefaultValue(0);
-        representation.setSupportsPartialRendering(true);
-        return representation;
-    }
-
-    native protected void nativeApplyFilter(Bitmap bitmap, int w, int h, float bright);
-
-    @Override
-    public Bitmap apply(Bitmap bitmap, float scaleFactor, int quality) {
-        if (getParameters() == null) {
-            return bitmap;
-        }
-        int w = bitmap.getWidth();
-        int h = bitmap.getHeight();
-        float value = getParameters().getValue();
-        nativeApplyFilter(bitmap, w, h, value);
-        return bitmap;
-    }
-}
diff --git a/src/com/android/gallery3d/filtershow/filters/ImageFilterFx.java b/src/com/android/gallery3d/filtershow/filters/ImageFilterFx.java
deleted file mode 100644
index 19bea59..0000000
--- a/src/com/android/gallery3d/filtershow/filters/ImageFilterFx.java
+++ /dev/null
@@ -1,111 +0,0 @@
-/*
- * 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.gallery3d.filtershow.filters;
-
-import android.content.res.Resources;
-import android.graphics.Bitmap;
-import android.graphics.BitmapFactory;
-import com.android.gallery3d.app.Log;
-
-public class ImageFilterFx extends ImageFilter {
-    private static final String LOGTAG = "ImageFilterFx";
-    private FilterFxRepresentation mParameters = null;
-    private Bitmap mFxBitmap = null;
-    private Resources mResources = null;
-    private int mFxBitmapId = 0;
-
-    public ImageFilterFx() {
-    }
-
-    @Override
-    public void freeResources() {
-        if (mFxBitmap != null) mFxBitmap.recycle();
-        mFxBitmap = null;
-    }
-
-    @Override
-    public FilterRepresentation getDefaultRepresentation() {
-        return null;
-    }
-
-    public void useRepresentation(FilterRepresentation representation) {
-        FilterFxRepresentation parameters = (FilterFxRepresentation) representation;
-        mParameters = parameters;
-    }
-
-    public FilterFxRepresentation getParameters() {
-        return mParameters;
-    }
-
-    native protected void nativeApplyFilter(Bitmap bitmap, int w, int h,
-                                            Bitmap fxBitmap, int fxw, int fxh,
-                                            int start, int end);
-
-    @Override
-    public Bitmap apply(Bitmap bitmap, float scaleFactor, int quality) {
-        if (getParameters() == null || mResources == null) {
-            return bitmap;
-        }
-
-        int w = bitmap.getWidth();
-        int h = bitmap.getHeight();
-
-        int bitmapResourceId = getParameters().getBitmapResource();
-        if (bitmapResourceId == 0) { // null filter fx
-            return bitmap;
-        }
-
-        if (mFxBitmap == null || mFxBitmapId != bitmapResourceId) {
-            BitmapFactory.Options o = new BitmapFactory.Options();
-            o.inScaled = false;
-            mFxBitmapId = bitmapResourceId;
-            if (mFxBitmapId != 0) {
-                mFxBitmap = BitmapFactory.decodeResource(mResources, mFxBitmapId, o);
-            } else {
-                Log.w(LOGTAG, "bad resource for filter: " + mName);
-            }
-        }
-
-        if (mFxBitmap == null) {
-            return bitmap;
-        }
-
-        int fxw = mFxBitmap.getWidth();
-        int fxh = mFxBitmap.getHeight();
-
-        int stride = w * 4;
-        int max = stride * h;
-        int increment = stride * 256; // 256 lines
-        for (int i = 0; i < max; i += increment) {
-            int start = i;
-            int end = i + increment;
-            if (end > max) {
-                end = max;
-            }
-            if (!getEnvironment().needsStop()) {
-                nativeApplyFilter(bitmap, w, h, mFxBitmap, fxw, fxh, start, end);
-            }
-        }
-
-        return bitmap;
-    }
-
-    public void setResources(Resources resources) {
-        mResources = resources;
-    }
-
-}
diff --git a/src/com/android/gallery3d/filtershow/filters/ImageFilterGrad.java b/src/com/android/gallery3d/filtershow/filters/ImageFilterGrad.java
deleted file mode 100644
index cbdfaa6..0000000
--- a/src/com/android/gallery3d/filtershow/filters/ImageFilterGrad.java
+++ /dev/null
@@ -1,190 +0,0 @@
-/*
- * Copyright (C) 2013 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.gallery3d.filtershow.filters;
-
-import android.graphics.Bitmap;
-import android.graphics.Color;
-import android.graphics.Matrix;
-
-import com.android.gallery3d.R;
-import com.android.gallery3d.filtershow.pipeline.FilterEnvironment;
-
-import android.graphics.Bitmap;
-import android.graphics.Color;
-import android.graphics.Matrix;
-import android.support.v8.renderscript.Allocation;
-import android.support.v8.renderscript.Element;
-import android.support.v8.renderscript.RenderScript;
-import android.support.v8.renderscript.Script.LaunchOptions;
-import android.support.v8.renderscript.Type;
-import android.util.Log;
-
-import com.android.gallery3d.R;
-import com.android.gallery3d.filtershow.pipeline.FilterEnvironment;
-
-public class ImageFilterGrad extends ImageFilterRS {
-    private static final String LOGTAG = "ImageFilterGrad";
-    private ScriptC_grad mScript;
-    private Bitmap mSourceBitmap;
-    private static final int RADIUS_SCALE_FACTOR = 160;
-
-    private static final int STRIP_SIZE = 64;
-
-    FilterGradRepresentation mParameters = new FilterGradRepresentation();
-    private Bitmap mOverlayBitmap;
-
-    public ImageFilterGrad() {
-        mName = "grad";
-    }
-
-    @Override
-    public FilterRepresentation getDefaultRepresentation() {
-        return new FilterGradRepresentation();
-    }
-
-    @Override
-    public void useRepresentation(FilterRepresentation representation) {
-        mParameters = (FilterGradRepresentation) representation;
-    }
-
-    @Override
-    protected void resetAllocations() {
-
-    }
-
-    @Override
-    public void resetScripts() {
-        if (mScript != null) {
-            mScript.destroy();
-            mScript = null;
-        }
-    }
-    @Override
-    protected void createFilter(android.content.res.Resources res, float scaleFactor,
-                                int quality) {
-        createFilter(res, scaleFactor, quality, getInPixelsAllocation());
-    }
-
-    @Override
-    protected void createFilter(android.content.res.Resources res, float scaleFactor,
-                                int quality, Allocation in) {
-        RenderScript rsCtx = getRenderScriptContext();
-
-        Type.Builder tb_float = new Type.Builder(rsCtx, Element.F32_4(rsCtx));
-        tb_float.setX(in.getType().getX());
-        tb_float.setY(in.getType().getY());
-        mScript = new ScriptC_grad(rsCtx, res, R.raw.grad);
-    }
-
-
-    private Bitmap getSourceBitmap() {
-        assert (mSourceBitmap != null);
-        return mSourceBitmap;
-    }
-
-    @Override
-    public Bitmap apply(Bitmap bitmap, float scaleFactor, int quality) {
-        if (SIMPLE_ICONS && FilterEnvironment.QUALITY_ICON == quality) {
-            return bitmap;
-        }
-
-        mSourceBitmap = bitmap;
-        Bitmap ret = super.apply(bitmap, scaleFactor, quality);
-        mSourceBitmap = null;
-
-        return ret;
-    }
-
-    @Override
-    protected void bindScriptValues() {
-        int width = getInPixelsAllocation().getType().getX();
-        int height = getInPixelsAllocation().getType().getY();
-        mScript.set_inputWidth(width);
-        mScript.set_inputHeight(height);
-    }
-
-    @Override
-    protected void runFilter() {
-        int[] x1 = mParameters.getXPos1();
-        int[] y1 = mParameters.getYPos1();
-        int[] x2 = mParameters.getXPos2();
-        int[] y2 = mParameters.getYPos2();
-
-        int width = getInPixelsAllocation().getType().getX();
-        int height = getInPixelsAllocation().getType().getY();
-        Matrix m = getOriginalToScreenMatrix(width, height);
-        float[] coord = new float[2];
-        for (int i = 0; i < x1.length; i++) {
-            coord[0] = x1[i];
-            coord[1] = y1[i];
-            m.mapPoints(coord);
-            x1[i] = (int) coord[0];
-            y1[i] = (int) coord[1];
-            coord[0] = x2[i];
-            coord[1] = y2[i];
-            m.mapPoints(coord);
-            x2[i] = (int) coord[0];
-            y2[i] = (int) coord[1];
-        }
-
-        mScript.set_mask(mParameters.getMask());
-        mScript.set_xPos1(x1);
-        mScript.set_yPos1(y1);
-        mScript.set_xPos2(x2);
-        mScript.set_yPos2(y2);
-
-        mScript.set_brightness(mParameters.getBrightness());
-        mScript.set_contrast(mParameters.getContrast());
-        mScript.set_saturation(mParameters.getSaturation());
-
-        mScript.invoke_setupGradParams();
-        runSelectiveAdjust(
-                getInPixelsAllocation(), getOutPixelsAllocation());
-
-    }
-
-    private void runSelectiveAdjust(Allocation in, Allocation out) {
-        int width = in.getType().getX();
-        int height = in.getType().getY();
-
-        LaunchOptions options = new LaunchOptions();
-        int ty;
-        options.setX(0, width);
-
-        for (ty = 0; ty < height; ty += STRIP_SIZE) {
-            int endy = ty + STRIP_SIZE;
-            if (endy > height) {
-                endy = height;
-            }
-            options.setY(ty, endy);
-            mScript.forEach_selectiveAdjust(in, out, options);
-            if (checkStop()) {
-                return;
-            }
-        }
-    }
-
-    private boolean checkStop() {
-        RenderScript rsCtx = getRenderScriptContext();
-        rsCtx.finish();
-        if (getEnvironment().needsStop()) {
-            return true;
-        }
-        return false;
-    }
-}
-
diff --git a/src/com/android/gallery3d/filtershow/filters/ImageFilterHighlights.java b/src/com/android/gallery3d/filtershow/filters/ImageFilterHighlights.java
deleted file mode 100644
index 4c837e0..0000000
--- a/src/com/android/gallery3d/filtershow/filters/ImageFilterHighlights.java
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * Copyright (C) 2013 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.gallery3d.filtershow.filters;
-
-import android.graphics.Bitmap;
-
-import com.android.gallery3d.R;
-
-public class ImageFilterHighlights extends SimpleImageFilter {
-    private static final String SERIALIZATION_NAME = "HIGHLIGHTS";
-    private static final String LOGTAG = "ImageFilterVignette";
-
-    public ImageFilterHighlights() {
-        mName = "Highlights";
-    }
-
-    SplineMath mSpline = new SplineMath(5);
-    double[] mHighlightCurve = { 0.0, 0.32, 0.418, 0.476, 0.642 };
-
-    public FilterRepresentation getDefaultRepresentation() {
-        FilterBasicRepresentation representation =
-                (FilterBasicRepresentation) super.getDefaultRepresentation();
-        representation.setName("Highlights");
-        representation.setSerializationName(SERIALIZATION_NAME);
-        representation.setFilterClass(ImageFilterHighlights.class);
-        representation.setTextId(R.string.highlight_recovery);
-        representation.setMinimum(-100);
-        representation.setMaximum(100);
-        representation.setDefaultValue(0);
-        representation.setSupportsPartialRendering(true);
-        return representation;
-    }
-
-    native protected void nativeApplyFilter(Bitmap bitmap, int w, int h, float[] luminanceMap);
-
-    @Override
-    public Bitmap apply(Bitmap bitmap, float scaleFactor, int quality) {
-        if (getParameters() == null) {
-            return bitmap;
-        }
-        float p = getParameters().getValue();
-        double t = p/100.;
-        for (int i = 0; i < 5; i++) {
-            double x = i / 4.;
-            double y = mHighlightCurve[i] *t+x*(1-t);
-            mSpline.setPoint(i, x, y);
-        }
-
-        float[][] curve = mSpline.calculatetCurve(256);
-        float[] luminanceMap = new float[curve.length];
-        for (int i = 0; i < luminanceMap.length; i++) {
-            luminanceMap[i] = curve[i][1];
-        }
-        int w = bitmap.getWidth();
-        int h = bitmap.getHeight();
-
-        nativeApplyFilter(bitmap, w, h, luminanceMap);
-        return bitmap;
-    }
-}
diff --git a/src/com/android/gallery3d/filtershow/filters/ImageFilterHue.java b/src/com/android/gallery3d/filtershow/filters/ImageFilterHue.java
deleted file mode 100644
index b87c254..0000000
--- a/src/com/android/gallery3d/filtershow/filters/ImageFilterHue.java
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * 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.gallery3d.filtershow.filters;
-
-import com.android.gallery3d.R;
-import com.android.gallery3d.filtershow.editors.BasicEditor;
-
-import android.graphics.Bitmap;
-
-public class ImageFilterHue extends SimpleImageFilter {
-    private static final String SERIALIZATION_NAME = "HUE";
-    private ColorSpaceMatrix cmatrix = null;
-
-    public ImageFilterHue() {
-        mName = "Hue";
-        cmatrix = new ColorSpaceMatrix();
-    }
-
-    public FilterRepresentation getDefaultRepresentation() {
-        FilterBasicRepresentation representation =
-                (FilterBasicRepresentation) super.getDefaultRepresentation();
-        representation.setName("Hue");
-        representation.setSerializationName(SERIALIZATION_NAME);
-        representation.setFilterClass(ImageFilterHue.class);
-        representation.setMinimum(-180);
-        representation.setMaximum(180);
-        representation.setTextId(R.string.hue);
-        representation.setEditorId(BasicEditor.ID);
-        representation.setSupportsPartialRendering(true);
-        return representation;
-    }
-
-    native protected void nativeApplyFilter(Bitmap bitmap, int w, int h, float []matrix);
-
-    @Override
-    public Bitmap apply(Bitmap bitmap, float scaleFactor, int quality) {
-        if (getParameters() == null) {
-            return bitmap;
-        }
-        int w = bitmap.getWidth();
-        int h = bitmap.getHeight();
-        float value = getParameters().getValue();
-        cmatrix.identity();
-        cmatrix.setHue(value);
-
-        nativeApplyFilter(bitmap, w, h, cmatrix.getMatrix());
-
-        return bitmap;
-    }
-}
diff --git a/src/com/android/gallery3d/filtershow/filters/ImageFilterKMeans.java b/src/com/android/gallery3d/filtershow/filters/ImageFilterKMeans.java
deleted file mode 100644
index 77cdf47..0000000
--- a/src/com/android/gallery3d/filtershow/filters/ImageFilterKMeans.java
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- * 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.gallery3d.filtershow.filters;
-
-import android.graphics.Bitmap;
-import android.text.format.Time;
-
-import com.android.gallery3d.R;
-
-public class ImageFilterKMeans extends SimpleImageFilter {
-    private static final String SERIALIZATION_NAME = "KMEANS";
-    private int mSeed = 0;
-
-    public ImageFilterKMeans() {
-        mName = "KMeans";
-
-        // set random seed for session
-        Time t = new Time();
-        t.setToNow();
-        mSeed = (int) t.toMillis(false);
-    }
-
-    public FilterRepresentation getDefaultRepresentation() {
-        FilterBasicRepresentation representation = (FilterBasicRepresentation) super.getDefaultRepresentation();
-        representation.setName("KMeans");
-        representation.setSerializationName(SERIALIZATION_NAME);
-        representation.setFilterClass(ImageFilterKMeans.class);
-        representation.setMaximum(20);
-        representation.setMinimum(2);
-        representation.setValue(4);
-        representation.setDefaultValue(4);
-        representation.setPreviewValue(4);
-        representation.setTextId(R.string.kmeans);
-        representation.setSupportsPartialRendering(true);
-        return representation;
-    }
-
-    native protected void nativeApplyFilter(Bitmap bitmap, int width, int height,
-            Bitmap large_ds_bm, int lwidth, int lheight, Bitmap small_ds_bm,
-            int swidth, int sheight, int p, int seed);
-
-    @Override
-    public Bitmap apply(Bitmap bitmap, float scaleFactor, int quality) {
-        if (getParameters() == null) {
-            return bitmap;
-        }
-        int w = bitmap.getWidth();
-        int h = bitmap.getHeight();
-
-        Bitmap large_bm_ds = bitmap;
-        Bitmap small_bm_ds = bitmap;
-
-        // find width/height for larger downsampled bitmap
-        int lw = w;
-        int lh = h;
-        while (lw > 256 && lh > 256) {
-            lw /= 2;
-            lh /= 2;
-        }
-        if (lw != w) {
-            large_bm_ds = Bitmap.createScaledBitmap(bitmap, lw, lh, true);
-        }
-
-        // find width/height for smaller downsampled bitmap
-        int sw = lw;
-        int sh = lh;
-        while (sw > 64 && sh > 64) {
-            sw /= 2;
-            sh /= 2;
-        }
-        if (sw != lw) {
-            small_bm_ds = Bitmap.createScaledBitmap(large_bm_ds, sw, sh, true);
-        }
-
-        if (getParameters() != null) {
-            int p = Math.max(getParameters().getValue(), getParameters().getMinimum()) % (getParameters().getMaximum() + 1);
-            nativeApplyFilter(bitmap, w, h, large_bm_ds, lw, lh, small_bm_ds, sw, sh, p, mSeed);
-        }
-        return bitmap;
-    }
-}
diff --git a/src/com/android/gallery3d/filtershow/filters/ImageFilterNegative.java b/src/com/android/gallery3d/filtershow/filters/ImageFilterNegative.java
deleted file mode 100644
index 9849759..0000000
--- a/src/com/android/gallery3d/filtershow/filters/ImageFilterNegative.java
+++ /dev/null
@@ -1,39 +0,0 @@
-package com.android.gallery3d.filtershow.filters;
-
-import android.graphics.Bitmap;
-
-import com.android.gallery3d.R;
-import com.android.gallery3d.filtershow.editors.ImageOnlyEditor;
-
-public class ImageFilterNegative extends ImageFilter {
-    private static final String SERIALIZATION_NAME = "NEGATIVE";
-    public ImageFilterNegative() {
-        mName = "Negative";
-    }
-
-    public FilterRepresentation getDefaultRepresentation() {
-        FilterRepresentation representation = new FilterDirectRepresentation("Negative");
-        representation.setSerializationName(SERIALIZATION_NAME);
-        representation.setFilterClass(ImageFilterNegative.class);
-        representation.setTextId(R.string.negative);
-        representation.setShowParameterValue(false);
-        representation.setEditorId(ImageOnlyEditor.ID);
-        representation.setSupportsPartialRendering(true);
-        return representation;
-    }
-
-    native protected void nativeApplyFilter(Bitmap bitmap, int w, int h);
-
-    @Override
-    public void useRepresentation(FilterRepresentation representation) {
-
-    }
-
-    @Override
-    public Bitmap apply(Bitmap bitmap, float scaleFactor, int quality) {
-        int w = bitmap.getWidth();
-        int h = bitmap.getHeight();
-        nativeApplyFilter(bitmap, w, h);
-        return bitmap;
-    }
-}
diff --git a/src/com/android/gallery3d/filtershow/filters/ImageFilterParametricBorder.java b/src/com/android/gallery3d/filtershow/filters/ImageFilterParametricBorder.java
deleted file mode 100644
index 25e5d14..0000000
--- a/src/com/android/gallery3d/filtershow/filters/ImageFilterParametricBorder.java
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * 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.gallery3d.filtershow.filters;
-
-import android.graphics.Bitmap;
-import android.graphics.Canvas;
-import android.graphics.Paint;
-import android.graphics.Path;
-import android.graphics.RectF;
-
-public class ImageFilterParametricBorder extends ImageFilter {
-    private FilterColorBorderRepresentation mParameters = null;
-
-    public ImageFilterParametricBorder() {
-        mName = "Border";
-    }
-
-    public void useRepresentation(FilterRepresentation representation) {
-        FilterColorBorderRepresentation parameters = (FilterColorBorderRepresentation) representation;
-        mParameters = parameters;
-    }
-
-    public FilterColorBorderRepresentation getParameters() {
-        return mParameters;
-    }
-
-    private void applyHelper(Canvas canvas, int w, int h) {
-        if (getParameters() == null) {
-            return;
-        }
-        Path border = new Path();
-        border.moveTo(0, 0);
-        float bs = getParameters().getBorderSize() / 100.0f * w;
-        float r = getParameters().getBorderRadius() / 100.0f * w;
-        border.lineTo(0, h);
-        border.lineTo(w, h);
-        border.lineTo(w, 0);
-        border.lineTo(0, 0);
-        border.addRoundRect(new RectF(bs, bs, w - bs, h - bs),
-                r, r, Path.Direction.CW);
-
-        Paint paint = new Paint();
-        paint.setAntiAlias(true);
-        paint.setColor(getParameters().getColor());
-        canvas.drawPath(border, paint);
-    }
-
-    @Override
-    public Bitmap apply(Bitmap bitmap, float scaleFactor, int quality) {
-       Canvas canvas = new Canvas(bitmap);
-       applyHelper(canvas, bitmap.getWidth(), bitmap.getHeight());
-       return bitmap;
-    }
-
-}
diff --git a/src/com/android/gallery3d/filtershow/filters/ImageFilterRS.java b/src/com/android/gallery3d/filtershow/filters/ImageFilterRS.java
deleted file mode 100644
index 5695ef5..0000000
--- a/src/com/android/gallery3d/filtershow/filters/ImageFilterRS.java
+++ /dev/null
@@ -1,260 +0,0 @@
-/*
- * 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.gallery3d.filtershow.filters;
-
-import android.graphics.Bitmap;
-import android.graphics.BitmapFactory;
-import android.support.v8.renderscript.*;
-import android.util.Log;
-import android.content.res.Resources;
-import com.android.gallery3d.R;
-import com.android.gallery3d.filtershow.pipeline.PipelineInterface;
-
-public abstract class ImageFilterRS extends ImageFilter {
-    private static final String LOGTAG = "ImageFilterRS";
-    private boolean DEBUG = false;
-    private int mLastInputWidth = 0;
-    private int mLastInputHeight = 0;
-    private long mLastTimeCalled;
-
-    public static boolean PERF_LOGGING = false;
-
-    private static ScriptC_grey mGreyConvert = null;
-    private static RenderScript mRScache = null;
-
-    private volatile boolean mResourcesLoaded = false;
-
-    protected abstract void createFilter(android.content.res.Resources res,
-            float scaleFactor, int quality);
-
-    protected void createFilter(android.content.res.Resources res,
-    float scaleFactor, int quality, Allocation in) {}
-    protected void bindScriptValues(Allocation in) {}
-
-    protected abstract void runFilter();
-
-    protected void update(Bitmap bitmap) {
-        getOutPixelsAllocation().copyTo(bitmap);
-    }
-
-    protected RenderScript getRenderScriptContext() {
-        PipelineInterface pipeline = getEnvironment().getPipeline();
-        return pipeline.getRSContext();
-    }
-
-    protected Allocation getInPixelsAllocation() {
-        PipelineInterface pipeline = getEnvironment().getPipeline();
-        return pipeline.getInPixelsAllocation();
-    }
-
-    protected Allocation getOutPixelsAllocation() {
-        PipelineInterface pipeline = getEnvironment().getPipeline();
-        return pipeline.getOutPixelsAllocation();
-    }
-
-    @Override
-    public void apply(Allocation in, Allocation out) {
-        long startOverAll = System.nanoTime();
-        if (PERF_LOGGING) {
-            long delay = (startOverAll - mLastTimeCalled) / 1000;
-            String msg = String.format("%s; image size %dx%d; ", getName(),
-                    in.getType().getX(), in.getType().getY());
-            msg += String.format("called after %.2f ms (%.2f FPS); ",
-                    delay / 1000.f, 1000000.f / delay);
-            Log.i(LOGTAG, msg);
-        }
-        mLastTimeCalled = startOverAll;
-        long startFilter = 0;
-        long endFilter = 0;
-        if (!mResourcesLoaded) {
-            PipelineInterface pipeline = getEnvironment().getPipeline();
-            createFilter(pipeline.getResources(), getEnvironment().getScaleFactor(),
-                    getEnvironment().getQuality(), in);
-            mResourcesLoaded = true;
-        }
-        startFilter = System.nanoTime();
-        bindScriptValues(in);
-        run(in, out);
-        if (PERF_LOGGING) {
-            getRenderScriptContext().finish();
-            endFilter = System.nanoTime();
-            long endOverAll = System.nanoTime();
-            String msg = String.format("%s; image size %dx%d; ", getName(),
-                    in.getType().getX(), in.getType().getY());
-            long timeOverAll = (endOverAll - startOverAll) / 1000;
-            long timeFilter = (endFilter - startFilter) / 1000;
-            msg += String.format("over all %.2f ms (%.2f FPS); ",
-                    timeOverAll / 1000.f, 1000000.f / timeOverAll);
-            msg += String.format("run filter %.2f ms (%.2f FPS)",
-                    timeFilter / 1000.f, 1000000.f / timeFilter);
-            Log.i(LOGTAG, msg);
-        }
-    }
-
-    protected void run(Allocation in, Allocation out) {}
-
-    @Override
-    public Bitmap apply(Bitmap bitmap, float scaleFactor, int quality) {
-        if (bitmap == null || bitmap.getWidth() == 0 || bitmap.getHeight() == 0) {
-            return bitmap;
-        }
-        try {
-            PipelineInterface pipeline = getEnvironment().getPipeline();
-            if (DEBUG) {
-                Log.v(LOGTAG, "apply filter " + getName() + " in pipeline " + pipeline.getName());
-            }
-            Resources rsc = pipeline.getResources();
-            boolean sizeChanged = false;
-            if (getInPixelsAllocation() != null
-                    && ((getInPixelsAllocation().getType().getX() != mLastInputWidth)
-                    || (getInPixelsAllocation().getType().getY() != mLastInputHeight))) {
-                sizeChanged = true;
-            }
-            if (pipeline.prepareRenderscriptAllocations(bitmap)
-                    || !isResourcesLoaded() || sizeChanged) {
-                freeResources();
-                createFilter(rsc, scaleFactor, quality);
-                setResourcesLoaded(true);
-                mLastInputWidth = getInPixelsAllocation().getType().getX();
-                mLastInputHeight = getInPixelsAllocation().getType().getY();
-            }
-            bindScriptValues();
-            runFilter();
-            update(bitmap);
-            if (DEBUG) {
-                Log.v(LOGTAG, "DONE apply filter " + getName() + " in pipeline " + pipeline.getName());
-            }
-        } catch (android.renderscript.RSIllegalArgumentException e) {
-            Log.e(LOGTAG, "Illegal argument? " + e);
-        } catch (android.renderscript.RSRuntimeException e) {
-            Log.e(LOGTAG, "RS runtime exception ? " + e);
-        } catch (java.lang.OutOfMemoryError e) {
-            // Many of the renderscript filters allocated large (>16Mb resources) in order to apply.
-            System.gc();
-            displayLowMemoryToast();
-            Log.e(LOGTAG, "not enough memory for filter " + getName(), e);
-        }
-        return bitmap;
-    }
-
-    protected static Allocation convertBitmap(RenderScript RS, Bitmap bitmap) {
-        return Allocation.createFromBitmap(RS, bitmap,
-                Allocation.MipmapControl.MIPMAP_NONE,
-                Allocation.USAGE_SCRIPT | Allocation.USAGE_GRAPHICS_TEXTURE);
-    }
-
-    private static Allocation convertRGBAtoA(RenderScript RS, Bitmap bitmap) {
-        if (RS != mRScache || mGreyConvert == null) {
-            mGreyConvert = new ScriptC_grey(RS, RS.getApplicationContext().getResources(),
-                                            R.raw.grey);
-            mRScache = RS;
-        }
-
-        Type.Builder tb_a8 = new Type.Builder(RS, Element.A_8(RS));
-
-        Allocation bitmapTemp = convertBitmap(RS, bitmap);
-        if (bitmapTemp.getType().getElement().isCompatible(Element.A_8(RS))) {
-            return bitmapTemp;
-        }
-
-        tb_a8.setX(bitmapTemp.getType().getX());
-        tb_a8.setY(bitmapTemp.getType().getY());
-        Allocation bitmapAlloc = Allocation.createTyped(RS, tb_a8.create(),
-                                                        Allocation.MipmapControl.MIPMAP_NONE,
-                                                        Allocation.USAGE_SCRIPT | Allocation.USAGE_GRAPHICS_TEXTURE);
-        mGreyConvert.forEach_RGBAtoA(bitmapTemp, bitmapAlloc);
-        bitmapTemp.destroy();
-        return bitmapAlloc;
-    }
-
-    public Allocation loadScaledResourceAlpha(int resource, int inSampleSize) {
-        Resources res = getEnvironment().getPipeline().getResources();
-        final BitmapFactory.Options options = new BitmapFactory.Options();
-        options.inPreferredConfig = Bitmap.Config.ALPHA_8;
-        options.inSampleSize      = inSampleSize;
-        Bitmap bitmap = BitmapFactory.decodeResource(
-                res,
-                resource, options);
-        Allocation ret = convertRGBAtoA(getRenderScriptContext(), bitmap);
-        bitmap.recycle();
-        return ret;
-    }
-
-    public Allocation loadScaledResourceAlpha(int resource, int w, int h, int inSampleSize) {
-        Resources res = getEnvironment().getPipeline().getResources();
-        final BitmapFactory.Options options = new BitmapFactory.Options();
-        options.inPreferredConfig = Bitmap.Config.ALPHA_8;
-        options.inSampleSize      = inSampleSize;
-        Bitmap bitmap = BitmapFactory.decodeResource(
-                res,
-                resource, options);
-        Bitmap resizeBitmap = Bitmap.createScaledBitmap(bitmap, w, h, true);
-        Allocation ret = convertRGBAtoA(getRenderScriptContext(), resizeBitmap);
-        resizeBitmap.recycle();
-        bitmap.recycle();
-        return ret;
-    }
-
-    public Allocation loadResourceAlpha(int resource) {
-        return loadScaledResourceAlpha(resource, 1);
-    }
-
-    public Allocation loadResource(int resource) {
-        Resources res = getEnvironment().getPipeline().getResources();
-        final BitmapFactory.Options options = new BitmapFactory.Options();
-        options.inPreferredConfig = Bitmap.Config.ARGB_8888;
-        Bitmap bitmap = BitmapFactory.decodeResource(
-                res,
-                resource, options);
-        Allocation ret = convertBitmap(getRenderScriptContext(), bitmap);
-        bitmap.recycle();
-        return ret;
-    }
-
-    private boolean isResourcesLoaded() {
-        return mResourcesLoaded;
-    }
-
-    private void setResourcesLoaded(boolean resourcesLoaded) {
-        mResourcesLoaded = resourcesLoaded;
-    }
-
-    /**
-     *  Bitmaps and RS Allocations should be cleared here
-     */
-    abstract protected void resetAllocations();
-
-    /**
-     * RS Script objects (and all other RS objects) should be cleared here
-     */
-    public abstract void resetScripts();
-
-    /**
-     * Scripts values should be bound here
-     */
-    abstract protected void bindScriptValues();
-
-    public void freeResources() {
-        if (!isResourcesLoaded()) {
-            return;
-        }
-        resetAllocations();
-        mLastInputWidth = 0;
-        mLastInputHeight = 0;
-        setResourcesLoaded(false);
-    }
-}
diff --git a/src/com/android/gallery3d/filtershow/filters/ImageFilterRedEye.java b/src/com/android/gallery3d/filtershow/filters/ImageFilterRedEye.java
deleted file mode 100644
index 511f9e9..0000000
--- a/src/com/android/gallery3d/filtershow/filters/ImageFilterRedEye.java
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * Copyright (C) 2013 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.gallery3d.filtershow.filters;
-
-import android.graphics.Bitmap;
-import android.graphics.Matrix;
-import android.graphics.RectF;
-
-import java.util.Vector;
-
-public class ImageFilterRedEye extends ImageFilter {
-    private static final String LOGTAG = "ImageFilterRedEye";
-    FilterRedEyeRepresentation mParameters = new FilterRedEyeRepresentation();
-
-    public ImageFilterRedEye() {
-        mName = "Red Eye";
-    }
-
-    @Override
-    public FilterRepresentation getDefaultRepresentation() {
-        return new FilterRedEyeRepresentation();
-    }
-
-    public boolean isNil() {
-        return mParameters.isNil();
-    }
-
-    public Vector<FilterPoint> getCandidates() {
-        return mParameters.getCandidates();
-    }
-
-    public void clear() {
-        mParameters.clearCandidates();
-    }
-
-    native protected void nativeApplyFilter(Bitmap bitmap, int w, int h, short[] matrix);
-
-    @Override
-    public void useRepresentation(FilterRepresentation representation) {
-        FilterRedEyeRepresentation parameters = (FilterRedEyeRepresentation) representation;
-        mParameters = parameters;
-    }
-
-    @Override
-    public Bitmap apply(Bitmap bitmap, float scaleFactor, int quality) {
-        int w = bitmap.getWidth();
-        int h = bitmap.getHeight();
-        short[] rect = new short[4];
-
-        int size = mParameters.getNumberOfCandidates();
-        Matrix originalToScreen = getOriginalToScreenMatrix(w, h);
-        for (int i = 0; i < size; i++) {
-            RectF r = new RectF(((RedEyeCandidate) (mParameters.getCandidate(i))).mRect);
-            originalToScreen.mapRect(r);
-            if (r.intersect(0, 0, w, h)) {
-                rect[0] = (short) r.left;
-                rect[1] = (short) r.top;
-                rect[2] = (short) r.width();
-                rect[3] = (short) r.height();
-                nativeApplyFilter(bitmap, w, h, rect);
-            }
-        }
-        return bitmap;
-    }
-}
diff --git a/src/com/android/gallery3d/filtershow/filters/ImageFilterSaturated.java b/src/com/android/gallery3d/filtershow/filters/ImageFilterSaturated.java
deleted file mode 100644
index c3124ff..0000000
--- a/src/com/android/gallery3d/filtershow/filters/ImageFilterSaturated.java
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * 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.gallery3d.filtershow.filters;
-
-import com.android.gallery3d.R;
-
-import android.graphics.Bitmap;
-
-public class ImageFilterSaturated extends SimpleImageFilter {
-    private static final String SERIALIZATION_NAME = "SATURATED";
-    public ImageFilterSaturated() {
-        mName = "Saturated";
-    }
-
-    @Override
-    public FilterRepresentation getDefaultRepresentation() {
-        FilterBasicRepresentation representation =
-                (FilterBasicRepresentation) super.getDefaultRepresentation();
-        representation.setName("Saturated");
-        representation.setSerializationName(SERIALIZATION_NAME);
-        representation.setFilterClass(ImageFilterSaturated.class);
-        representation.setTextId(R.string.saturation);
-        representation.setMinimum(-100);
-        representation.setMaximum(100);
-        representation.setDefaultValue(0);
-        representation.setSupportsPartialRendering(true);
-        return representation;
-    }
-
-    native protected void nativeApplyFilter(Bitmap bitmap, int w, int h, float saturation);
-
-    @Override
-    public Bitmap apply(Bitmap bitmap, float scaleFactor, int quality) {
-        if (getParameters() == null) {
-            return bitmap;
-        }
-        int w = bitmap.getWidth();
-        int h = bitmap.getHeight();
-        int p = getParameters().getValue();
-        float value = 1 +  p / 100.0f;
-        nativeApplyFilter(bitmap, w, h, value);
-        return bitmap;
-    }
-}
diff --git a/src/com/android/gallery3d/filtershow/filters/ImageFilterShadows.java b/src/com/android/gallery3d/filtershow/filters/ImageFilterShadows.java
deleted file mode 100644
index bd119bb..0000000
--- a/src/com/android/gallery3d/filtershow/filters/ImageFilterShadows.java
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * 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.gallery3d.filtershow.filters;
-
-import com.android.gallery3d.R;
-
-import android.graphics.Bitmap;
-
-public class ImageFilterShadows extends SimpleImageFilter {
-    private static final String SERIALIZATION_NAME = "SHADOWS";
-    public ImageFilterShadows() {
-        mName = "Shadows";
-
-    }
-
-    public FilterRepresentation getDefaultRepresentation() {
-        FilterBasicRepresentation representation =
-                (FilterBasicRepresentation) super.getDefaultRepresentation();
-        representation.setName("Shadows");
-        representation.setSerializationName(SERIALIZATION_NAME);
-        representation.setFilterClass(ImageFilterShadows.class);
-        representation.setTextId(R.string.shadow_recovery);
-        representation.setMinimum(-100);
-        representation.setMaximum(100);
-        representation.setDefaultValue(0);
-        representation.setSupportsPartialRendering(true);
-        return representation;
-    }
-
-    native protected void nativeApplyFilter(Bitmap bitmap, int w, int h, float  factor);
-
-    @Override
-    public Bitmap apply(Bitmap bitmap, float scaleFactor, int quality) {
-        if (getParameters() == null) {
-            return bitmap;
-        }
-        int w = bitmap.getWidth();
-        int h = bitmap.getHeight();
-        float p = getParameters().getValue();
-
-        nativeApplyFilter(bitmap, w, h, p);
-        return bitmap;
-    }
-}
diff --git a/src/com/android/gallery3d/filtershow/filters/ImageFilterSharpen.java b/src/com/android/gallery3d/filtershow/filters/ImageFilterSharpen.java
deleted file mode 100644
index 3bd7944..0000000
--- a/src/com/android/gallery3d/filtershow/filters/ImageFilterSharpen.java
+++ /dev/null
@@ -1,107 +0,0 @@
-/*
- * 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.gallery3d.filtershow.filters;
-
-import com.android.gallery3d.R;
-
-public class ImageFilterSharpen extends ImageFilterRS {
-    private static final String SERIALIZATION_NAME = "SHARPEN";
-    private static final String LOGTAG = "ImageFilterSharpen";
-    private ScriptC_convolve3x3 mScript;
-
-    private FilterBasicRepresentation mParameters;
-
-    public ImageFilterSharpen() {
-        mName = "Sharpen";
-    }
-
-    public FilterRepresentation getDefaultRepresentation() {
-        FilterRepresentation representation = new FilterBasicRepresentation("Sharpen", 0, 0, 100);
-        representation.setSerializationName(SERIALIZATION_NAME);
-        representation.setShowParameterValue(true);
-        representation.setFilterClass(ImageFilterSharpen.class);
-        representation.setTextId(R.string.sharpness);
-        representation.setOverlayId(R.drawable.filtershow_button_colors_sharpen);
-        representation.setEditorId(R.id.imageShow);
-        representation.setSupportsPartialRendering(true);
-        return representation;
-    }
-
-    public void useRepresentation(FilterRepresentation representation) {
-        FilterBasicRepresentation parameters = (FilterBasicRepresentation) representation;
-        mParameters = parameters;
-    }
-
-    @Override
-    protected void resetAllocations() {
-        // nothing to do
-    }
-
-    @Override
-    public void resetScripts() {
-        if (mScript != null) {
-            mScript.destroy();
-            mScript = null;
-        }
-    }
-
-    @Override
-    protected void createFilter(android.content.res.Resources res, float scaleFactor,
-            int quality) {
-        if (mScript == null) {
-            mScript = new ScriptC_convolve3x3(getRenderScriptContext(), res, R.raw.convolve3x3);
-        }
-    }
-
-    private void computeKernel() {
-        float scaleFactor = getEnvironment().getScaleFactor();
-        float p1 = mParameters.getValue() * scaleFactor;
-        float value = p1 / 100.0f;
-        float f[] = new float[9];
-        float p = value;
-        f[0] = -p;
-        f[1] = -p;
-        f[2] = -p;
-        f[3] = -p;
-        f[4] = 8 * p + 1;
-        f[5] = -p;
-        f[6] = -p;
-        f[7] = -p;
-        f[8] = -p;
-        mScript.set_gCoeffs(f);
-    }
-
-    @Override
-    protected void bindScriptValues() {
-        int w = getInPixelsAllocation().getType().getX();
-        int h = getInPixelsAllocation().getType().getY();
-        mScript.set_gWidth(w);
-        mScript.set_gHeight(h);
-    }
-
-    @Override
-    protected void runFilter() {
-        if (mParameters == null) {
-            return;
-        }
-        computeKernel();
-        mScript.set_gIn(getInPixelsAllocation());
-        mScript.bind_gPixels(getInPixelsAllocation());
-        mScript.forEach_root(getInPixelsAllocation(), getOutPixelsAllocation());
-    }
-
-}
diff --git a/src/com/android/gallery3d/filtershow/filters/ImageFilterTinyPlanet.java b/src/com/android/gallery3d/filtershow/filters/ImageFilterTinyPlanet.java
deleted file mode 100644
index 77250bd..0000000
--- a/src/com/android/gallery3d/filtershow/filters/ImageFilterTinyPlanet.java
+++ /dev/null
@@ -1,158 +0,0 @@
-/*
- * 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.gallery3d.filtershow.filters;
-
-import android.graphics.Bitmap;
-import android.graphics.Canvas;
-import android.graphics.RectF;
-
-import com.adobe.xmp.XMPException;
-import com.adobe.xmp.XMPMeta;
-import com.android.gallery3d.app.Log;
-import com.android.gallery3d.filtershow.cache.ImageLoader;
-import com.android.gallery3d.filtershow.imageshow.MasterImage;
-import com.android.gallery3d.filtershow.pipeline.ImagePreset;
-
-/**
- * An image filter which creates a tiny planet projection.
- */
-public class ImageFilterTinyPlanet extends SimpleImageFilter {
-
-
-    private static final String LOGTAG = ImageFilterTinyPlanet.class.getSimpleName();
-    public static final String GOOGLE_PANO_NAMESPACE = "http://ns.google.com/photos/1.0/panorama/";
-    FilterTinyPlanetRepresentation mParameters = new FilterTinyPlanetRepresentation();
-
-    public static final String CROPPED_AREA_IMAGE_WIDTH_PIXELS =
-            "CroppedAreaImageWidthPixels";
-    public static final String CROPPED_AREA_IMAGE_HEIGHT_PIXELS =
-            "CroppedAreaImageHeightPixels";
-    public static final String CROPPED_AREA_FULL_PANO_WIDTH_PIXELS =
-            "FullPanoWidthPixels";
-    public static final String CROPPED_AREA_FULL_PANO_HEIGHT_PIXELS =
-            "FullPanoHeightPixels";
-    public static final String CROPPED_AREA_LEFT =
-            "CroppedAreaLeftPixels";
-    public static final String CROPPED_AREA_TOP =
-            "CroppedAreaTopPixels";
-
-    public ImageFilterTinyPlanet() {
-        mName = "TinyPlanet";
-    }
-
-    @Override
-    public void useRepresentation(FilterRepresentation representation) {
-        FilterTinyPlanetRepresentation parameters = (FilterTinyPlanetRepresentation) representation;
-        mParameters = parameters;
-    }
-
-    @Override
-    public FilterRepresentation getDefaultRepresentation() {
-        return new FilterTinyPlanetRepresentation();
-    }
-
-
-    native protected void nativeApplyFilter(
-            Bitmap bitmapIn, int width, int height, Bitmap bitmapOut, int outSize, float scale,
-            float angle);
-
-
-    @Override
-    public Bitmap apply(Bitmap bitmapIn, float scaleFactor, int quality) {
-        int w = bitmapIn.getWidth();
-        int h = bitmapIn.getHeight();
-        int outputSize = (int) (w / 2f);
-        ImagePreset preset = getEnvironment().getImagePreset();
-        Bitmap mBitmapOut = null;
-        if (preset != null) {
-            XMPMeta xmp = ImageLoader.getXmpObject(MasterImage.getImage().getActivity());
-            // Do nothing, just use bitmapIn as is if we don't have XMP.
-            if(xmp != null) {
-                bitmapIn = applyXmp(bitmapIn, xmp, w);
-            }
-        }
-        if (mBitmapOut != null) {
-            if (outputSize != mBitmapOut.getHeight()) {
-                mBitmapOut = null;
-            }
-        }
-        while (mBitmapOut == null) {
-            try {
-                mBitmapOut = getEnvironment().getBitmap(outputSize, outputSize);
-            } catch (java.lang.OutOfMemoryError e) {
-                System.gc();
-                outputSize /= 2;
-                Log.v(LOGTAG, "No memory to create Full Tiny Planet create half");
-            }
-        }
-        nativeApplyFilter(bitmapIn, bitmapIn.getWidth(), bitmapIn.getHeight(), mBitmapOut,
-                outputSize, mParameters.getZoom() / 100f, mParameters.getAngle());
-
-        return mBitmapOut;
-    }
-
-    private Bitmap applyXmp(Bitmap bitmapIn, XMPMeta xmp, int intermediateWidth) {
-        try {
-            int croppedAreaWidth =
-                    getInt(xmp, CROPPED_AREA_IMAGE_WIDTH_PIXELS);
-            int croppedAreaHeight =
-                    getInt(xmp, CROPPED_AREA_IMAGE_HEIGHT_PIXELS);
-            int fullPanoWidth =
-                    getInt(xmp, CROPPED_AREA_FULL_PANO_WIDTH_PIXELS);
-            int fullPanoHeight =
-                    getInt(xmp, CROPPED_AREA_FULL_PANO_HEIGHT_PIXELS);
-            int left = getInt(xmp, CROPPED_AREA_LEFT);
-            int top = getInt(xmp, CROPPED_AREA_TOP);
-
-            if (fullPanoWidth == 0 || fullPanoHeight == 0) {
-                return bitmapIn;
-            }
-            // Make sure the intermediate image has the similar size to the
-            // input.
-            Bitmap paddedBitmap = null;
-            float scale = intermediateWidth / (float) fullPanoWidth;
-            while (paddedBitmap == null) {
-                try {
-                    paddedBitmap = Bitmap.createBitmap(
-                            (int) (fullPanoWidth * scale), (int) (fullPanoHeight * scale),
-                            Bitmap.Config.ARGB_8888);
-                } catch (java.lang.OutOfMemoryError e) {
-                    System.gc();
-                    scale /= 2;
-                }
-            }
-            Canvas paddedCanvas = new Canvas(paddedBitmap);
-
-            int right = left + croppedAreaWidth;
-            int bottom = top + croppedAreaHeight;
-            RectF destRect = new RectF(left * scale, top * scale, right * scale, bottom * scale);
-            paddedCanvas.drawBitmap(bitmapIn, null, destRect, null);
-            bitmapIn = paddedBitmap;
-        } catch (XMPException ex) {
-            // Do nothing, just use bitmapIn as is.
-        }
-        return bitmapIn;
-    }
-
-    private static int getInt(XMPMeta xmp, String key) throws XMPException {
-        if (xmp.doesPropertyExist(GOOGLE_PANO_NAMESPACE, key)) {
-            return xmp.getPropertyInteger(GOOGLE_PANO_NAMESPACE, key);
-        } else {
-            return 0;
-        }
-    }
-}
diff --git a/src/com/android/gallery3d/filtershow/filters/ImageFilterVibrance.java b/src/com/android/gallery3d/filtershow/filters/ImageFilterVibrance.java
deleted file mode 100644
index 86be9a1..0000000
--- a/src/com/android/gallery3d/filtershow/filters/ImageFilterVibrance.java
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * 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.gallery3d.filtershow.filters;
-
-import com.android.gallery3d.R;
-
-import android.graphics.Bitmap;
-
-public class ImageFilterVibrance extends SimpleImageFilter {
-    private static final String SERIALIZATION_NAME = "VIBRANCE";
-    public ImageFilterVibrance() {
-        mName = "Vibrance";
-    }
-
-    public FilterRepresentation getDefaultRepresentation() {
-        FilterBasicRepresentation representation =
-                (FilterBasicRepresentation) super.getDefaultRepresentation();
-        representation.setName("Vibrance");
-        representation.setSerializationName(SERIALIZATION_NAME);
-        representation.setFilterClass(ImageFilterVibrance.class);
-        representation.setTextId(R.string.vibrance);
-        representation.setMinimum(-100);
-        representation.setMaximum(100);
-        representation.setDefaultValue(0);
-        representation.setSupportsPartialRendering(true);
-        return representation;
-    }
-
-    native protected void nativeApplyFilter(Bitmap bitmap, int w, int h, float bright);
-
-    @Override
-    public Bitmap apply(Bitmap bitmap, float scaleFactor, int quality) {
-        if (getParameters() == null) {
-            return bitmap;
-        }
-        int w = bitmap.getWidth();
-        int h = bitmap.getHeight();
-        float value = getParameters().getValue();
-        nativeApplyFilter(bitmap, w, h, value);
-
-        return bitmap;
-    }
-}
diff --git a/src/com/android/gallery3d/filtershow/filters/ImageFilterVignette.java b/src/com/android/gallery3d/filtershow/filters/ImageFilterVignette.java
deleted file mode 100644
index 7e0a452..0000000
--- a/src/com/android/gallery3d/filtershow/filters/ImageFilterVignette.java
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- * 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.gallery3d.filtershow.filters;
-
-import android.content.res.Resources;
-import android.graphics.Bitmap;
-import android.graphics.Canvas;
-import android.graphics.Matrix;
-import android.graphics.Rect;
-import com.android.gallery3d.R;
-import com.android.gallery3d.filtershow.pipeline.FilterEnvironment;
-
-public class ImageFilterVignette extends SimpleImageFilter {
-    private static final String LOGTAG = "ImageFilterVignette";
-    private Bitmap mOverlayBitmap;
-
-    public ImageFilterVignette() {
-        mName = "Vignette";
-    }
-
-    @Override
-    public FilterRepresentation getDefaultRepresentation() {
-        FilterVignetteRepresentation representation = new FilterVignetteRepresentation();
-        return representation;
-    }
-
-    native protected void nativeApplyFilter(
-            Bitmap bitmap, int w, int h, int cx, int cy, float radx, float rady, float strength);
-
-    private float calcRadius(float cx, float cy, int w, int h) {
-        float d = cx;
-        if (d < (w - cx)) {
-            d = w - cx;
-        }
-        if (d < cy) {
-            d = cy;
-        }
-        if (d < (h - cy)) {
-            d = h - cy;
-        }
-        return d * d * 2.0f;
-    }
-
-    @Override
-    public Bitmap apply(Bitmap bitmap, float scaleFactor, int quality) {
-        if (SIMPLE_ICONS && FilterEnvironment.QUALITY_ICON == quality) {
-            if (mOverlayBitmap == null) {
-                Resources res = getEnvironment().getPipeline().getResources();
-                mOverlayBitmap = IconUtilities.getFXBitmap(res,
-                        R.drawable.filtershow_icon_vignette);
-            }
-            Canvas c = new Canvas(bitmap);
-            int dim = Math.max(bitmap.getWidth(), bitmap.getHeight());
-            Rect r = new Rect(0, 0, dim, dim);
-            c.drawBitmap(mOverlayBitmap, null, r, null);
-            return bitmap;
-        }
-        FilterVignetteRepresentation rep = (FilterVignetteRepresentation) getParameters();
-        if (rep == null) {
-            return bitmap;
-        }
-        int w = bitmap.getWidth();
-        int h = bitmap.getHeight();
-        float value = rep.getValue() / 100.0f;
-        float cx = w / 2;
-        float cy = h / 2;
-        float r = calcRadius(cx, cy, w, h);
-        float rx = r;
-        float ry = r;
-        if (rep.isCenterSet()) {
-            Matrix m = getOriginalToScreenMatrix(w, h);
-            cx = rep.getCenterX();
-            cy = rep.getCenterY();
-            float[] center = new float[] { cx, cy };
-            m.mapPoints(center);
-            cx = center[0];
-            cy = center[1];
-            rx = m.mapRadius(rep.getRadiusX());
-            ry = m.mapRadius(rep.getRadiusY());
-         }
-        nativeApplyFilter(bitmap, w, h, (int) cx, (int) cy, rx, ry, value);
-        return bitmap;
-    }
-}
diff --git a/src/com/android/gallery3d/filtershow/filters/ImageFilterWBalance.java b/src/com/android/gallery3d/filtershow/filters/ImageFilterWBalance.java
deleted file mode 100644
index 6bb88ec..0000000
--- a/src/com/android/gallery3d/filtershow/filters/ImageFilterWBalance.java
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * 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.gallery3d.filtershow.filters;
-
-import com.android.gallery3d.R;
-import com.android.gallery3d.filtershow.editors.ImageOnlyEditor;
-
-import android.graphics.Bitmap;
-
-public class ImageFilterWBalance extends ImageFilter {
-    private static final String SERIALIZATION_NAME = "WBALANCE";
-    private static final String TAG = "ImageFilterWBalance";
-
-    public ImageFilterWBalance() {
-        mName = "WBalance";
-    }
-
-    public FilterRepresentation getDefaultRepresentation() {
-        FilterRepresentation representation = new FilterDirectRepresentation("WBalance");
-        representation.setSerializationName(SERIALIZATION_NAME);
-        representation.setFilterClass(ImageFilterWBalance.class);
-        representation.setFilterType(FilterRepresentation.TYPE_WBALANCE);
-        representation.setTextId(R.string.wbalance);
-        representation.setShowParameterValue(false);
-        representation.setEditorId(ImageOnlyEditor.ID);
-        representation.setSupportsPartialRendering(true);
-        return representation;
-    }
-
-    @Override
-    public void useRepresentation(FilterRepresentation representation) {
-
-    }
-
-    native protected void nativeApplyFilter(Bitmap bitmap, int w, int h, int locX, int locY);
-
-    @Override
-    public Bitmap apply(Bitmap bitmap, float scaleFactor, int quality) {
-        int w = bitmap.getWidth();
-        int h = bitmap.getHeight();
-        nativeApplyFilter(bitmap, w, h, -1, -1);
-        return bitmap;
-    }
-
-}
diff --git a/src/com/android/gallery3d/filtershow/filters/RedEyeCandidate.java b/src/com/android/gallery3d/filtershow/filters/RedEyeCandidate.java
deleted file mode 100644
index a40d4fa..0000000
--- a/src/com/android/gallery3d/filtershow/filters/RedEyeCandidate.java
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Copyright (C) 2013 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.gallery3d.filtershow.filters;
-
-import android.graphics.RectF;
-
-public class RedEyeCandidate implements FilterPoint {
-    RectF mRect = new RectF();
-    RectF mBounds = new RectF();
-
-    public RedEyeCandidate(RedEyeCandidate candidate) {
-        mRect.set(candidate.mRect);
-        mBounds.set(candidate.mBounds);
-    }
-
-    public RedEyeCandidate(RectF rect, RectF bounds) {
-        mRect.set(rect);
-        mBounds.set(bounds);
-    }
-
-    public boolean equals(RedEyeCandidate candidate) {
-        if (candidate.mRect.equals(mRect)
-                && candidate.mBounds.equals(mBounds)) {
-            return true;
-        }
-        return false;
-    }
-
-    public boolean intersect(RectF rect) {
-        return mRect.intersect(rect);
-    }
-
-    public RectF getRect() {
-        return mRect;
-    }
-}
diff --git a/src/com/android/gallery3d/filtershow/filters/SimpleImageFilter.java b/src/com/android/gallery3d/filtershow/filters/SimpleImageFilter.java
deleted file mode 100644
index c891d20..0000000
--- a/src/com/android/gallery3d/filtershow/filters/SimpleImageFilter.java
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright (C) 2013 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.gallery3d.filtershow.filters;
-
-public class SimpleImageFilter extends ImageFilter {
-
-    private FilterBasicRepresentation mParameters;
-
-    public FilterRepresentation getDefaultRepresentation() {
-        FilterRepresentation representation = new FilterBasicRepresentation("Default", 0, 50, 100);
-        representation.setShowParameterValue(true);
-        return representation;
-    }
-
-    public void useRepresentation(FilterRepresentation representation) {
-        FilterBasicRepresentation parameters = (FilterBasicRepresentation) representation;
-        mParameters = parameters;
-    }
-
-    public FilterBasicRepresentation getParameters() {
-        return mParameters;
-    }
-}
diff --git a/src/com/android/gallery3d/filtershow/filters/SplineMath.java b/src/com/android/gallery3d/filtershow/filters/SplineMath.java
deleted file mode 100644
index 5b12d0a..0000000
--- a/src/com/android/gallery3d/filtershow/filters/SplineMath.java
+++ /dev/null
@@ -1,166 +0,0 @@
-package com.android.gallery3d.filtershow.filters;
-
-
-public class SplineMath {
-    double[][] mPoints = new double[6][2];
-    double[] mDerivatives;
-    SplineMath(int n) {
-        mPoints = new double[n][2];
-    }
-
-    public void setPoint(int index, double x, double y) {
-        mPoints[index][0] = x;
-        mPoints[index][1] = y;
-        mDerivatives = null;
-    }
-
-    public float[][] calculatetCurve(int n) {
-        float[][] curve = new float[n][2];
-        double[][] points = new double[mPoints.length][2];
-        for (int i = 0; i < mPoints.length; i++) {
-
-            points[i][0] = mPoints[i][0];
-            points[i][1] = mPoints[i][1];
-
-        }
-        double[] derivatives = solveSystem(points);
-        float start = (float) points[0][0];
-        float end = (float) (points[points.length - 1][0]);
-
-        curve[0][0] = (float) (points[0][0]);
-        curve[0][1] = (float) (points[0][1]);
-        int last = curve.length - 1;
-        curve[last][0] = (float) (points[points.length - 1][0]);
-        curve[last][1] = (float) (points[points.length - 1][1]);
-
-        for (int i = 0; i < curve.length; i++) {
-
-            double[] cur = null;
-            double[] next = null;
-            double x = start + i * (end - start) / (curve.length - 1);
-            int pivot = 0;
-            for (int j = 0; j < points.length - 1; j++) {
-                if (x >= points[j][0] && x <= points[j + 1][0]) {
-                    pivot = j;
-                }
-            }
-            cur = points[pivot];
-            next = points[pivot + 1];
-            if (x <= next[0]) {
-                double x1 = cur[0];
-                double x2 = next[0];
-                double y1 = cur[1];
-                double y2 = next[1];
-
-                // Use the second derivatives to apply the cubic spline
-                // equation:
-                double delta = (x2 - x1);
-                double delta2 = delta * delta;
-                double b = (x - x1) / delta;
-                double a = 1 - b;
-                double ta = a * y1;
-                double tb = b * y2;
-                double tc = (a * a * a - a) * derivatives[pivot];
-                double td = (b * b * b - b) * derivatives[pivot + 1];
-                double y = ta + tb + (delta2 / 6) * (tc + td);
-
-                curve[i][0] = (float) (x);
-                curve[i][1] = (float) (y);
-            } else {
-                curve[i][0] = (float) (next[0]);
-                curve[i][1] = (float) (next[1]);
-            }
-        }
-        return curve;
-    }
-
-    public double getValue(double x) {
-        double[] cur = null;
-        double[] next = null;
-        if (mDerivatives == null)
-            mDerivatives = solveSystem(mPoints);
-        int pivot = 0;
-        for (int j = 0; j < mPoints.length - 1; j++) {
-            pivot = j;
-            if (x <= mPoints[j][0]) {
-                break;
-            }
-        }
-        cur = mPoints[pivot];
-        next = mPoints[pivot + 1];
-        double x1 = cur[0];
-        double x2 = next[0];
-        double y1 = cur[1];
-        double y2 = next[1];
-
-        // Use the second derivatives to apply the cubic spline
-        // equation:
-        double delta = (x2 - x1);
-        double delta2 = delta * delta;
-        double b = (x - x1) / delta;
-        double a = 1 - b;
-        double ta = a * y1;
-        double tb = b * y2;
-        double tc = (a * a * a - a) * mDerivatives[pivot];
-        double td = (b * b * b - b) * mDerivatives[pivot + 1];
-        double y = ta + tb + (delta2 / 6) * (tc + td);
-
-        return y;
-
-    }
-
-    double[] solveSystem(double[][] points) {
-        int n = points.length;
-        double[][] system = new double[n][3];
-        double[] result = new double[n]; // d
-        double[] solution = new double[n]; // returned coefficients
-        system[0][1] = 1;
-        system[n - 1][1] = 1;
-        double d6 = 1.0 / 6.0;
-        double d3 = 1.0 / 3.0;
-
-        // let's create a tridiagonal matrix representing the
-        // system, and apply the TDMA algorithm to solve it
-        // (see http://en.wikipedia.org/wiki/Tridiagonal_matrix_algorithm)
-        for (int i = 1; i < n - 1; i++) {
-            double deltaPrevX = points[i][0] - points[i - 1][0];
-            double deltaX = points[i + 1][0] - points[i - 1][0];
-            double deltaNextX = points[i + 1][0] - points[i][0];
-            double deltaNextY = points[i + 1][1] - points[i][1];
-            double deltaPrevY = points[i][1] - points[i - 1][1];
-            system[i][0] = d6 * deltaPrevX; // a_i
-            system[i][1] = d3 * deltaX; // b_i
-            system[i][2] = d6 * deltaNextX; // c_i
-            result[i] = (deltaNextY / deltaNextX) - (deltaPrevY / deltaPrevX); // d_i
-        }
-
-        // Forward sweep
-        for (int i = 1; i < n; i++) {
-            // m = a_i/b_i-1
-            double m = system[i][0] / system[i - 1][1];
-            // b_i = b_i - m(c_i-1)
-            system[i][1] = system[i][1] - m * system[i - 1][2];
-            // d_i = d_i - m(d_i-1)
-            result[i] = result[i] - m * result[i - 1];
-        }
-
-        // Back substitution
-        solution[n - 1] = result[n - 1] / system[n - 1][1];
-        for (int i = n - 2; i >= 0; --i) {
-            solution[i] = (result[i] - system[i][2] * solution[i + 1]) / system[i][1];
-        }
-        return solution;
-    }
-
-    public static void main(String[] args) {
-        SplineMath s = new SplineMath(10);
-        for (int i = 0; i < 10; i++) {
-            s.setPoint(i, i, i);
-        }
-        float[][] curve = s.calculatetCurve(40);
-
-        for (int j = 0; j < curve.length; j++) {
-            System.out.println(curve[j][0] + "," + curve[j][1]);
-        }
-    }
-}
diff --git a/src/com/android/gallery3d/filtershow/filters/convolve3x3.rs b/src/com/android/gallery3d/filtershow/filters/convolve3x3.rs
deleted file mode 100644
index 2acffab..0000000
--- a/src/com/android/gallery3d/filtershow/filters/convolve3x3.rs
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * 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.
- */
-
-#pragma version(1)
-#pragma rs java_package_name(com.android.gallery3d.filtershow.filters)
-#pragma rs_fp_relaxed
-
-int32_t gWidth;
-int32_t gHeight;
-const uchar4 *gPixels;
-rs_allocation gIn;
-
-float gCoeffs[9];
-
-void root(const uchar4 *in, uchar4 *out, const void *usrData, uint32_t x, uint32_t y) {
-    uint32_t x1 = min((int32_t)x+1, gWidth-1);
-    uint32_t x2 = max((int32_t)x-1, 0);
-    uint32_t y1 = min((int32_t)y+1, gHeight-1);
-    uint32_t y2 = max((int32_t)y-1, 0);
-
-    float4 p00 = rsUnpackColor8888(gPixels[x1 + gWidth * y1]);
-    float4 p01 = rsUnpackColor8888(gPixels[x + gWidth * y1]);
-    float4 p02 = rsUnpackColor8888(gPixels[x2 + gWidth * y1]);
-    float4 p10 = rsUnpackColor8888(gPixels[x1 + gWidth * y]);
-    float4 p11 = rsUnpackColor8888(gPixels[x + gWidth * y]);
-    float4 p12 = rsUnpackColor8888(gPixels[x2 + gWidth * y]);
-    float4 p20 = rsUnpackColor8888(gPixels[x1 + gWidth * y2]);
-    float4 p21 = rsUnpackColor8888(gPixels[x + gWidth * y2]);
-    float4 p22 = rsUnpackColor8888(gPixels[x2 + gWidth * y2]);
-
-    p00 *= gCoeffs[0];
-    p01 *= gCoeffs[1];
-    p02 *= gCoeffs[2];
-    p10 *= gCoeffs[3];
-    p11 *= gCoeffs[4];
-    p12 *= gCoeffs[5];
-    p20 *= gCoeffs[6];
-    p21 *= gCoeffs[7];
-    p22 *= gCoeffs[8];
-
-    p00 += p01;
-    p02 += p10;
-    p11 += p12;
-    p20 += p21;
-
-    p22 += p00;
-    p02 += p11;
-
-    p20 += p22;
-    p20 += p02;
-
-    p20 = clamp(p20, 0.f, 1.f);
-    *out = rsPackColorTo8888(p20.r, p20.g, p20.b);
-}
diff --git a/src/com/android/gallery3d/filtershow/filters/grad.rs b/src/com/android/gallery3d/filtershow/filters/grad.rs
deleted file mode 100644
index ddbafd3..0000000
--- a/src/com/android/gallery3d/filtershow/filters/grad.rs
+++ /dev/null
@@ -1,121 +0,0 @@
-/*
- * Copyright (C) 2012 Unknown
- *
- * 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.
- */
-
-#pragma version(1)
-#pragma rs java_package_name(com.android.gallery3d.filtershow.filters)
-
-#define MAX_POINTS 16
-
-uint32_t inputWidth;
-uint32_t inputHeight;
-static const float Rf = 0.2999f;
-static const float Gf = 0.587f;
-static const float Bf = 0.114f;
-//static const float size_scale = 0.01f;
-
-typedef struct {
-    rs_matrix3x3 colorMatrix;
-    float rgbOff;
-    float dx;
-    float dy;
-    float off;
-} UPointData;
-int mNumberOfLines;
-// input data
-bool mask[MAX_POINTS];
-int xPos1[MAX_POINTS];
-int yPos1[MAX_POINTS];
-int xPos2[MAX_POINTS];
-int yPos2[MAX_POINTS];
-int size[MAX_POINTS];
-int brightness[MAX_POINTS];
-int contrast[MAX_POINTS];
-int saturation[MAX_POINTS];
-
-// generated data
-static UPointData grads[MAX_POINTS];
-
-void setupGradParams() {
-    int k = 0;
-    for (int i = 0; i < MAX_POINTS; i++) {
-      if (!mask[i]) {
-         continue;
-      }
-      float x1 = xPos1[i];
-      float y1 = yPos1[i];
-      float x2 = xPos2[i];
-      float y2 = yPos2[i];
-
-      float denom = (y2 * y2 - 2 * y1 * y2 + x2 * x2 - 2 * x1 * x2 + y1 * y1 + x1 * x1);
-      if (denom == 0) {
-         continue;
-      }
-      grads[k].dy = (y1 - y2) / denom;
-      grads[k].dx = (x1 - x2) / denom;
-      grads[k].off = (y2 * y2 + x2 * x2 - x1 * x2 - y1 * y2) / denom;
-
-      float S = 1+saturation[i]/100.f;
-      float MS = 1-S;
-      float Rt = Rf * MS;
-      float Gt = Gf * MS;
-      float Bt = Bf * MS;
-
-      float b = 1+brightness[i]/100.f;
-      float c = 1+contrast[i]/100.f;
-      b *= c;
-      grads[k].rgbOff = .5f - c/2.f;
-      rsMatrixSet(&grads[i].colorMatrix, 0, 0, b * (Rt + S));
-      rsMatrixSet(&grads[i].colorMatrix, 1, 0, b * Gt);
-      rsMatrixSet(&grads[i].colorMatrix, 2, 0, b * Bt);
-      rsMatrixSet(&grads[i].colorMatrix, 0, 1, b * Rt);
-      rsMatrixSet(&grads[i].colorMatrix, 1, 1, b * (Gt + S));
-      rsMatrixSet(&grads[i].colorMatrix, 2, 1, b * Bt);
-      rsMatrixSet(&grads[i].colorMatrix, 0, 2, b * Rt);
-      rsMatrixSet(&grads[i].colorMatrix, 1, 2, b * Gt);
-      rsMatrixSet(&grads[i].colorMatrix, 2, 2, b * (Bt + S));
-
-      k++;
-    }
-    mNumberOfLines = k;
-}
-
-void init() {
-
-}
-
-uchar4 __attribute__((kernel)) selectiveAdjust(const uchar4 in, uint32_t x,
-    uint32_t y) {
-    float4 pixel = rsUnpackColor8888(in);
-
-    float4 wsum = pixel;
-    wsum.a = 0.f;
-    for (int i = 0; i < mNumberOfLines; i++) {
-        UPointData* grad = &grads[i];
-        float t = clamp(x*grad->dx+y*grad->dy+grad->off,0.f,1.0f);
-        wsum.xyz = wsum.xyz*(1-t)+
-            t*(rsMatrixMultiply(&grad->colorMatrix ,wsum.xyz)+grad->rgbOff);
-
-    }
-
-    pixel.rgb = wsum.rgb;
-    pixel.a = 1.0f;
-
-    uchar4 out = rsPackColorTo8888(clamp(pixel, 0.f, 1.0f));
-    return out;
-}
-
-
-
diff --git a/src/com/android/gallery3d/filtershow/filters/grey.rs b/src/com/android/gallery3d/filtershow/filters/grey.rs
deleted file mode 100644
index e018803..0000000
--- a/src/com/android/gallery3d/filtershow/filters/grey.rs
+++ /dev/null
@@ -1,22 +0,0 @@
-  /*
- * Copyright (C) 2013 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.
- */
-
-#pragma version(1)
-#pragma rs java_package_name(com.android.gallery3d.filtershow.filters)
-
-uchar __attribute__((kernel)) RGBAtoA(uchar4 in) {
-    return in.r;
-}
diff --git a/src/com/android/gallery3d/filtershow/filters/saturation.rs b/src/com/android/gallery3d/filtershow/filters/saturation.rs
deleted file mode 100644
index 5210e34..0000000
--- a/src/com/android/gallery3d/filtershow/filters/saturation.rs
+++ /dev/null
@@ -1,161 +0,0 @@
-/*
- * Copyright (C) 2012 Unknown
- *
- * 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.
- */
-
-#pragma version(1)
-#pragma rs java_package_name(com.android.gallery3d.filtershow.filters)
-
-#define MAX_CHANELS 7
-#define MAX_HUE 4096
-static const int ABITS = 4;
-static const int HSCALE = 256;
-static const int k1=255 << ABITS;
-static const int k2=HSCALE << ABITS;
-
-static const float Rf = 0.2999f;
-static const float Gf = 0.587f;
-static const float Bf = 0.114f;
-
-rs_matrix3x3 colorMatrix_min;
-rs_matrix3x3 colorMatrix_max;
-
-int mNumberOfLines;
-// input data
-int saturation[MAX_CHANELS];
-float sat[MAX_CHANELS];
-
-float satLut[MAX_HUE];
-// generated data
-
-
-void setupGradParams() {
-
-    int master = saturation[0];
-    int max = master+saturation[1];
-    int min = max;
-
-    // calculate the minimum and maximum saturation
-    for (int i = 1; i < MAX_CHANELS; i++) {
-       int v = master+saturation[i];
-       if (max < v) {
-         max = v;
-       }
-       else if (min > v) {
-         min = v;
-       }
-    }
-    // generate a lookup table for all hue 0 to 4K  which goes from 0 to 1 0=min sat 1 = max sat
-    min = min - 1;
-    for(int i = 0; i < MAX_HUE ; i++) {
-       float p =  i * 6 / (float)MAX_HUE;
-       int ip = ((int)(p + .5f)) % 6;
-       int v = master + saturation[ip + 1];
-       satLut[i] = (v - min)/(float)(max - min);
-    }
-
-    float S = 1 + max / 100.f;
-    float MS = 1 - S;
-    float Rt = Rf * MS;
-    float Gt = Gf * MS;
-    float Bt = Bf * MS;
-    float b = 1.f;
-
-    // Generate 2 color matrix one at min sat and one at max
-    rsMatrixSet(&colorMatrix_max, 0, 0, b * (Rt + S));
-    rsMatrixSet(&colorMatrix_max, 1, 0, b * Gt);
-    rsMatrixSet(&colorMatrix_max, 2, 0, b * Bt);
-    rsMatrixSet(&colorMatrix_max, 0, 1, b * Rt);
-    rsMatrixSet(&colorMatrix_max, 1, 1, b * (Gt + S));
-    rsMatrixSet(&colorMatrix_max, 2, 1, b * Bt);
-    rsMatrixSet(&colorMatrix_max, 0, 2, b * Rt);
-    rsMatrixSet(&colorMatrix_max, 1, 2, b * Gt);
-    rsMatrixSet(&colorMatrix_max, 2, 2, b * (Bt + S));
-
-    S = 1 + min / 100.f;
-    MS = 1-S;
-    Rt = Rf * MS;
-    Gt = Gf * MS;
-    Bt = Bf * MS;
-    b = 1;
-
-    rsMatrixSet(&colorMatrix_min, 0, 0, b * (Rt + S));
-    rsMatrixSet(&colorMatrix_min, 1, 0, b * Gt);
-    rsMatrixSet(&colorMatrix_min, 2, 0, b * Bt);
-    rsMatrixSet(&colorMatrix_min, 0, 1, b * Rt);
-    rsMatrixSet(&colorMatrix_min, 1, 1, b * (Gt + S));
-    rsMatrixSet(&colorMatrix_min, 2, 1, b * Bt);
-    rsMatrixSet(&colorMatrix_min, 0, 2, b * Rt);
-    rsMatrixSet(&colorMatrix_min, 1, 2, b * Gt);
-    rsMatrixSet(&colorMatrix_min, 2, 2, b * (Bt + S));
-}
-
-static ushort rgb2hue( uchar4 rgb)
-{
-    int iMin,iMax,chroma;
-
-    int ri = rgb.r;
-    int gi = rgb.g;
-    int bi = rgb.b;
-    short rv,rs,rh;
-
-    if (ri > gi) {
-        iMax = max (ri, bi);
-        iMin = min (gi, bi);
-    } else {
-        iMax = max (gi, bi);
-        iMin = min (ri, bi);
-    }
-
-    rv = (short) (iMax << ABITS);
-
-    if (rv == 0) {
-        return 0;
-    }
-
-    chroma = iMax - iMin;
-    rs = (short) ((k1 * chroma) / iMax);
-    if (rs == 0) {
-        return 0;
-    }
-
-    if ( ri == iMax ) {
-        rh  = (short) ((k2 * (6 * chroma + gi - bi))/(6 * chroma));
-        if (rh >= k2) {
-           rh -= k2;
-        }
-        return rh;
-    }
-
-    if (gi  == iMax) {
-        return(short) ((k2 * (2 * chroma + bi - ri)) / (6 * chroma));
-    }
-
-    return (short) ((k2 * (4 * chroma + ri - gi)) / (6 * chroma));
-}
-
-uchar4 __attribute__((kernel)) selectiveAdjust(const uchar4 in, uint32_t x,
-    uint32_t y) {
-    float4 pixel = rsUnpackColor8888(in);
-
-    float4 wsum = pixel;
-    int hue = rgb2hue(in);
-
-    float t = satLut[hue];
-        pixel.xyz = rsMatrixMultiply(&colorMatrix_min ,pixel.xyz) * (1 - t) +
-            t * (rsMatrixMultiply(&colorMatrix_max ,pixel.xyz));
-
-    pixel.a = 1.0f;
-    return rsPackColorTo8888(clamp(pixel, 0.f, 1.0f));
-}
\ No newline at end of file
diff --git a/src/com/android/gallery3d/filtershow/history/HistoryItem.java b/src/com/android/gallery3d/filtershow/history/HistoryItem.java
deleted file mode 100644
index 2baaac3..0000000
--- a/src/com/android/gallery3d/filtershow/history/HistoryItem.java
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Copyright (C) 2013 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.gallery3d.filtershow.history;
-
-import android.graphics.Bitmap;
-import android.util.Log;
-import com.android.gallery3d.filtershow.filters.FilterRepresentation;
-import com.android.gallery3d.filtershow.pipeline.ImagePreset;
-
-public class HistoryItem {
-    private static final String LOGTAG = "HistoryItem";
-    private ImagePreset mImagePreset;
-    private FilterRepresentation mFilterRepresentation;
-    private Bitmap mPreviewImage;
-
-    public HistoryItem(ImagePreset preset, FilterRepresentation representation) {
-        mImagePreset = new ImagePreset(preset);
-        if (representation != null) {
-            mFilterRepresentation = representation.copy();
-        }
-    }
-
-    public ImagePreset getImagePreset() {
-        return mImagePreset;
-    }
-
-    public FilterRepresentation getFilterRepresentation() {
-        return mFilterRepresentation;
-    }
-
-    public Bitmap getPreviewImage() {
-        return mPreviewImage;
-    }
-
-    public void setPreviewImage(Bitmap previewImage) {
-        mPreviewImage = previewImage;
-    }
-
-}
diff --git a/src/com/android/gallery3d/filtershow/history/HistoryManager.java b/src/com/android/gallery3d/filtershow/history/HistoryManager.java
deleted file mode 100644
index 755e2ea..0000000
--- a/src/com/android/gallery3d/filtershow/history/HistoryManager.java
+++ /dev/null
@@ -1,172 +0,0 @@
-/*
- * Copyright (C) 2013 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.gallery3d.filtershow.history;
-
-import android.graphics.drawable.Drawable;
-import android.view.MenuItem;
-
-import java.util.Vector;
-
-public class HistoryManager {
-    private static final String LOGTAG = "HistoryManager";
-
-    private Vector<HistoryItem> mHistoryItems = new Vector<HistoryItem>();
-    private int mCurrentPresetPosition = 0;
-    private MenuItem mUndoMenuItem = null;
-    private MenuItem mRedoMenuItem = null;
-    private MenuItem mResetMenuItem = null;
-
-    public void setMenuItems(MenuItem undoItem, MenuItem redoItem, MenuItem resetItem) {
-        mUndoMenuItem = undoItem;
-        mRedoMenuItem = redoItem;
-        mResetMenuItem = resetItem;
-        updateMenuItems();
-    }
-
-    private int getCount() {
-        return mHistoryItems.size();
-    }
-
-    public HistoryItem getItem(int position) {
-        return mHistoryItems.elementAt(position);
-    }
-
-    private void clear() {
-        mHistoryItems.clear();
-    }
-
-    private void add(HistoryItem item) {
-        mHistoryItems.add(item);
-    }
-
-    private void notifyDataSetChanged() {
-        // TODO
-    }
-
-    public boolean canReset() {
-        if (getCount() <= 1) {
-            return false;
-        }
-        return true;
-    }
-
-    public boolean canUndo() {
-        if (mCurrentPresetPosition == getCount() - 1) {
-            return false;
-        }
-        return true;
-    }
-
-    public boolean canRedo() {
-        if (mCurrentPresetPosition == 0) {
-            return false;
-        }
-        return true;
-    }
-
-    public void updateMenuItems() {
-        if (mUndoMenuItem != null) {
-            setEnabled(mUndoMenuItem, canUndo());
-        }
-        if (mRedoMenuItem != null) {
-            setEnabled(mRedoMenuItem, canRedo());
-        }
-        if (mResetMenuItem != null) {
-            setEnabled(mResetMenuItem, canReset());
-        }
-    }
-
-    private void setEnabled(MenuItem item, boolean enabled) {
-        item.setEnabled(enabled);
-        Drawable drawable = item.getIcon();
-        if (drawable != null) {
-            drawable.setAlpha(enabled ? 255 : 80);
-        }
-    }
-
-    public void setCurrentPreset(int n) {
-        mCurrentPresetPosition = n;
-        updateMenuItems();
-        notifyDataSetChanged();
-    }
-
-    public void reset() {
-        if (getCount() == 0) {
-            return;
-        }
-        HistoryItem first = getItem(getCount() - 1);
-        clear();
-        addHistoryItem(first);
-        updateMenuItems();
-    }
-
-    public HistoryItem getLast() {
-        if (getCount() == 0) {
-            return null;
-        }
-        return getItem(0);
-    }
-
-    public HistoryItem getCurrent() {
-        return getItem(mCurrentPresetPosition);
-    }
-
-    public void addHistoryItem(HistoryItem preset) {
-        insert(preset, 0);
-        updateMenuItems();
-    }
-
-    private void insert(HistoryItem preset, int position) {
-        if (mCurrentPresetPosition != 0) {
-            // in this case, let's discount the presets before the current one
-            Vector<HistoryItem> oldItems = new Vector<HistoryItem>();
-            for (int i = mCurrentPresetPosition; i < getCount(); i++) {
-                oldItems.add(getItem(i));
-            }
-            clear();
-            for (int i = 0; i < oldItems.size(); i++) {
-                add(oldItems.elementAt(i));
-            }
-            mCurrentPresetPosition = position;
-            notifyDataSetChanged();
-        }
-        mHistoryItems.insertElementAt(preset, position);
-        mCurrentPresetPosition = position;
-        notifyDataSetChanged();
-    }
-
-    public int redo() {
-        mCurrentPresetPosition--;
-        if (mCurrentPresetPosition < 0) {
-            mCurrentPresetPosition = 0;
-        }
-        notifyDataSetChanged();
-        updateMenuItems();
-        return mCurrentPresetPosition;
-    }
-
-    public int undo() {
-        mCurrentPresetPosition++;
-        if (mCurrentPresetPosition >= getCount()) {
-            mCurrentPresetPosition = getCount() - 1;
-        }
-        notifyDataSetChanged();
-        updateMenuItems();
-        return mCurrentPresetPosition;
-    }
-
-}
diff --git a/src/com/android/gallery3d/filtershow/imageshow/ControlPoint.java b/src/com/android/gallery3d/filtershow/imageshow/ControlPoint.java
deleted file mode 100644
index aaec728..0000000
--- a/src/com/android/gallery3d/filtershow/imageshow/ControlPoint.java
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * 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.gallery3d.filtershow.imageshow;
-
-public class ControlPoint implements Comparable {
-    public float x;
-    public float y;
-
-    public ControlPoint(float px, float py) {
-        x = px;
-        y = py;
-    }
-
-    public ControlPoint(ControlPoint point) {
-        x = point.x;
-        y = point.y;
-    }
-
-    public boolean sameValues(ControlPoint other) {
-        if (this == other) {
-            return true;
-        }
-        if (other == null) {
-            return false;
-        }
-
-        if (Float.floatToIntBits(x) != Float.floatToIntBits(other.x)) {
-            return false;
-        }
-        if (Float.floatToIntBits(y) != Float.floatToIntBits(other.y)) {
-            return false;
-        }
-        return true;
-    }
-
-    public ControlPoint copy() {
-        return new ControlPoint(x, y);
-    }
-
-    @Override
-    public int compareTo(Object another) {
-        ControlPoint p = (ControlPoint) another;
-        if (p.x < x) {
-            return 1;
-        } else if (p.x > x) {
-            return -1;
-        }
-        return 0;
-    }
-}
diff --git a/src/com/android/gallery3d/filtershow/imageshow/EclipseControl.java b/src/com/android/gallery3d/filtershow/imageshow/EclipseControl.java
deleted file mode 100644
index 8ceb375..0000000
--- a/src/com/android/gallery3d/filtershow/imageshow/EclipseControl.java
+++ /dev/null
@@ -1,302 +0,0 @@
-/*
- * 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.gallery3d.filtershow.imageshow;
-
-import android.content.Context;
-import android.graphics.Canvas;
-import android.graphics.Color;
-import android.graphics.Matrix;
-import android.graphics.Paint;
-import android.graphics.RadialGradient;
-import android.graphics.RectF;
-import android.graphics.Shader;
-
-import com.android.gallery3d.R;
-
-public class EclipseControl {
-    private float mCenterX = Float.NaN;
-    private float mCenterY = 0;
-    private float mRadiusX = 200;
-    private float mRadiusY = 300;
-    private static int MIN_TOUCH_DIST = 80;// should be a resource & in dips
-
-    private float[] handlex = new float[9];
-    private float[] handley = new float[9];
-    private int mSliderColor;
-    private int mCenterDotSize = 40;
-    private float mDownX;
-    private float mDownY;
-    private float mDownCenterX;
-    private float mDownCenterY;
-    private float mDownRadiusX;
-    private float mDownRadiusY;
-    private Matrix mScrToImg;
-
-    private boolean mShowReshapeHandles = true;
-    public final static int HAN_CENTER = 0;
-    public final static int HAN_NORTH = 7;
-    public final static int HAN_NE = 8;
-    public final static int HAN_EAST = 1;
-    public final static int HAN_SE = 2;
-    public final static int HAN_SOUTH = 3;
-    public final static int HAN_SW = 4;
-    public final static int HAN_WEST = 5;
-    public final static int HAN_NW = 6;
-
-    public EclipseControl(Context context) {
-        mSliderColor = Color.WHITE;
-    }
-
-    public void setRadius(float x, float y) {
-        mRadiusX = x;
-        mRadiusY = y;
-    }
-
-    public void setCenter(float x, float y) {
-        mCenterX = x;
-        mCenterY = y;
-    }
-
-    public int getCloseHandle(float x, float y) {
-        float min = Float.MAX_VALUE;
-        int handle = -1;
-        for (int i = 0; i < handlex.length; i++) {
-            float dx = handlex[i] - x;
-            float dy = handley[i] - y;
-            float dist = dx * dx + dy * dy;
-            if (dist < min) {
-                min = dist;
-                handle = i;
-            }
-        }
-
-        if (min < MIN_TOUCH_DIST * MIN_TOUCH_DIST) {
-            return handle;
-        }
-        for (int i = 0; i < handlex.length; i++) {
-            float dx = handlex[i] - x;
-            float dy = handley[i] - y;
-            float dist = (float) Math.sqrt(dx * dx + dy * dy);
-        }
-
-        return -1;
-    }
-
-    public void setScrToImageMatrix(Matrix scrToImg) {
-        mScrToImg = scrToImg;
-    }
-
-    public void actionDown(float x, float y, Oval oval) {
-        float[] point = new float[] {
-                x, y };
-        mScrToImg.mapPoints(point);
-        mDownX = point[0];
-        mDownY = point[1];
-        mDownCenterX = oval.getCenterX();
-        mDownCenterY = oval.getCenterY();
-        mDownRadiusX = oval.getRadiusX();
-        mDownRadiusY = oval.getRadiusY();
-    }
-
-    public void actionMove(int handle, float x, float y, Oval oval) {
-        float[] point = new float[] {
-                x, y };
-        mScrToImg.mapPoints(point);
-        x = point[0];
-        y = point[1];
-
-        // Test if the matrix is swapping x and y
-        point[0] = 0;
-        point[1] = 1;
-        mScrToImg.mapVectors(point);
-        boolean swapxy = (point[0] > 0.0f);
-
-        int sign = 1;
-        switch (handle) {
-            case HAN_CENTER:
-                float ctrdx = mDownX - mDownCenterX;
-                float ctrdy = mDownY - mDownCenterY;
-                oval.setCenter(x - ctrdx, y - ctrdy);
-                // setRepresentation(mVignetteRep);
-                break;
-            case HAN_NORTH:
-                sign = -1;
-            case HAN_SOUTH:
-                if (swapxy) {
-                    float raddx = mDownRadiusY - Math.abs(mDownX - mDownCenterY);
-                    oval.setRadiusY(Math.abs(x - oval.getCenterY() + sign * raddx));
-                } else {
-                    float raddy = mDownRadiusY - Math.abs(mDownY - mDownCenterY);
-                    oval.setRadiusY(Math.abs(y - oval.getCenterY() + sign * raddy));
-                }
-                break;
-            case HAN_EAST:
-                sign = -1;
-            case HAN_WEST:
-                if (swapxy) {
-                    float raddy = mDownRadiusX - Math.abs(mDownY - mDownCenterX);
-                    oval.setRadiusX(Math.abs(y - oval.getCenterX() + sign * raddy));
-                } else {
-                    float raddx = mDownRadiusX - Math.abs(mDownX - mDownCenterX);
-                    oval.setRadiusX(Math.abs(x - oval.getCenterX() - sign * raddx));
-                }
-                break;
-            case HAN_SE:
-            case HAN_NE:
-            case HAN_SW:
-            case HAN_NW:
-                float sin45 = (float) Math.sin(45);
-                float dr = (mDownRadiusX + mDownRadiusY) * sin45;
-                float ctr_dx = mDownX - mDownCenterX;
-                float ctr_dy = mDownY - mDownCenterY;
-                float downRad = Math.abs(ctr_dx) + Math.abs(ctr_dy) - dr;
-                float rx = oval.getRadiusX();
-                float ry = oval.getRadiusY();
-                float r = (Math.abs(rx) + Math.abs(ry)) * sin45;
-                float dx = x - oval.getCenterX();
-                float dy = y - oval.getCenterY();
-                float nr = Math.abs(Math.abs(dx) + Math.abs(dy) - downRad);
-                oval.setRadius(rx * nr / r, ry * nr / r);
-
-                break;
-        }
-    }
-
-    public void paintGrayPoint(Canvas canvas, float x, float y) {
-        if (x == Float.NaN) {
-            return;
-        }
-
-        Paint paint = new Paint();
-
-        paint.setStyle(Paint.Style.FILL);
-        paint.setColor(Color.BLUE);
-        int[] colors3 = new int[] {
-                Color.GRAY, Color.LTGRAY, 0x66000000, 0 };
-        RadialGradient g = new RadialGradient(x, y, mCenterDotSize, colors3, new float[] {
-                0, .3f, .31f, 1 }, Shader.TileMode.CLAMP);
-        paint.setShader(g);
-        canvas.drawCircle(x, y, mCenterDotSize, paint);
-    }
-
-    public void paintPoint(Canvas canvas, float x, float y) {
-        if (x == Float.NaN) {
-            return;
-        }
-
-        Paint paint = new Paint();
-
-        paint.setStyle(Paint.Style.FILL);
-        paint.setColor(Color.BLUE);
-        int[] colors3 = new int[] {
-                mSliderColor, mSliderColor, 0x66000000, 0 };
-        RadialGradient g = new RadialGradient(x, y, mCenterDotSize, colors3, new float[] {
-                0, .3f, .31f, 1 }, Shader.TileMode.CLAMP);
-        paint.setShader(g);
-        canvas.drawCircle(x, y, mCenterDotSize, paint);
-    }
-
-    void paintRadius(Canvas canvas, float cx, float cy, float rx, float ry) {
-        if (cx == Float.NaN) {
-            return;
-        }
-        int mSliderColor = 0xFF33B5E5;
-        Paint paint = new Paint();
-        RectF rect = new RectF(cx - rx, cy - ry, cx + rx, cy + ry);
-        paint.setAntiAlias(true);
-        paint.setStyle(Paint.Style.STROKE);
-        paint.setStrokeWidth(6);
-        paint.setColor(Color.BLACK);
-        paintOvallines(canvas, rect, paint, cx, cy, rx, ry);
-
-        paint.setStrokeWidth(3);
-        paint.setColor(Color.WHITE);
-        paintOvallines(canvas, rect, paint, cx, cy, rx, ry);
-    }
-
-    public void paintOvallines(
-            Canvas canvas, RectF rect, Paint paint, float cx, float cy, float rx, float ry) {
-        canvas.drawOval(rect, paint);
-        float da = 4;
-        float arclen = da + da;
-        if (mShowReshapeHandles) {
-            paint.setStyle(Paint.Style.STROKE);
-
-            for (int i = 0; i < 361; i += 90) {
-                float dx = rx + 10;
-                float dy = ry + 10;
-                rect.left = cx - dx;
-                rect.top = cy - dy;
-                rect.right = cx + dx;
-                rect.bottom = cy + dy;
-                canvas.drawArc(rect, i - da, arclen, false, paint);
-                dx = rx - 10;
-                dy = ry - 10;
-                rect.left = cx - dx;
-                rect.top = cy - dy;
-                rect.right = cx + dx;
-                rect.bottom = cy + dy;
-                canvas.drawArc(rect, i - da, arclen, false, paint);
-            }
-        }
-        da *= 2;
-        paint.setStyle(Paint.Style.FILL);
-
-        for (int i = 45; i < 361; i += 90) {
-            double angle = Math.PI * i / 180.;
-            float x = cx + (float) (rx * Math.cos(angle));
-            float y = cy + (float) (ry * Math.sin(angle));
-            canvas.drawRect(x - da, y - da, x + da, y + da, paint);
-        }
-        paint.setStyle(Paint.Style.STROKE);
-        rect.left = cx - rx;
-        rect.top = cy - ry;
-        rect.right = cx + rx;
-        rect.bottom = cy + ry;
-    }
-
-    public void fillHandles(Canvas canvas, float cx, float cy, float rx, float ry) {
-        handlex[0] = cx;
-        handley[0] = cy;
-        int k = 1;
-
-        for (int i = 0; i < 360; i += 45) {
-            double angle = Math.PI * i / 180.;
-
-            float x = cx + (float) (rx * Math.cos(angle));
-            float y = cy + (float) (ry * Math.sin(angle));
-            handlex[k] = x;
-            handley[k] = y;
-
-            k++;
-        }
-    }
-
-    public void draw(Canvas canvas) {
-        paintRadius(canvas, mCenterX, mCenterY, mRadiusX, mRadiusY);
-        fillHandles(canvas, mCenterX, mCenterY, mRadiusX, mRadiusY);
-        paintPoint(canvas, mCenterX, mCenterY);
-    }
-
-    public boolean isUndefined() {
-        return Float.isNaN(mCenterX);
-    }
-
-    public void setShowReshapeHandles(boolean showReshapeHandles) {
-        this.mShowReshapeHandles = showReshapeHandles;
-    }
-}
diff --git a/src/com/android/gallery3d/filtershow/imageshow/GeometryMathUtils.java b/src/com/android/gallery3d/filtershow/imageshow/GeometryMathUtils.java
deleted file mode 100644
index 81394f1..0000000
--- a/src/com/android/gallery3d/filtershow/imageshow/GeometryMathUtils.java
+++ /dev/null
@@ -1,416 +0,0 @@
-/*
- * 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.gallery3d.filtershow.imageshow;
-
-import android.graphics.Bitmap;
-import android.graphics.Canvas;
-import android.graphics.Matrix;
-import android.graphics.Paint;
-import android.graphics.Rect;
-import android.graphics.RectF;
-
-import com.android.gallery3d.filtershow.cache.ImageLoader;
-import com.android.gallery3d.filtershow.filters.FilterCropRepresentation;
-import com.android.gallery3d.filtershow.filters.FilterMirrorRepresentation;
-import com.android.gallery3d.filtershow.filters.FilterMirrorRepresentation.Mirror;
-import com.android.gallery3d.filtershow.filters.FilterRepresentation;
-import com.android.gallery3d.filtershow.filters.FilterRotateRepresentation;
-import com.android.gallery3d.filtershow.filters.FilterRotateRepresentation.Rotation;
-import com.android.gallery3d.filtershow.filters.FilterStraightenRepresentation;
-import com.android.gallery3d.filtershow.pipeline.ImagePreset;
-
-import java.util.Collection;
-import java.util.Iterator;
-
-public final class GeometryMathUtils {
-    private GeometryMathUtils() {};
-
-    // Holder class for Geometry data.
-    public static final class GeometryHolder {
-        public Rotation rotation = FilterRotateRepresentation.getNil();
-        public float straighten = FilterStraightenRepresentation.getNil();
-        public RectF crop = FilterCropRepresentation.getNil();
-        public Mirror mirror = FilterMirrorRepresentation.getNil();
-
-        public void set(GeometryHolder h) {
-            rotation = h.rotation;
-            straighten = h.straighten;
-            crop.set(h.crop);
-            mirror = h.mirror;
-        }
-
-        public void wipe() {
-            rotation = FilterRotateRepresentation.getNil();
-            straighten = FilterStraightenRepresentation.getNil();
-            crop = FilterCropRepresentation.getNil();
-            mirror = FilterMirrorRepresentation.getNil();
-        }
-
-        public boolean isNil() {
-            return rotation == FilterRotateRepresentation.getNil() &&
-                    straighten == FilterStraightenRepresentation.getNil() &&
-                    crop.equals(FilterCropRepresentation.getNil()) &&
-                    mirror == FilterMirrorRepresentation.getNil();
-        }
-
-        @Override
-        public boolean equals(Object o) {
-            if (this == o) {
-                return true;
-            }
-            if (!(o instanceof GeometryHolder)) {
-                return false;
-            }
-            GeometryHolder h = (GeometryHolder) o;
-            return rotation == h.rotation && straighten == h.straighten &&
-                    ((crop == null && h.crop == null) || (crop != null && crop.equals(h.crop))) &&
-                    mirror == h.mirror;
-        }
-
-        @Override
-        public String toString() {
-            return getClass().getSimpleName() + "[" + "rotation:" + rotation.value()
-                    + ",straighten:" + straighten + ",crop:" + crop.toString()
-                    + ",mirror:" + mirror.value() + "]";
-        }
-    }
-
-    // Math operations for 2d vectors
-    public static float clamp(float i, float low, float high) {
-        return Math.max(Math.min(i, high), low);
-    }
-
-    public static float[] lineIntersect(float[] line1, float[] line2) {
-        float a0 = line1[0];
-        float a1 = line1[1];
-        float b0 = line1[2];
-        float b1 = line1[3];
-        float c0 = line2[0];
-        float c1 = line2[1];
-        float d0 = line2[2];
-        float d1 = line2[3];
-        float t0 = a0 - b0;
-        float t1 = a1 - b1;
-        float t2 = b0 - d0;
-        float t3 = d1 - b1;
-        float t4 = c0 - d0;
-        float t5 = c1 - d1;
-
-        float denom = t1 * t4 - t0 * t5;
-        if (denom == 0)
-            return null;
-        float u = (t3 * t4 + t5 * t2) / denom;
-        float[] intersect = {
-                b0 + u * t0, b1 + u * t1
-        };
-        return intersect;
-    }
-
-    public static float[] shortestVectorFromPointToLine(float[] point, float[] line) {
-        float x1 = line[0];
-        float x2 = line[2];
-        float y1 = line[1];
-        float y2 = line[3];
-        float xdelt = x2 - x1;
-        float ydelt = y2 - y1;
-        if (xdelt == 0 && ydelt == 0)
-            return null;
-        float u = ((point[0] - x1) * xdelt + (point[1] - y1) * ydelt)
-                / (xdelt * xdelt + ydelt * ydelt);
-        float[] ret = {
-                (x1 + u * (x2 - x1)), (y1 + u * (y2 - y1))
-        };
-        float[] vec = {
-                ret[0] - point[0], ret[1] - point[1]
-        };
-        return vec;
-    }
-
-    // A . B
-    public static float dotProduct(float[] a, float[] b) {
-        return a[0] * b[0] + a[1] * b[1];
-    }
-
-    public static float[] normalize(float[] a) {
-        float length = (float) Math.sqrt(a[0] * a[0] + a[1] * a[1]);
-        float[] b = {
-                a[0] / length, a[1] / length
-        };
-        return b;
-    }
-
-    // A onto B
-    public static float scalarProjection(float[] a, float[] b) {
-        float length = (float) Math.sqrt(b[0] * b[0] + b[1] * b[1]);
-        return dotProduct(a, b) / length;
-    }
-
-    public static float[] getVectorFromPoints(float[] point1, float[] point2) {
-        float[] p = {
-                point2[0] - point1[0], point2[1] - point1[1]
-        };
-        return p;
-    }
-
-    public static float[] getUnitVectorFromPoints(float[] point1, float[] point2) {
-        float[] p = {
-                point2[0] - point1[0], point2[1] - point1[1]
-        };
-        float length = (float) Math.sqrt(p[0] * p[0] + p[1] * p[1]);
-        p[0] = p[0] / length;
-        p[1] = p[1] / length;
-        return p;
-    }
-
-    public static void scaleRect(RectF r, float scale) {
-        r.set(r.left * scale, r.top * scale, r.right * scale, r.bottom * scale);
-    }
-
-    // A - B
-    public static float[] vectorSubtract(float[] a, float[] b) {
-        int len = a.length;
-        if (len != b.length)
-            return null;
-        float[] ret = new float[len];
-        for (int i = 0; i < len; i++) {
-            ret[i] = a[i] - b[i];
-        }
-        return ret;
-    }
-
-    public static float vectorLength(float[] a) {
-        return (float) Math.sqrt(a[0] * a[0] + a[1] * a[1]);
-    }
-
-    public static float scale(float oldWidth, float oldHeight, float newWidth, float newHeight) {
-        if (oldHeight == 0 || oldWidth == 0 || (oldWidth == newWidth && oldHeight == newHeight)) {
-            return 1;
-        }
-        return Math.min(newWidth / oldWidth, newHeight / oldHeight);
-    }
-
-    public static Rect roundNearest(RectF r) {
-        Rect q = new Rect(Math.round(r.left), Math.round(r.top), Math.round(r.right),
-                Math.round(r.bottom));
-        return q;
-    }
-
-    private static void concatMirrorMatrix(Matrix m, Mirror type) {
-        if (type == Mirror.HORIZONTAL) {
-            m.postScale(-1, 1);
-        } else if (type == Mirror.VERTICAL) {
-            m.postScale(1, -1);
-        } else if (type == Mirror.BOTH) {
-            m.postScale(1, -1);
-            m.postScale(-1, 1);
-        }
-    }
-
-    private static int getRotationForOrientation(int orientation) {
-        switch (orientation) {
-            case ImageLoader.ORI_ROTATE_90:
-                return 90;
-            case ImageLoader.ORI_ROTATE_180:
-                return 180;
-            case ImageLoader.ORI_ROTATE_270:
-                return 270;
-            default:
-                return 0;
-        }
-    }
-
-    public static GeometryHolder unpackGeometry(Collection<FilterRepresentation> geometry) {
-        GeometryHolder holder = new GeometryHolder();
-        unpackGeometry(holder, geometry);
-        return holder;
-    }
-
-    public static void unpackGeometry(GeometryHolder out,
-            Collection<FilterRepresentation> geometry) {
-        out.wipe();
-        // Get geometry data from filters
-        for (FilterRepresentation r : geometry) {
-            if (r.isNil()) {
-                continue;
-            }
-            if (r.getSerializationName() == FilterRotateRepresentation.SERIALIZATION_NAME) {
-                out.rotation = ((FilterRotateRepresentation) r).getRotation();
-            } else if (r.getSerializationName() ==
-                    FilterStraightenRepresentation.SERIALIZATION_NAME) {
-                out.straighten = ((FilterStraightenRepresentation) r).getStraighten();
-            } else if (r.getSerializationName() == FilterCropRepresentation.SERIALIZATION_NAME) {
-                ((FilterCropRepresentation) r).getCrop(out.crop);
-            } else if (r.getSerializationName() == FilterMirrorRepresentation.SERIALIZATION_NAME) {
-                out.mirror = ((FilterMirrorRepresentation) r).getMirror();
-            }
-        }
-    }
-
-    public static void replaceInstances(Collection<FilterRepresentation> geometry,
-            FilterRepresentation rep) {
-        Iterator<FilterRepresentation> iter = geometry.iterator();
-        while (iter.hasNext()) {
-            FilterRepresentation r = iter.next();
-            if (ImagePreset.sameSerializationName(rep, r)) {
-                iter.remove();
-            }
-        }
-        if (!rep.isNil()) {
-            geometry.add(rep);
-        }
-    }
-
-    public static void initializeHolder(GeometryHolder outHolder,
-            FilterRepresentation currentLocal) {
-        Collection<FilterRepresentation> geometry = MasterImage.getImage().getPreset()
-                .getGeometryFilters();
-        replaceInstances(geometry, currentLocal);
-        unpackGeometry(outHolder, geometry);
-    }
-
-    private static Bitmap applyFullGeometryMatrix(Bitmap image, GeometryHolder holder) {
-        int width = image.getWidth();
-        int height = image.getHeight();
-        RectF crop = getTrueCropRect(holder, width, height);
-        Rect frame = new Rect();
-        crop.roundOut(frame);
-        Matrix m = getCropSelectionToScreenMatrix(null, holder, width, height, frame.width(),
-                frame.height());
-        Bitmap temp = Bitmap.createBitmap(frame.width(), frame.height(), Bitmap.Config.ARGB_8888);
-        Canvas canvas = new Canvas(temp);
-        Paint paint = new Paint();
-        paint.setAntiAlias(true);
-        paint.setFilterBitmap(true);
-        paint.setDither(true);
-        canvas.drawBitmap(image, m, paint);
-        return temp;
-    }
-
-    public static Matrix getImageToScreenMatrix(Collection<FilterRepresentation> geometry,
-            boolean reflectRotation, Rect bmapDimens, float viewWidth, float viewHeight) {
-        GeometryHolder h = unpackGeometry(geometry);
-        return GeometryMathUtils.getOriginalToScreen(h, reflectRotation, bmapDimens.width(),
-                bmapDimens.height(), viewWidth, viewHeight);
-    }
-
-    public static Matrix getOriginalToScreen(GeometryHolder holder, boolean rotate,
-            float originalWidth,
-            float originalHeight, float viewWidth, float viewHeight) {
-        int orientation = MasterImage.getImage().getZoomOrientation();
-        int rotation = getRotationForOrientation(orientation);
-        Rotation prev = holder.rotation;
-        rotation = (rotation + prev.value()) % 360;
-        holder.rotation = Rotation.fromValue(rotation);
-        Matrix m = getCropSelectionToScreenMatrix(null, holder, (int) originalWidth,
-                (int) originalHeight, (int) viewWidth, (int) viewHeight);
-        holder.rotation = prev;
-        return m;
-    }
-
-    public static Bitmap applyGeometryRepresentations(Collection<FilterRepresentation> res,
-            Bitmap image) {
-        GeometryHolder holder = unpackGeometry(res);
-        Bitmap bmap = image;
-        // If there are geometry changes, apply them to the image
-        if (!holder.isNil()) {
-            bmap = applyFullGeometryMatrix(bmap, holder);
-        }
-        return bmap;
-    }
-
-    public static RectF drawTransformedCropped(GeometryHolder holder, Canvas canvas,
-            Bitmap photo, int viewWidth, int viewHeight) {
-        if (photo == null) {
-            return null;
-        }
-        RectF crop = new RectF();
-        Matrix m = getCropSelectionToScreenMatrix(crop, holder, photo.getWidth(), photo.getHeight(),
-                viewWidth, viewHeight);
-        canvas.save();
-        canvas.clipRect(crop);
-        Paint p = new Paint();
-        p.setAntiAlias(true);
-        canvas.drawBitmap(photo, m, p);
-        canvas.restore();
-        return crop;
-    }
-
-    public static boolean needsDimensionSwap(Rotation rotation) {
-        switch (rotation) {
-            case NINETY:
-            case TWO_SEVENTY:
-                return true;
-            default:
-                return false;
-        }
-    }
-
-    // Gives matrix for rotated, straightened, mirrored bitmap centered at 0,0.
-    private static Matrix getFullGeometryMatrix(GeometryHolder holder, int bitmapWidth,
-            int bitmapHeight) {
-        float centerX = bitmapWidth / 2f;
-        float centerY = bitmapHeight / 2f;
-        Matrix m = new Matrix();
-        m.setTranslate(-centerX, -centerY);
-        m.postRotate(holder.straighten + holder.rotation.value());
-        concatMirrorMatrix(m, holder.mirror);
-        return m;
-    }
-
-    public static Matrix getFullGeometryToScreenMatrix(GeometryHolder holder, int bitmapWidth,
-            int bitmapHeight, int viewWidth, int viewHeight) {
-        float scale = GeometryMathUtils.scale(bitmapWidth, bitmapHeight, viewWidth, viewHeight);
-        Matrix m = getFullGeometryMatrix(holder, bitmapWidth, bitmapHeight);
-        m.postScale(scale, scale);
-        m.postTranslate(viewWidth / 2f, viewHeight / 2f);
-        return m;
-    }
-
-    public static RectF getTrueCropRect(GeometryHolder holder, int bitmapWidth, int bitmapHeight) {
-        RectF r = new RectF(holder.crop);
-        FilterCropRepresentation.findScaledCrop(r, bitmapWidth, bitmapHeight);
-        float s = holder.straighten;
-        holder.straighten = 0;
-        Matrix m1 = getFullGeometryMatrix(holder, bitmapWidth, bitmapHeight);
-        holder.straighten = s;
-        m1.mapRect(r);
-        return r;
-    }
-
-    public static Matrix getCropSelectionToScreenMatrix(RectF outCrop, GeometryHolder holder,
-            int bitmapWidth, int bitmapHeight, int viewWidth, int viewHeight) {
-        Matrix m = getFullGeometryMatrix(holder, bitmapWidth, bitmapHeight);
-        RectF crop = getTrueCropRect(holder, bitmapWidth, bitmapHeight);
-        float scale = GeometryMathUtils.scale(crop.width(), crop.height(), viewWidth, viewHeight);
-        m.postScale(scale, scale);
-        GeometryMathUtils.scaleRect(crop, scale);
-        m.postTranslate(viewWidth / 2f - crop.centerX(), viewHeight / 2f - crop.centerY());
-        if (outCrop != null) {
-            crop.offset(viewWidth / 2f - crop.centerX(), viewHeight / 2f - crop.centerY());
-            outCrop.set(crop);
-        }
-        return m;
-    }
-
-    public static Matrix getCropSelectionToScreenMatrix(RectF outCrop,
-            Collection<FilterRepresentation> res, int bitmapWidth, int bitmapHeight, int viewWidth,
-            int viewHeight) {
-        GeometryHolder holder = unpackGeometry(res);
-        return getCropSelectionToScreenMatrix(outCrop, holder, bitmapWidth, bitmapHeight,
-                viewWidth, viewHeight);
-    }
-}
diff --git a/src/com/android/gallery3d/filtershow/imageshow/GradControl.java b/src/com/android/gallery3d/filtershow/imageshow/GradControl.java
deleted file mode 100644
index 964da99..0000000
--- a/src/com/android/gallery3d/filtershow/imageshow/GradControl.java
+++ /dev/null
@@ -1,274 +0,0 @@
-/*
- * 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.gallery3d.filtershow.imageshow;
-
-import android.content.Context;
-import android.content.res.Resources;
-import android.graphics.Canvas;
-import android.graphics.Color;
-import android.graphics.DashPathEffect;
-import android.graphics.Matrix;
-import android.graphics.Paint;
-import android.graphics.RadialGradient;
-import android.graphics.Rect;
-import android.graphics.Shader;
-
-import com.android.gallery3d.R;
-
-public class GradControl {
-    private float mPoint1X = Float.NaN; // used to flag parameters have not been set
-    private float mPoint1Y = 0;
-    private float mPoint2X = 200;
-    private float mPoint2Y = 300;
-    private int mMinTouchDist = 80;// should be a resource & in dips
-
-    private float[] handlex = new float[3];
-    private float[] handley = new float[3];
-    private int mSliderColor;
-    private int mCenterDotSize;
-    private float mDownX;
-    private float mDownY;
-    private float mDownPoint1X;
-    private float mDownPoint1Y;
-    private float mDownPoint2X;
-    private float mDownPoint2Y;
-    Rect mImageBounds;
-    int mImageHeight;
-    private Matrix mScrToImg;
-    Paint mPaint = new Paint();
-    DashPathEffect mDash = new DashPathEffect(new float[]{30, 30}, 0);
-    private boolean mShowReshapeHandles = true;
-    public final static int HAN_CENTER = 0;
-    public final static int HAN_NORTH = 2;
-    public final static int HAN_SOUTH = 1;
-    private int[] mPointColorPatern;
-    private int[] mGrayPointColorPatern;
-    private float[] mPointRadialPos = new float[]{0, .3f, .31f, 1};
-    private int mLineColor;
-    private int mlineShadowColor;
-
-    public GradControl(Context context) {
-
-        Resources res = context.getResources();
-        mCenterDotSize = (int) res.getDimension(R.dimen.gradcontrol_dot_size);
-        mMinTouchDist = (int) res.getDimension(R.dimen.gradcontrol_min_touch_dist);
-        int grayPointCenterColor = res.getColor(R.color.gradcontrol_graypoint_center);
-        int grayPointEdgeColor = res.getColor(R.color.gradcontrol_graypoint_edge);
-        int pointCenterColor = res.getColor(R.color.gradcontrol_point_center);
-        int pointEdgeColor = res.getColor(R.color.gradcontrol_point_edge);
-        int pointShadowStartColor = res.getColor(R.color.gradcontrol_point_shadow_start);
-        int pointShadowEndColor = res.getColor(R.color.gradcontrol_point_shadow_end);
-        mPointColorPatern = new int[]{
-                pointCenterColor, pointEdgeColor, pointShadowStartColor, pointShadowEndColor};
-        mGrayPointColorPatern = new int[]{
-                grayPointCenterColor, grayPointEdgeColor, pointShadowStartColor, pointShadowEndColor};
-        mSliderColor = Color.WHITE;
-        mLineColor = res.getColor(R.color.gradcontrol_line_color);
-        mlineShadowColor = res.getColor(R.color.gradcontrol_line_shadow);
-    }
-
-    public void setPoint2(float x, float y) {
-        mPoint2X = x;
-        mPoint2Y = y;
-    }
-
-    public void setPoint1(float x, float y) {
-        mPoint1X = x;
-        mPoint1Y = y;
-    }
-
-    public int getCloseHandle(float x, float y) {
-        float min = Float.MAX_VALUE;
-        int handle = -1;
-        for (int i = 0; i < handlex.length; i++) {
-            float dx = handlex[i] - x;
-            float dy = handley[i] - y;
-            float dist = dx * dx + dy * dy;
-            if (dist < min) {
-                min = dist;
-                handle = i;
-            }
-        }
-
-        if (min < mMinTouchDist * mMinTouchDist) {
-            return handle;
-        }
-        for (int i = 0; i < handlex.length; i++) {
-            float dx = handlex[i] - x;
-            float dy = handley[i] - y;
-            float dist = (float) Math.sqrt(dx * dx + dy * dy);
-        }
-
-        return -1;
-    }
-
-    public void setScrImageInfo(Matrix scrToImg, Rect imageBounds) {
-        mScrToImg = scrToImg;
-        mImageBounds = new Rect(imageBounds);
-    }
-
-    private boolean centerIsOutside(float x1, float y1, float x2, float y2) {
-        return (!mImageBounds.contains((int) ((x1 + x2) / 2), (int) ((y1 + y2) / 2)));
-    }
-
-    public void actionDown(float x, float y, Line line) {
-        float[] point = new float[]{
-                x, y};
-        mScrToImg.mapPoints(point);
-        mDownX = point[0];
-        mDownY = point[1];
-        mDownPoint1X = line.getPoint1X();
-        mDownPoint1Y = line.getPoint1Y();
-        mDownPoint2X = line.getPoint2X();
-        mDownPoint2Y = line.getPoint2Y();
-    }
-
-    public void actionMove(int handle, float x, float y, Line line) {
-        float[] point = new float[]{
-                x, y};
-        mScrToImg.mapPoints(point);
-        x = point[0];
-        y = point[1];
-
-        // Test if the matrix is swapping x and y
-        point[0] = 0;
-        point[1] = 1;
-        mScrToImg.mapVectors(point);
-        boolean swapxy = (point[0] > 0.0f);
-
-        int sign = 1;
-
-        float dx = x - mDownX;
-        float dy = y - mDownY;
-        switch (handle) {
-            case HAN_CENTER:
-                if (centerIsOutside(mDownPoint1X + dx, mDownPoint1Y + dy,
-                        mDownPoint2X + dx, mDownPoint2Y + dy)) {
-                    break;
-                }
-                line.setPoint1(mDownPoint1X + dx, mDownPoint1Y + dy);
-                line.setPoint2(mDownPoint2X + dx, mDownPoint2Y + dy);
-                break;
-            case HAN_SOUTH:
-                if (centerIsOutside(mDownPoint1X + dx, mDownPoint1Y + dy,
-                        mDownPoint2X, mDownPoint2Y)) {
-                    break;
-                }
-                line.setPoint1(mDownPoint1X + dx, mDownPoint1Y + dy);
-                break;
-            case HAN_NORTH:
-                if (centerIsOutside(mDownPoint1X, mDownPoint1Y,
-                        mDownPoint2X + dx, mDownPoint2Y + dy)) {
-                    break;
-                }
-                line.setPoint2(mDownPoint2X + dx, mDownPoint2Y + dy);
-                break;
-        }
-    }
-
-    public void paintGrayPoint(Canvas canvas, float x, float y) {
-        if (isUndefined()) {
-            return;
-        }
-
-        Paint paint = new Paint();
-        paint.setStyle(Paint.Style.FILL);
-        RadialGradient g = new RadialGradient(x, y, mCenterDotSize, mGrayPointColorPatern,
-                mPointRadialPos, Shader.TileMode.CLAMP);
-        paint.setShader(g);
-        canvas.drawCircle(x, y, mCenterDotSize, paint);
-    }
-
-    public void paintPoint(Canvas canvas, float x, float y) {
-        if (isUndefined()) {
-            return;
-        }
-
-        Paint paint = new Paint();
-        paint.setStyle(Paint.Style.FILL);
-        RadialGradient g = new RadialGradient(x, y, mCenterDotSize, mPointColorPatern,
-                mPointRadialPos, Shader.TileMode.CLAMP);
-        paint.setShader(g);
-        canvas.drawCircle(x, y, mCenterDotSize, paint);
-    }
-
-    void paintLines(Canvas canvas, float p1x, float p1y, float p2x, float p2y) {
-        if (isUndefined()) {
-            return;
-        }
-
-        mPaint.setAntiAlias(true);
-        mPaint.setStyle(Paint.Style.STROKE);
-
-        mPaint.setStrokeWidth(6);
-        mPaint.setColor(mlineShadowColor);
-        mPaint.setPathEffect(mDash);
-        paintOvallines(canvas, mPaint, p1x, p1y, p2x, p2y);
-
-        mPaint.setStrokeWidth(3);
-        mPaint.setColor(mLineColor);
-        mPaint.setPathEffect(mDash);
-        paintOvallines(canvas, mPaint, p1x, p1y, p2x, p2y);
-    }
-
-    public void paintOvallines(
-            Canvas canvas, Paint paint, float p1x, float p1y, float p2x, float p2y) {
-
-
-
-        canvas.drawLine(p1x, p1y, p2x, p2y, paint);
-
-        float cx = (p1x + p2x) / 2;
-        float cy = (p1y + p2y) / 2;
-        float dx = p1x - p2x;
-        float dy = p1y - p2y;
-        float len = (float) Math.sqrt(dx * dx + dy * dy);
-        dx *= 2048 / len;
-        dy *= 2048 / len;
-
-        canvas.drawLine(p1x + dy, p1y - dx, p1x - dy, p1y + dx, paint);
-        canvas.drawLine(p2x + dy, p2y - dx, p2x - dy, p2y + dx, paint);
-    }
-
-    public void fillHandles(Canvas canvas, float p1x, float p1y, float p2x, float p2y) {
-        float cx = (p1x + p2x) / 2;
-        float cy = (p1y + p2y) / 2;
-        handlex[0] = cx;
-        handley[0] = cy;
-        handlex[1] = p1x;
-        handley[1] = p1y;
-        handlex[2] = p2x;
-        handley[2] = p2y;
-
-    }
-
-    public void draw(Canvas canvas) {
-        paintLines(canvas, mPoint1X, mPoint1Y, mPoint2X, mPoint2Y);
-        fillHandles(canvas, mPoint1X, mPoint1Y, mPoint2X, mPoint2Y);
-        paintPoint(canvas, mPoint2X, mPoint2Y);
-        paintPoint(canvas, mPoint1X, mPoint1Y);
-        paintPoint(canvas, (mPoint1X + mPoint2X) / 2, (mPoint1Y + mPoint2Y) / 2);
-    }
-
-    public boolean isUndefined() {
-        return Float.isNaN(mPoint1X);
-    }
-
-    public void setShowReshapeHandles(boolean showReshapeHandles) {
-        this.mShowReshapeHandles = showReshapeHandles;
-    }
-}
diff --git a/src/com/android/gallery3d/filtershow/imageshow/ImageCrop.java b/src/com/android/gallery3d/filtershow/imageshow/ImageCrop.java
deleted file mode 100644
index 7fee031..0000000
--- a/src/com/android/gallery3d/filtershow/imageshow/ImageCrop.java
+++ /dev/null
@@ -1,307 +0,0 @@
-/*
- * Copyright (C) 2013 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.gallery3d.filtershow.imageshow;
-
-import android.content.Context;
-import android.content.res.Resources;
-import android.graphics.Bitmap;
-import android.graphics.Canvas;
-import android.graphics.Matrix;
-import android.graphics.Paint;
-import android.graphics.RectF;
-import android.graphics.drawable.Drawable;
-import android.util.AttributeSet;
-import android.util.Log;
-import android.view.MotionEvent;
-
-import com.android.gallery3d.R;
-import com.android.gallery3d.filtershow.crop.CropDrawingUtils;
-import com.android.gallery3d.filtershow.crop.CropMath;
-import com.android.gallery3d.filtershow.crop.CropObject;
-import com.android.gallery3d.filtershow.editors.EditorCrop;
-import com.android.gallery3d.filtershow.filters.FilterCropRepresentation;
-import com.android.gallery3d.filtershow.imageshow.GeometryMathUtils.GeometryHolder;
-
-public class ImageCrop extends ImageShow {
-    private static final String TAG = ImageCrop.class.getSimpleName();
-    private RectF mImageBounds = new RectF();
-    private RectF mScreenCropBounds = new RectF();
-    private Paint mPaint = new Paint();
-    private CropObject mCropObj = null;
-    private GeometryHolder mGeometry = new GeometryHolder();
-    private GeometryHolder mUpdateHolder = new GeometryHolder();
-    private Drawable mCropIndicator;
-    private int mIndicatorSize;
-    private boolean mMovingBlock = false;
-    private Matrix mDisplayMatrix = null;
-    private Matrix mDisplayCropMatrix = null;
-    private Matrix mDisplayMatrixInverse = null;
-    private float mPrevX = 0;
-    private float mPrevY = 0;
-    private int mMinSideSize = 90;
-    private int mTouchTolerance = 40;
-    private enum Mode {
-        NONE, MOVE
-    }
-    private Mode mState = Mode.NONE;
-    private boolean mValidDraw = false;
-    FilterCropRepresentation mLocalRep = new FilterCropRepresentation();
-    EditorCrop mEditorCrop;
-
-    public ImageCrop(Context context) {
-        super(context);
-        setup(context);
-    }
-
-    public ImageCrop(Context context, AttributeSet attrs) {
-        super(context, attrs);
-        setup(context);
-    }
-
-    public ImageCrop(Context context, AttributeSet attrs, int defStyle) {
-        super(context, attrs, defStyle);
-        setup(context);
-    }
-
-    private void setup(Context context) {
-        Resources rsc = context.getResources();
-        mCropIndicator = rsc.getDrawable(R.drawable.camera_crop);
-        mIndicatorSize = (int) rsc.getDimension(R.dimen.crop_indicator_size);
-        mMinSideSize = (int) rsc.getDimension(R.dimen.crop_min_side);
-        mTouchTolerance = (int) rsc.getDimension(R.dimen.crop_touch_tolerance);
-    }
-
-    public void setFilterCropRepresentation(FilterCropRepresentation crop) {
-        mLocalRep = (crop == null) ? new FilterCropRepresentation() : crop;
-        GeometryMathUtils.initializeHolder(mUpdateHolder, mLocalRep);
-        mValidDraw = true;
-    }
-
-    public FilterCropRepresentation getFinalRepresentation() {
-        return mLocalRep;
-    }
-
-    private void internallyUpdateLocalRep(RectF crop, RectF image) {
-        FilterCropRepresentation
-                .findNormalizedCrop(crop, (int) image.width(), (int) image.height());
-        mGeometry.crop.set(crop);
-        mUpdateHolder.set(mGeometry);
-        mLocalRep.setCrop(crop);
-    }
-
-    @Override
-    public boolean onTouchEvent(MotionEvent event) {
-        float x = event.getX();
-        float y = event.getY();
-        if (mDisplayMatrix == null || mDisplayMatrixInverse == null) {
-            return true;
-        }
-        float[] touchPoint = {
-                x, y
-        };
-        mDisplayMatrixInverse.mapPoints(touchPoint);
-        x = touchPoint[0];
-        y = touchPoint[1];
-        switch (event.getActionMasked()) {
-            case (MotionEvent.ACTION_DOWN):
-                if (mState == Mode.NONE) {
-                    if (!mCropObj.selectEdge(x, y)) {
-                        mMovingBlock = mCropObj.selectEdge(CropObject.MOVE_BLOCK);
-                    }
-                    mPrevX = x;
-                    mPrevY = y;
-                    mState = Mode.MOVE;
-                }
-                break;
-            case (MotionEvent.ACTION_UP):
-                if (mState == Mode.MOVE) {
-                    mCropObj.selectEdge(CropObject.MOVE_NONE);
-                    mMovingBlock = false;
-                    mPrevX = x;
-                    mPrevY = y;
-                    mState = Mode.NONE;
-                    internallyUpdateLocalRep(mCropObj.getInnerBounds(), mCropObj.getOuterBounds());
-                }
-                break;
-            case (MotionEvent.ACTION_MOVE):
-                if (mState == Mode.MOVE) {
-                    float dx = x - mPrevX;
-                    float dy = y - mPrevY;
-                    mCropObj.moveCurrentSelection(dx, dy);
-                    mPrevX = x;
-                    mPrevY = y;
-                }
-                break;
-            default:
-                break;
-        }
-        invalidate();
-        return true;
-    }
-
-    private void clearDisplay() {
-        mDisplayMatrix = null;
-        mDisplayMatrixInverse = null;
-        invalidate();
-    }
-
-    public void applyFreeAspect() {
-        mCropObj.unsetAspectRatio();
-        invalidate();
-    }
-
-    public void applyOriginalAspect() {
-        RectF outer = mCropObj.getOuterBounds();
-        float w = outer.width();
-        float h = outer.height();
-        if (w > 0 && h > 0) {
-            applyAspect(w, h);
-            mCropObj.resetBoundsTo(outer, outer);
-            internallyUpdateLocalRep(mCropObj.getInnerBounds(), mCropObj.getOuterBounds());
-        } else {
-            Log.w(TAG, "failed to set aspect ratio original");
-        }
-        invalidate();
-    }
-
-    public void applyAspect(float x, float y) {
-        if (x <= 0 || y <= 0) {
-            throw new IllegalArgumentException("Bad arguments to applyAspect");
-        }
-        // If we are rotated by 90 degrees from horizontal, swap x and y
-        if (GeometryMathUtils.needsDimensionSwap(mGeometry.rotation)) {
-            float tmp = x;
-            x = y;
-            y = tmp;
-        }
-        if (!mCropObj.setInnerAspectRatio(x, y)) {
-            Log.w(TAG, "failed to set aspect ratio");
-        }
-        internallyUpdateLocalRep(mCropObj.getInnerBounds(), mCropObj.getOuterBounds());
-        invalidate();
-    }
-
-    /**
-     * Rotates first d bits in integer x to the left some number of times.
-     */
-    private int bitCycleLeft(int x, int times, int d) {
-        int mask = (1 << d) - 1;
-        int mout = x & mask;
-        times %= d;
-        int hi = mout >> (d - times);
-        int low = (mout << times) & mask;
-        int ret = x & ~mask;
-        ret |= low;
-        ret |= hi;
-        return ret;
-    }
-
-    /**
-     * Find the selected edge or corner in screen coordinates.
-     */
-    private int decode(int movingEdges, float rotation) {
-        int rot = CropMath.constrainedRotation(rotation);
-        switch (rot) {
-            case 90:
-                return bitCycleLeft(movingEdges, 1, 4);
-            case 180:
-                return bitCycleLeft(movingEdges, 2, 4);
-            case 270:
-                return bitCycleLeft(movingEdges, 3, 4);
-            default:
-                return movingEdges;
-        }
-    }
-
-    private void forceStateConsistency() {
-        MasterImage master = MasterImage.getImage();
-        Bitmap image = master.getFiltersOnlyImage();
-        int width = image.getWidth();
-        int height = image.getHeight();
-        if (mCropObj == null || !mUpdateHolder.equals(mGeometry)
-                || mImageBounds.width() != width || mImageBounds.height() != height
-                || !mLocalRep.getCrop().equals(mUpdateHolder.crop)) {
-            mImageBounds.set(0, 0, width, height);
-            mGeometry.set(mUpdateHolder);
-            mLocalRep.setCrop(mUpdateHolder.crop);
-            RectF scaledCrop = new RectF(mUpdateHolder.crop);
-            FilterCropRepresentation.findScaledCrop(scaledCrop, width, height);
-            mCropObj = new CropObject(mImageBounds, scaledCrop, (int) mUpdateHolder.straighten);
-            mState = Mode.NONE;
-            clearDisplay();
-        }
-    }
-
-    @Override
-    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
-        super.onSizeChanged(w, h, oldw, oldh);
-        clearDisplay();
-    }
-
-    @Override
-    public void onDraw(Canvas canvas) {
-        Bitmap bitmap = MasterImage.getImage().getFiltersOnlyImage();
-        if (!mValidDraw || bitmap == null) {
-            return;
-        }
-        forceStateConsistency();
-        mImageBounds.set(0, 0, bitmap.getWidth(), bitmap.getHeight());
-        // If display matrix doesn't exist, create it and its dependencies
-        if (mDisplayCropMatrix == null || mDisplayMatrix == null || mDisplayMatrixInverse == null) {
-            mDisplayMatrix = GeometryMathUtils.getFullGeometryToScreenMatrix(mGeometry,
-                    bitmap.getWidth(), bitmap.getHeight(), canvas.getWidth(), canvas.getHeight());
-            float straighten = mGeometry.straighten;
-            mGeometry.straighten = 0;
-            mDisplayCropMatrix = GeometryMathUtils.getFullGeometryToScreenMatrix(mGeometry,
-                    bitmap.getWidth(), bitmap.getHeight(), canvas.getWidth(), canvas.getHeight());
-            mGeometry.straighten = straighten;
-            mDisplayMatrixInverse = new Matrix();
-            mDisplayMatrixInverse.reset();
-            if (!mDisplayCropMatrix.invert(mDisplayMatrixInverse)) {
-                Log.w(TAG, "could not invert display matrix");
-                mDisplayMatrixInverse = null;
-                return;
-            }
-            // Scale min side and tolerance by display matrix scale factor
-            mCropObj.setMinInnerSideSize(mDisplayMatrixInverse.mapRadius(mMinSideSize));
-            mCropObj.setTouchTolerance(mDisplayMatrixInverse.mapRadius(mTouchTolerance));
-        }
-        // Draw actual bitmap
-        mPaint.reset();
-        mPaint.setAntiAlias(true);
-        mPaint.setFilterBitmap(true);
-        canvas.drawBitmap(bitmap, mDisplayMatrix, mPaint);
-        mCropObj.getInnerBounds(mScreenCropBounds);
-        RectF outer = mCropObj.getOuterBounds();
-        FilterCropRepresentation.findNormalizedCrop(mScreenCropBounds, (int) outer.width(),
-                (int) outer.height());
-        FilterCropRepresentation.findScaledCrop(mScreenCropBounds, bitmap.getWidth(),
-                bitmap.getHeight());
-        if (mDisplayCropMatrix.mapRect(mScreenCropBounds)) {
-            // Draw crop rect and markers
-            CropDrawingUtils.drawCropRect(canvas, mScreenCropBounds);
-            CropDrawingUtils.drawRuleOfThird(canvas, mScreenCropBounds);
-            CropDrawingUtils.drawIndicators(canvas, mCropIndicator, mIndicatorSize,
-                    mScreenCropBounds, mCropObj.isFixedAspect(),
-                    decode(mCropObj.getSelectState(), mGeometry.rotation.value()));
-        }
-    }
-
-    public void setEditor(EditorCrop editorCrop) {
-        mEditorCrop = editorCrop;
-    }
-}
diff --git a/src/com/android/gallery3d/filtershow/imageshow/ImageCurves.java b/src/com/android/gallery3d/filtershow/imageshow/ImageCurves.java
deleted file mode 100644
index 82c4b2f..0000000
--- a/src/com/android/gallery3d/filtershow/imageshow/ImageCurves.java
+++ /dev/null
@@ -1,445 +0,0 @@
-/*
- * 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.gallery3d.filtershow.imageshow;
-
-import android.content.Context;
-import android.graphics.Bitmap;
-import android.graphics.Canvas;
-import android.graphics.Color;
-import android.graphics.Paint;
-import android.graphics.Path;
-import android.graphics.PorterDuff;
-import android.graphics.PorterDuffXfermode;
-import android.os.AsyncTask;
-import android.util.AttributeSet;
-import android.view.MenuItem;
-import android.view.MotionEvent;
-import android.view.View;
-import android.widget.Button;
-import android.widget.LinearLayout;
-import android.widget.PopupMenu;
-
-import com.android.gallery3d.R;
-import com.android.gallery3d.filtershow.editors.Editor;
-import com.android.gallery3d.filtershow.editors.EditorCurves;
-import com.android.gallery3d.filtershow.filters.FilterCurvesRepresentation;
-import com.android.gallery3d.filtershow.filters.FiltersManager;
-import com.android.gallery3d.filtershow.filters.ImageFilterCurves;
-import com.android.gallery3d.filtershow.pipeline.ImagePreset;
-
-import java.util.HashMap;
-
-public class ImageCurves extends ImageShow {
-
-    private static final String LOGTAG = "ImageCurves";
-    Paint gPaint = new Paint();
-    Path gPathSpline = new Path();
-    HashMap<Integer, String> mIdStrLut;
-
-    private int mCurrentCurveIndex = Spline.RGB;
-    private boolean mDidAddPoint = false;
-    private boolean mDidDelete = false;
-    private ControlPoint mCurrentControlPoint = null;
-    private int mCurrentPick = -1;
-    private ImagePreset mLastPreset = null;
-    int[] redHistogram = new int[256];
-    int[] greenHistogram = new int[256];
-    int[] blueHistogram = new int[256];
-    Path gHistoPath = new Path();
-
-    boolean mDoingTouchMove = false;
-    private EditorCurves mEditorCurves;
-    private FilterCurvesRepresentation mFilterCurvesRepresentation;
-
-    public ImageCurves(Context context) {
-        super(context);
-        setLayerType(LAYER_TYPE_SOFTWARE, gPaint);
-        resetCurve();
-    }
-
-    public ImageCurves(Context context, AttributeSet attrs) {
-        super(context, attrs);
-        setLayerType(LAYER_TYPE_SOFTWARE, gPaint);
-        resetCurve();
-    }
-
-    @Override
-    protected boolean enableComparison() {
-        return false;
-    }
-
-    @Override
-    public boolean useUtilityPanel() {
-        return true;
-    }
-
-    private void showPopupMenu(LinearLayout accessoryViewList) {
-        final Button button = (Button) accessoryViewList.findViewById(
-                R.id.applyEffect);
-        if (button == null) {
-            return;
-        }
-        if (mIdStrLut == null){
-            mIdStrLut = new HashMap<Integer, String>();
-            mIdStrLut.put(R.id.curve_menu_rgb,
-                    getContext().getString(R.string.curves_channel_rgb));
-            mIdStrLut.put(R.id.curve_menu_red,
-                    getContext().getString(R.string.curves_channel_red));
-            mIdStrLut.put(R.id.curve_menu_green,
-                    getContext().getString(R.string.curves_channel_green));
-            mIdStrLut.put(R.id.curve_menu_blue,
-                    getContext().getString(R.string.curves_channel_blue));
-        }
-        PopupMenu popupMenu = new PopupMenu(getActivity(), button);
-        popupMenu.getMenuInflater().inflate(R.menu.filtershow_menu_curves, popupMenu.getMenu());
-        popupMenu.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
-            @Override
-            public boolean onMenuItemClick(MenuItem item) {
-                setChannel(item.getItemId());
-                button.setText(mIdStrLut.get(item.getItemId()));
-                return true;
-            }
-        });
-        Editor.hackFixStrings(popupMenu.getMenu());
-        popupMenu.show();
-    }
-
-    @Override
-    public void openUtilityPanel(final LinearLayout accessoryViewList) {
-        Context context = accessoryViewList.getContext();
-        Button view = (Button) accessoryViewList.findViewById(R.id.applyEffect);
-        view.setText(context.getString(R.string.curves_channel_rgb));
-        view.setVisibility(View.VISIBLE);
-
-        view.setOnClickListener(new OnClickListener() {
-                @Override
-            public void onClick(View arg0) {
-                showPopupMenu(accessoryViewList);
-            }
-        });
-
-        if (view != null) {
-            view.setVisibility(View.VISIBLE);
-        }
-    }
-
-    public void nextChannel() {
-        mCurrentCurveIndex = ((mCurrentCurveIndex + 1) % 4);
-        invalidate();
-    }
-
-    private ImageFilterCurves curves() {
-        String filterName = getFilterName();
-        ImagePreset p = getImagePreset();
-        if (p != null) {
-            return (ImageFilterCurves) FiltersManager.getManager().getFilter(ImageFilterCurves.class);
-        }
-        return null;
-    }
-
-    private Spline getSpline(int index) {
-        return mFilterCurvesRepresentation.getSpline(index);
-    }
-
-    @Override
-    public void resetParameter() {
-        super.resetParameter();
-        resetCurve();
-        mLastPreset = null;
-        invalidate();
-    }
-
-    public void resetCurve() {
-        if (mFilterCurvesRepresentation != null) {
-            mFilterCurvesRepresentation.reset();
-            updateCachedImage();
-        }
-    }
-
-    @Override
-    public void onDraw(Canvas canvas) {
-        super.onDraw(canvas);
-        if (mFilterCurvesRepresentation == null) {
-            return;
-        }
-
-        gPaint.setAntiAlias(true);
-
-        if (getImagePreset() != mLastPreset && getFilteredImage() != null) {
-            new ComputeHistogramTask().execute(getFilteredImage());
-            mLastPreset = getImagePreset();
-        }
-
-        if (curves() == null) {
-            return;
-        }
-
-        if (mCurrentCurveIndex == Spline.RGB || mCurrentCurveIndex == Spline.RED) {
-            drawHistogram(canvas, redHistogram, Color.RED, PorterDuff.Mode.SCREEN);
-        }
-        if (mCurrentCurveIndex == Spline.RGB || mCurrentCurveIndex == Spline.GREEN) {
-            drawHistogram(canvas, greenHistogram, Color.GREEN, PorterDuff.Mode.SCREEN);
-        }
-        if (mCurrentCurveIndex == Spline.RGB || mCurrentCurveIndex == Spline.BLUE) {
-            drawHistogram(canvas, blueHistogram, Color.BLUE, PorterDuff.Mode.SCREEN);
-        }
-        // We only display the other channels curves when showing the RGB curve
-        if (mCurrentCurveIndex == Spline.RGB) {
-            for (int i = 0; i < 4; i++) {
-                Spline spline = getSpline(i);
-                if (i != mCurrentCurveIndex && !spline.isOriginal()) {
-                    // And we only display a curve if it has more than two
-                    // points
-                    spline.draw(canvas, Spline.colorForCurve(i), getWidth(),
-                            getHeight(), false, mDoingTouchMove);
-                }
-            }
-        }
-        // ...but we always display the current curve.
-        getSpline(mCurrentCurveIndex)
-                .draw(canvas, Spline.colorForCurve(mCurrentCurveIndex), getWidth(), getHeight(),
-                        true, mDoingTouchMove);
-
-    }
-
-    private int pickControlPoint(float x, float y) {
-        int pick = 0;
-        Spline spline = getSpline(mCurrentCurveIndex);
-        float px = spline.getPoint(0).x;
-        float py = spline.getPoint(0).y;
-        double delta = Math.sqrt((px - x) * (px - x) + (py - y) * (py - y));
-        for (int i = 1; i < spline.getNbPoints(); i++) {
-            px = spline.getPoint(i).x;
-            py = spline.getPoint(i).y;
-            double currentDelta = Math.sqrt((px - x) * (px - x) + (py - y)
-                    * (py - y));
-            if (currentDelta < delta) {
-                delta = currentDelta;
-                pick = i;
-            }
-        }
-
-        if (!mDidAddPoint && (delta * getWidth() > 100)
-                && (spline.getNbPoints() < 10)) {
-            return -1;
-        }
-
-        return pick;
-    }
-
-    private String getFilterName() {
-        return "Curves";
-    }
-
-    @Override
-    public synchronized boolean onTouchEvent(MotionEvent e) {
-        if (e.getPointerCount() != 1) {
-            return true;
-        }
-
-        if (didFinishScalingOperation()) {
-            return true;
-        }
-
-        float margin = Spline.curveHandleSize() / 2;
-        float posX = e.getX();
-        if (posX < margin) {
-            posX = margin;
-        }
-        float posY = e.getY();
-        if (posY < margin) {
-            posY = margin;
-        }
-        if (posX > getWidth() - margin) {
-            posX = getWidth() - margin;
-        }
-        if (posY > getHeight() - margin) {
-            posY = getHeight() - margin;
-        }
-        posX = (posX - margin) / (getWidth() - 2 * margin);
-        posY = (posY - margin) / (getHeight() - 2 * margin);
-
-        if (e.getActionMasked() == MotionEvent.ACTION_UP) {
-            mCurrentControlPoint = null;
-            mCurrentPick = -1;
-            updateCachedImage();
-            mDidAddPoint = false;
-            if (mDidDelete) {
-                mDidDelete = false;
-            }
-            mDoingTouchMove = false;
-            return true;
-        }
-
-        if (mDidDelete) {
-            return true;
-        }
-
-        if (curves() == null) {
-            return true;
-        }
-
-        if (e.getActionMasked() == MotionEvent.ACTION_MOVE) {
-            mDoingTouchMove = true;
-            Spline spline = getSpline(mCurrentCurveIndex);
-            int pick = mCurrentPick;
-            if (mCurrentControlPoint == null) {
-                pick = pickControlPoint(posX, posY);
-                if (pick == -1) {
-                    mCurrentControlPoint = new ControlPoint(posX, posY);
-                    pick = spline.addPoint(mCurrentControlPoint);
-                    mDidAddPoint = true;
-                } else {
-                    mCurrentControlPoint = spline.getPoint(pick);
-                }
-                mCurrentPick = pick;
-            }
-
-            if (spline.isPointContained(posX, pick)) {
-                spline.movePoint(pick, posX, posY);
-            } else if (pick != -1 && spline.getNbPoints() > 2) {
-                spline.deletePoint(pick);
-                mDidDelete = true;
-            }
-            updateCachedImage();
-            invalidate();
-        }
-        return true;
-    }
-
-    public synchronized void updateCachedImage() {
-        if (getImagePreset() != null) {
-            resetImageCaches(this);
-            if (mEditorCurves != null) {
-                mEditorCurves.commitLocalRepresentation();
-            }
-            invalidate();
-        }
-    }
-
-    class ComputeHistogramTask extends AsyncTask<Bitmap, Void, int[]> {
-        @Override
-        protected int[] doInBackground(Bitmap... params) {
-            int[] histo = new int[256 * 3];
-            Bitmap bitmap = params[0];
-            int w = bitmap.getWidth();
-            int h = bitmap.getHeight();
-            int[] pixels = new int[w * h];
-            bitmap.getPixels(pixels, 0, w, 0, 0, w, h);
-            for (int i = 0; i < w; i++) {
-                for (int j = 0; j < h; j++) {
-                    int index = j * w + i;
-                    int r = Color.red(pixels[index]);
-                    int g = Color.green(pixels[index]);
-                    int b = Color.blue(pixels[index]);
-                    histo[r]++;
-                    histo[256 + g]++;
-                    histo[512 + b]++;
-                }
-            }
-            return histo;
-        }
-
-        @Override
-        protected void onPostExecute(int[] result) {
-            System.arraycopy(result, 0, redHistogram, 0, 256);
-            System.arraycopy(result, 256, greenHistogram, 0, 256);
-            System.arraycopy(result, 512, blueHistogram, 0, 256);
-            invalidate();
-        }
-    }
-
-    private void drawHistogram(Canvas canvas, int[] histogram, int color, PorterDuff.Mode mode) {
-        int max = 0;
-        for (int i = 0; i < histogram.length; i++) {
-            if (histogram[i] > max) {
-                max = histogram[i];
-            }
-        }
-        float w = getWidth() - Spline.curveHandleSize();
-        float h = getHeight() - Spline.curveHandleSize() / 2.0f;
-        float dx = Spline.curveHandleSize() / 2.0f;
-        float wl = w / histogram.length;
-        float wh = (0.3f * h) / max;
-        Paint paint = new Paint();
-        paint.setARGB(100, 255, 255, 255);
-        paint.setStrokeWidth((int) Math.ceil(wl));
-
-        Paint paint2 = new Paint();
-        paint2.setColor(color);
-        paint2.setStrokeWidth(6);
-        paint2.setXfermode(new PorterDuffXfermode(mode));
-        gHistoPath.reset();
-        gHistoPath.moveTo(dx, h);
-        boolean firstPointEncountered = false;
-        float prev = 0;
-        float last = 0;
-        for (int i = 0; i < histogram.length; i++) {
-            float x = i * wl + dx;
-            float l = histogram[i] * wh;
-            if (l != 0) {
-                float v = h - (l + prev) / 2.0f;
-                if (!firstPointEncountered) {
-                    gHistoPath.lineTo(x, h);
-                    firstPointEncountered = true;
-                }
-                gHistoPath.lineTo(x, v);
-                prev = l;
-                last = x;
-            }
-        }
-        gHistoPath.lineTo(last, h);
-        gHistoPath.lineTo(w, h);
-        gHistoPath.close();
-        canvas.drawPath(gHistoPath, paint2);
-        paint2.setStrokeWidth(2);
-        paint2.setStyle(Paint.Style.STROKE);
-        paint2.setARGB(255, 200, 200, 200);
-        canvas.drawPath(gHistoPath, paint2);
-    }
-
-    public void setChannel(int itemId) {
-        switch (itemId) {
-            case R.id.curve_menu_rgb: {
-                mCurrentCurveIndex = Spline.RGB;
-                break;
-            }
-            case R.id.curve_menu_red: {
-                mCurrentCurveIndex = Spline.RED;
-                break;
-            }
-            case R.id.curve_menu_green: {
-                mCurrentCurveIndex = Spline.GREEN;
-                break;
-            }
-            case R.id.curve_menu_blue: {
-                mCurrentCurveIndex = Spline.BLUE;
-                break;
-            }
-        }
-        mEditorCurves.commitLocalRepresentation();
-        invalidate();
-    }
-
-    public void setEditor(EditorCurves editorCurves) {
-        mEditorCurves = editorCurves;
-    }
-
-    public void setFilterDrawRepresentation(FilterCurvesRepresentation drawRep) {
-        mFilterCurvesRepresentation = drawRep;
-    }
-}
diff --git a/src/com/android/gallery3d/filtershow/imageshow/ImageDraw.java b/src/com/android/gallery3d/filtershow/imageshow/ImageDraw.java
deleted file mode 100644
index 9722034..0000000
--- a/src/com/android/gallery3d/filtershow/imageshow/ImageDraw.java
+++ /dev/null
@@ -1,139 +0,0 @@
-
-package com.android.gallery3d.filtershow.imageshow;
-
-import android.content.Context;
-import android.graphics.Canvas;
-import android.graphics.Color;
-import android.graphics.Matrix;
-import android.graphics.drawable.Drawable;
-import android.util.AttributeSet;
-import android.view.MotionEvent;
-
-import com.android.gallery3d.filtershow.editors.EditorDraw;
-import com.android.gallery3d.filtershow.filters.FilterDrawRepresentation;
-import com.android.gallery3d.filtershow.filters.ImageFilterDraw;
-
-public class ImageDraw extends ImageShow {
-
-    private static final String LOGTAG = "ImageDraw";
-    private int mCurrentColor = Color.RED;
-    final static float INITAL_STROKE_RADIUS = 40;
-    private float mCurrentSize = INITAL_STROKE_RADIUS;
-    private byte mType = 0;
-    private FilterDrawRepresentation mFRep;
-    private EditorDraw mEditorDraw;
-
-    public ImageDraw(Context context, AttributeSet attrs) {
-        super(context, attrs);
-        resetParameter();
-    }
-
-    public ImageDraw(Context context) {
-        super(context);
-        resetParameter();
-    }
-
-    public void setEditor(EditorDraw editorDraw) {
-        mEditorDraw = editorDraw;
-    }
-    public void setFilterDrawRepresentation(FilterDrawRepresentation fr) {
-        mFRep = fr;
-    }
-
-    public Drawable getIcon(Context context) {
-
-        return null;
-    }
-
-    @Override
-    public void resetParameter() {
-        if (mFRep != null) {
-            mFRep.clear();
-        }
-    }
-
-    public void setColor(int color) {
-        mCurrentColor = color;
-    }
-
-    public void setSize(int size) {
-        mCurrentSize = size;
-    }
-
-    public void setStyle(byte style) {
-        mType = (byte) (style % ImageFilterDraw.NUMBER_OF_STYLES);
-    }
-
-    public int getStyle() {
-        return mType;
-    }
-
-    public int getSize() {
-        return (int) mCurrentSize;
-    }
-
-    float[] mTmpPoint = new float[2]; // so we do not malloc
-    @Override
-    public boolean onTouchEvent(MotionEvent event) {
-        if (event.getPointerCount() > 1) {
-            boolean ret = super.onTouchEvent(event);
-            if (mFRep.getCurrentDrawing() != null) {
-                mFRep.clearCurrentSection();
-                mEditorDraw.commitLocalRepresentation();
-            }
-            return ret;
-        }
-        if (event.getAction() != MotionEvent.ACTION_DOWN) {
-            if (mFRep.getCurrentDrawing() == null) {
-                return super.onTouchEvent(event);
-            }
-        }
-
-        if (event.getAction() == MotionEvent.ACTION_DOWN) {
-            calcScreenMapping();
-            mTmpPoint[0] = event.getX();
-            mTmpPoint[1] = event.getY();
-            mToOrig.mapPoints(mTmpPoint);
-            mFRep.startNewSection(mType, mCurrentColor, mCurrentSize, mTmpPoint[0], mTmpPoint[1]);
-        }
-
-        if (event.getAction() == MotionEvent.ACTION_MOVE) {
-
-            int historySize = event.getHistorySize();
-            for (int h = 0; h < historySize; h++) {
-                int p = 0;
-                {
-                    mTmpPoint[0] = event.getHistoricalX(p, h);
-                    mTmpPoint[1] = event.getHistoricalY(p, h);
-                    mToOrig.mapPoints(mTmpPoint);
-                    mFRep.addPoint(mTmpPoint[0], mTmpPoint[1]);
-                }
-            }
-        }
-
-        if (event.getAction() == MotionEvent.ACTION_UP) {
-            mTmpPoint[0] = event.getX();
-            mTmpPoint[1] = event.getY();
-            mToOrig.mapPoints(mTmpPoint);
-            mFRep.endSection(mTmpPoint[0], mTmpPoint[1]);
-        }
-        mEditorDraw.commitLocalRepresentation();
-        invalidate();
-        return true;
-    }
-
-    Matrix mRotateToScreen = new Matrix();
-    Matrix mToOrig;
-    private void calcScreenMapping() {
-        mToOrig = getScreenToImageMatrix(true);
-        mToOrig.invert(mRotateToScreen);
-    }
-
-    @Override
-    public void onDraw(Canvas canvas) {
-        super.onDraw(canvas);
-        calcScreenMapping();
-
-    }
-
-}
diff --git a/src/com/android/gallery3d/filtershow/imageshow/ImageGrad.java b/src/com/android/gallery3d/filtershow/imageshow/ImageGrad.java
deleted file mode 100644
index b55cc2b..0000000
--- a/src/com/android/gallery3d/filtershow/imageshow/ImageGrad.java
+++ /dev/null
@@ -1,215 +0,0 @@
-package com.android.gallery3d.filtershow.imageshow;
-/*
- * Copyright (C) 2013 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.
- */
-
-import android.content.Context;
-import android.content.res.Resources;
-import android.graphics.Canvas;
-import android.graphics.Matrix;
-import android.util.AttributeSet;
-import android.view.MotionEvent;
-
-import com.android.gallery3d.R;
-import com.android.gallery3d.filtershow.editors.EditorGrad;
-import com.android.gallery3d.filtershow.filters.FilterGradRepresentation;
-
-public class ImageGrad extends ImageShow {
-    private static final String LOGTAG = "ImageGrad";
-    private FilterGradRepresentation mGradRep;
-    private EditorGrad mEditorGrad;
-    private float mMinTouchDist;
-    private int mActiveHandle = -1;
-    private GradControl mEllipse;
-
-    Matrix mToScr = new Matrix();
-    float[] mPointsX = new float[FilterGradRepresentation.MAX_POINTS];
-    float[] mPointsY = new float[FilterGradRepresentation.MAX_POINTS];
-
-    public ImageGrad(Context context) {
-        super(context);
-        Resources res = context.getResources();
-        mMinTouchDist = res.getDimensionPixelSize(R.dimen.gradcontrol_min_touch_dist);
-        mEllipse = new GradControl(context);
-        mEllipse.setShowReshapeHandles(false);
-    }
-
-    public ImageGrad(Context context, AttributeSet attrs) {
-        super(context, attrs);
-        Resources res = context.getResources();
-        mMinTouchDist = res.getDimensionPixelSize(R.dimen.gradcontrol_min_touch_dist);
-        mEllipse = new GradControl(context);
-        mEllipse.setShowReshapeHandles(false);
-    }
-
-    @Override
-    public boolean onTouchEvent(MotionEvent event) {
-        int mask = event.getActionMasked();
-
-        if (mActiveHandle == -1) {
-            if (MotionEvent.ACTION_DOWN != mask) {
-                return super.onTouchEvent(event);
-            }
-            if (event.getPointerCount() == 1) {
-                mActiveHandle = mEllipse.getCloseHandle(event.getX(), event.getY());
-                if (mActiveHandle == -1) {
-                    float x = event.getX();
-                    float y = event.getY();
-                    float min_d = Float.MAX_VALUE;
-                    int pos = -1;
-                    for (int i = 0; i < mPointsX.length; i++) {
-                        if (mPointsX[i] == -1) {
-                            continue;
-                        }
-                        float d = (float) Math.hypot(x - mPointsX[i], y - mPointsY[i]);
-                        if ( min_d > d) {
-                            min_d = d;
-                            pos = i;
-                        }
-                    }
-                    if (min_d > mMinTouchDist){
-                        pos = -1;
-                    }
-
-                    if (pos != -1) {
-                        mGradRep.setSelectedPoint(pos);
-                        resetImageCaches(this);
-                        mEditorGrad.updateSeekBar(mGradRep);
-                        mEditorGrad.commitLocalRepresentation();
-                        invalidate();
-                    }
-                }
-            }
-            if (mActiveHandle == -1) {
-                return super.onTouchEvent(event);
-            }
-        } else {
-            switch (mask) {
-                case MotionEvent.ACTION_UP: {
-
-                    mActiveHandle = -1;
-                    break;
-                }
-                case MotionEvent.ACTION_DOWN: {
-                    break;
-                }
-            }
-        }
-        float x = event.getX();
-        float y = event.getY();
-
-        mEllipse.setScrImageInfo(getScreenToImageMatrix(true),
-                MasterImage.getImage().getOriginalBounds());
-
-        switch (mask) {
-            case (MotionEvent.ACTION_DOWN): {
-                mEllipse.actionDown(x, y, mGradRep);
-                break;
-            }
-            case (MotionEvent.ACTION_UP):
-            case (MotionEvent.ACTION_MOVE): {
-                mEllipse.actionMove(mActiveHandle, x, y, mGradRep);
-                setRepresentation(mGradRep);
-                break;
-            }
-        }
-        invalidate();
-        mEditorGrad.commitLocalRepresentation();
-        return true;
-    }
-
-    public void setRepresentation(FilterGradRepresentation pointRep) {
-        mGradRep = pointRep;
-        Matrix toImg = getScreenToImageMatrix(false);
-
-        toImg.invert(mToScr);
-
-        float[] c1 = new float[] { mGradRep.getPoint1X(), mGradRep.getPoint1Y() };
-        float[] c2 = new float[] { mGradRep.getPoint2X(), mGradRep.getPoint2Y() };
-
-        if (c1[0] == -1) {
-            float cx = MasterImage.getImage().getOriginalBounds().width() / 2;
-            float cy = MasterImage.getImage().getOriginalBounds().height() / 2;
-            float rx = Math.min(cx, cy) * .4f;
-
-            mGradRep.setPoint1(cx, cy-rx);
-            mGradRep.setPoint2(cx, cy+rx);
-            c1[0] = cx;
-            c1[1] = cy-rx;
-            mToScr.mapPoints(c1);
-            if (getWidth() != 0) {
-                mEllipse.setPoint1(c1[0], c1[1]);
-                c2[0] = cx;
-                c2[1] = cy+rx;
-                mToScr.mapPoints(c2);
-                mEllipse.setPoint2(c2[0], c2[1]);
-            }
-            mEditorGrad.commitLocalRepresentation();
-        } else {
-            mToScr.mapPoints(c1);
-            mToScr.mapPoints(c2);
-            mEllipse.setPoint1(c1[0], c1[1]);
-            mEllipse.setPoint2(c2[0], c2[1]);
-        }
-    }
-
-    public void drawOtherPoints(Canvas canvas) {
-        computCenterLocations();
-        for (int i = 0; i < mPointsX.length; i++) {
-            if (mPointsX[i] != -1) {
-                mEllipse.paintGrayPoint(canvas, mPointsX[i], mPointsY[i]);
-            }
-        }
-    }
-
-    public void computCenterLocations() {
-        int x1[] = mGradRep.getXPos1();
-        int y1[] = mGradRep.getYPos1();
-        int x2[] = mGradRep.getXPos2();
-        int y2[] = mGradRep.getYPos2();
-        int selected = mGradRep.getSelectedPoint();
-        boolean m[] = mGradRep.getMask();
-        float[] c = new float[2];
-        for (int i = 0; i < m.length; i++) {
-            if (selected == i || !m[i]) {
-                mPointsX[i] = -1;
-                continue;
-            }
-
-            c[0] = (x1[i]+x2[i])/2;
-            c[1] = (y1[i]+y2[i])/2;
-            mToScr.mapPoints(c);
-
-            mPointsX[i] = c[0];
-            mPointsY[i] = c[1];
-        }
-    }
-
-    public void setEditor(EditorGrad editorGrad) {
-        mEditorGrad = editorGrad;
-    }
-
-    @Override
-    public void onDraw(Canvas canvas) {
-        super.onDraw(canvas);
-        if (mGradRep == null) {
-            return;
-        }
-        setRepresentation(mGradRep);
-        mEllipse.draw(canvas);
-        drawOtherPoints(canvas);
-    }
-
-}
diff --git a/src/com/android/gallery3d/filtershow/imageshow/ImageMirror.java b/src/com/android/gallery3d/filtershow/imageshow/ImageMirror.java
deleted file mode 100644
index 26c49b1..0000000
--- a/src/com/android/gallery3d/filtershow/imageshow/ImageMirror.java
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * Copyright (C) 2013 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.gallery3d.filtershow.imageshow;
-
-import android.content.Context;
-import android.graphics.Bitmap;
-import android.graphics.Canvas;
-import android.util.AttributeSet;
-import android.view.MotionEvent;
-
-import com.android.gallery3d.filtershow.editors.EditorMirror;
-import com.android.gallery3d.filtershow.filters.FilterMirrorRepresentation;
-import com.android.gallery3d.filtershow.imageshow.GeometryMathUtils.GeometryHolder;
-
-public class ImageMirror extends ImageShow {
-    private static final String TAG = ImageMirror.class.getSimpleName();
-    private EditorMirror mEditorMirror;
-    private FilterMirrorRepresentation mLocalRep = new FilterMirrorRepresentation();
-    private GeometryHolder mDrawHolder = new GeometryHolder();
-
-    public ImageMirror(Context context, AttributeSet attrs) {
-        super(context, attrs);
-    }
-
-    public ImageMirror(Context context) {
-        super(context);
-    }
-
-    public void setFilterMirrorRepresentation(FilterMirrorRepresentation rep) {
-        mLocalRep = (rep == null) ? new FilterMirrorRepresentation() : rep;
-    }
-
-    public void flip() {
-        mLocalRep.cycle();
-        invalidate();
-    }
-
-    public FilterMirrorRepresentation getFinalRepresentation() {
-        return mLocalRep;
-    }
-
-    @Override
-    public boolean onTouchEvent(MotionEvent event) {
-        // Treat event as handled.
-        return true;
-    }
-
-    @Override
-    public void onDraw(Canvas canvas) {
-        MasterImage master = MasterImage.getImage();
-        Bitmap image = master.getFiltersOnlyImage();
-        if (image == null) {
-            return;
-        }
-        GeometryMathUtils.initializeHolder(mDrawHolder, mLocalRep);
-        GeometryMathUtils.drawTransformedCropped(mDrawHolder, canvas, image, getWidth(),
-                getHeight());
-    }
-
-    public void setEditor(EditorMirror editorFlip) {
-        mEditorMirror = editorFlip;
-    }
-
-}
diff --git a/src/com/android/gallery3d/filtershow/imageshow/ImagePoint.java b/src/com/android/gallery3d/filtershow/imageshow/ImagePoint.java
deleted file mode 100644
index fd57141..0000000
--- a/src/com/android/gallery3d/filtershow/imageshow/ImagePoint.java
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- * Copyright (C) 2013 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.gallery3d.filtershow.imageshow;
-
-import android.content.Context;
-import android.graphics.Canvas;
-import android.graphics.Color;
-import android.graphics.Matrix;
-import android.graphics.Paint;
-import android.graphics.Paint.Style;
-import android.util.AttributeSet;
-
-import com.android.gallery3d.filtershow.editors.EditorRedEye;
-import com.android.gallery3d.filtershow.filters.FilterPoint;
-import com.android.gallery3d.filtershow.filters.FilterRedEyeRepresentation;
-import com.android.gallery3d.filtershow.filters.ImageFilterRedEye;
-
-public abstract class ImagePoint extends ImageShow {
-
-    private static final String LOGTAG = "ImageRedEyes";
-    protected EditorRedEye mEditorRedEye;
-    protected FilterRedEyeRepresentation mRedEyeRep;
-    protected static float mTouchPadding = 80;
-
-    public static void setTouchPadding(float padding) {
-        mTouchPadding = padding;
-    }
-
-    public ImagePoint(Context context, AttributeSet attrs) {
-        super(context, attrs);
-    }
-
-    public ImagePoint(Context context) {
-        super(context);
-    }
-
-    @Override
-    public void resetParameter() {
-        ImageFilterRedEye filter = (ImageFilterRedEye) getCurrentFilter();
-        if (filter != null) {
-            filter.clear();
-        }
-        invalidate();
-    }
-
-    @Override
-    public void onDraw(Canvas canvas) {
-        super.onDraw(canvas);
-        Paint paint = new Paint();
-        paint.setStyle(Style.STROKE);
-        paint.setColor(Color.RED);
-        paint.setStrokeWidth(2);
-
-        Matrix originalToScreen = getImageToScreenMatrix(false);
-        Matrix originalRotateToScreen = getImageToScreenMatrix(true);
-
-        if (mRedEyeRep != null) {
-            for (FilterPoint candidate : mRedEyeRep.getCandidates()) {
-                drawPoint(candidate, canvas, originalToScreen, originalRotateToScreen, paint);
-            }
-        }
-    }
-
-    protected abstract void drawPoint(
-            FilterPoint candidate, Canvas canvas, Matrix originalToScreen,
-            Matrix originalRotateToScreen, Paint paint);
-
-    public void setEditor(EditorRedEye editorRedEye) {
-        mEditorRedEye = editorRedEye;
-    }
-
-    public void setRepresentation(FilterRedEyeRepresentation redEyeRep) {
-        mRedEyeRep = redEyeRep;
-    }
-}
diff --git a/src/com/android/gallery3d/filtershow/imageshow/ImageRedEye.java b/src/com/android/gallery3d/filtershow/imageshow/ImageRedEye.java
deleted file mode 100644
index 40433a0..0000000
--- a/src/com/android/gallery3d/filtershow/imageshow/ImageRedEye.java
+++ /dev/null
@@ -1,137 +0,0 @@
-/*
- * Copyright (C) 2013 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.gallery3d.filtershow.imageshow;
-
-import android.content.Context;
-import android.graphics.Canvas;
-import android.graphics.Color;
-import android.graphics.Matrix;
-import android.graphics.Paint;
-import android.graphics.Paint.Style;
-import android.graphics.RectF;
-import android.view.MotionEvent;
-
-import com.android.gallery3d.filtershow.filters.FilterPoint;
-import com.android.gallery3d.filtershow.filters.RedEyeCandidate;
-
-public class ImageRedEye extends ImagePoint {
-    private static final String LOGTAG = "ImageRedEyes";
-    private RectF mCurrentRect = null;
-
-    public ImageRedEye(Context context) {
-        super(context);
-    }
-
-    @Override
-    public void resetParameter() {
-        super.resetParameter();
-        invalidate();
-    }
-
-    @Override
-
-    public boolean onTouchEvent(MotionEvent event) {
-        super.onTouchEvent(event);
-
-        if (event.getPointerCount() > 1) {
-            return true;
-        }
-
-        if (didFinishScalingOperation()) {
-            return true;
-        }
-
-        float ex = event.getX();
-        float ey = event.getY();
-
-        // let's transform (ex, ey) to displayed image coordinates
-        if (event.getAction() == MotionEvent.ACTION_DOWN) {
-            mCurrentRect = new RectF();
-            mCurrentRect.left = ex - mTouchPadding;
-            mCurrentRect.top = ey - mTouchPadding;
-        }
-        if (event.getAction() == MotionEvent.ACTION_MOVE) {
-            mCurrentRect.right = ex + mTouchPadding;
-            mCurrentRect.bottom = ey + mTouchPadding;
-        }
-        if (event.getAction() == MotionEvent.ACTION_UP) {
-            if (mCurrentRect != null) {
-                // transform to original coordinates
-                Matrix originalNoRotateToScreen = getImageToScreenMatrix(false);
-                Matrix originalToScreen = getImageToScreenMatrix(true);
-                Matrix invert = new Matrix();
-                originalToScreen.invert(invert);
-                RectF r = new RectF(mCurrentRect);
-                invert.mapRect(r);
-                RectF r2 = new RectF(mCurrentRect);
-                invert.reset();
-                originalNoRotateToScreen.invert(invert);
-                invert.mapRect(r2);
-                mRedEyeRep.addRect(r, r2);
-                this.resetImageCaches(this);
-            }
-            mCurrentRect = null;
-        }
-        mEditorRedEye.commitLocalRepresentation();
-        invalidate();
-        return true;
-    }
-
-    @Override
-    public void onDraw(Canvas canvas) {
-        super.onDraw(canvas);
-        Paint paint = new Paint();
-        paint.setStyle(Style.STROKE);
-        paint.setColor(Color.RED);
-        paint.setStrokeWidth(2);
-        if (mCurrentRect != null) {
-            paint.setColor(Color.RED);
-            RectF drawRect = new RectF(mCurrentRect);
-            canvas.drawRect(drawRect, paint);
-        }
-    }
-
-    @Override
-    protected void drawPoint(FilterPoint point, Canvas canvas, Matrix originalToScreen,
-            Matrix originalRotateToScreen, Paint paint) {
-        RedEyeCandidate candidate = (RedEyeCandidate) point;
-        RectF rect = candidate.getRect();
-        RectF drawRect = new RectF();
-        originalToScreen.mapRect(drawRect, rect);
-        RectF fullRect = new RectF();
-        originalRotateToScreen.mapRect(fullRect, rect);
-        paint.setColor(Color.BLUE);
-        canvas.drawRect(fullRect, paint);
-        canvas.drawLine(fullRect.centerX(), fullRect.top,
-                fullRect.centerX(), fullRect.bottom, paint);
-        canvas.drawLine(fullRect.left, fullRect.centerY(),
-                fullRect.right, fullRect.centerY(), paint);
-        paint.setColor(Color.GREEN);
-        float dw = drawRect.width();
-        float dh = drawRect.height();
-        float dx = fullRect.centerX() - dw / 2;
-        float dy = fullRect.centerY() - dh / 2;
-        drawRect.set(dx, dy, dx + dw, dy + dh);
-        canvas.drawRect(drawRect, paint);
-        canvas.drawLine(drawRect.centerX(), drawRect.top,
-                drawRect.centerX(), drawRect.bottom, paint);
-        canvas.drawLine(drawRect.left, drawRect.centerY(),
-                drawRect.right, drawRect.centerY(), paint);
-        canvas.drawCircle(drawRect.centerX(), drawRect.centerY(),
-                mTouchPadding, paint);
-    }
-}
diff --git a/src/com/android/gallery3d/filtershow/imageshow/ImageRotate.java b/src/com/android/gallery3d/filtershow/imageshow/ImageRotate.java
deleted file mode 100644
index 5186c09..0000000
--- a/src/com/android/gallery3d/filtershow/imageshow/ImageRotate.java
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * 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.gallery3d.filtershow.imageshow;
-
-import android.content.Context;
-import android.graphics.Bitmap;
-import android.graphics.Canvas;
-import android.util.AttributeSet;
-import android.view.MotionEvent;
-
-import com.android.gallery3d.filtershow.editors.EditorRotate;
-import com.android.gallery3d.filtershow.filters.FilterRotateRepresentation;
-import com.android.gallery3d.filtershow.imageshow.GeometryMathUtils.GeometryHolder;
-
-public class ImageRotate extends ImageShow {
-    private EditorRotate mEditorRotate;
-    private static final String TAG = ImageRotate.class.getSimpleName();
-    private FilterRotateRepresentation mLocalRep = new FilterRotateRepresentation();
-    private GeometryHolder mDrawHolder = new GeometryHolder();
-
-    public ImageRotate(Context context, AttributeSet attrs) {
-        super(context, attrs);
-    }
-
-    public ImageRotate(Context context) {
-        super(context);
-    }
-
-    public void setFilterRotateRepresentation(FilterRotateRepresentation rep) {
-        mLocalRep = (rep == null) ? new FilterRotateRepresentation() : rep;
-    }
-
-    public void rotate() {
-        mLocalRep.rotateCW();
-        invalidate();
-    }
-
-    public FilterRotateRepresentation getFinalRepresentation() {
-        return mLocalRep;
-    }
-
-    @Override
-    public boolean onTouchEvent(MotionEvent event) {
-        // Treat event as handled.
-        return true;
-    }
-
-    public int getLocalValue() {
-        return mLocalRep.getRotation().value();
-    }
-
-    @Override
-    public void onDraw(Canvas canvas) {
-        MasterImage master = MasterImage.getImage();
-        Bitmap image = master.getFiltersOnlyImage();
-        if (image == null) {
-            return;
-        }
-        GeometryMathUtils.initializeHolder(mDrawHolder, mLocalRep);
-        GeometryMathUtils.drawTransformedCropped(mDrawHolder, canvas, image, canvas.getWidth(),
-                canvas.getHeight());
-    }
-
-    public void setEditor(EditorRotate editorRotate) {
-        mEditorRotate = editorRotate;
-    }
-}
diff --git a/src/com/android/gallery3d/filtershow/imageshow/ImageShow.java b/src/com/android/gallery3d/filtershow/imageshow/ImageShow.java
deleted file mode 100644
index 6278b2a..0000000
--- a/src/com/android/gallery3d/filtershow/imageshow/ImageShow.java
+++ /dev/null
@@ -1,578 +0,0 @@
-/*
- * 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.gallery3d.filtershow.imageshow;
-
-import android.content.Context;
-import android.content.res.Resources;
-import android.graphics.Bitmap;
-import android.graphics.Canvas;
-import android.graphics.Color;
-import android.graphics.Matrix;
-import android.graphics.Paint;
-import android.graphics.Point;
-import android.graphics.Rect;
-import android.graphics.RectF;
-import android.util.AttributeSet;
-import android.view.GestureDetector;
-import android.view.GestureDetector.OnDoubleTapListener;
-import android.view.GestureDetector.OnGestureListener;
-import android.view.MotionEvent;
-import android.view.ScaleGestureDetector;
-import android.view.View;
-import android.widget.LinearLayout;
-
-import com.android.gallery3d.R;
-import com.android.gallery3d.filtershow.FilterShowActivity;
-import com.android.gallery3d.filtershow.filters.ImageFilter;
-import com.android.gallery3d.filtershow.pipeline.ImagePreset;
-import com.android.gallery3d.filtershow.tools.SaveImage;
-
-import java.io.File;
-
-public class ImageShow extends View implements OnGestureListener,
-        ScaleGestureDetector.OnScaleGestureListener,
-        OnDoubleTapListener {
-
-    private static final String LOGTAG = "ImageShow";
-    private static final boolean ENABLE_ZOOMED_COMPARISON = false;
-
-    protected Paint mPaint = new Paint();
-    protected int mTextSize;
-    protected int mTextPadding;
-
-    protected int mBackgroundColor;
-
-    private GestureDetector mGestureDetector = null;
-    private ScaleGestureDetector mScaleGestureDetector = null;
-
-    protected Rect mImageBounds = new Rect();
-    private boolean mOriginalDisabled = false;
-    private boolean mTouchShowOriginal = false;
-    private long mTouchShowOriginalDate = 0;
-    private final long mTouchShowOriginalDelayMin = 200; // 200ms
-    private int mShowOriginalDirection = 0;
-    private static int UNVEIL_HORIZONTAL = 1;
-    private static int UNVEIL_VERTICAL = 2;
-
-    private Point mTouchDown = new Point();
-    private Point mTouch = new Point();
-    private boolean mFinishedScalingOperation = false;
-
-    private int mOriginalTextMargin;
-    private int mOriginalTextSize;
-    private String mOriginalText;
-    private boolean mZoomIn = false;
-    Point mOriginalTranslation = new Point();
-    float mOriginalScale;
-    float mStartFocusX, mStartFocusY;
-    private enum InteractionMode {
-        NONE,
-        SCALE,
-        MOVE
-    }
-    InteractionMode mInteractionMode = InteractionMode.NONE;
-
-    private FilterShowActivity mActivity = null;
-
-    public FilterShowActivity getActivity() {
-        return mActivity;
-    }
-
-    public boolean hasModifications() {
-        return MasterImage.getImage().hasModifications();
-    }
-
-    public void resetParameter() {
-        // TODO: implement reset
-    }
-
-    public void onNewValue(int parameter) {
-        invalidate();
-    }
-
-    public ImageShow(Context context, AttributeSet attrs, int defStyle) {
-        super(context, attrs, defStyle);
-        setupImageShow(context);
-    }
-
-    public ImageShow(Context context, AttributeSet attrs) {
-        super(context, attrs);
-        setupImageShow(context);
-
-    }
-
-    public ImageShow(Context context) {
-        super(context);
-        setupImageShow(context);
-    }
-
-    private void setupImageShow(Context context) {
-        Resources res = context.getResources();
-        mTextSize = res.getDimensionPixelSize(R.dimen.photoeditor_text_size);
-        mTextPadding = res.getDimensionPixelSize(R.dimen.photoeditor_text_padding);
-        mOriginalTextMargin = res.getDimensionPixelSize(R.dimen.photoeditor_original_text_margin);
-        mOriginalTextSize = res.getDimensionPixelSize(R.dimen.photoeditor_original_text_size);
-        mBackgroundColor = res.getColor(R.color.background_screen);
-        mOriginalText = res.getString(R.string.original_picture_text);
-        setupGestureDetector(context);
-        mActivity = (FilterShowActivity) context;
-        MasterImage.getImage().addObserver(this);
-    }
-
-    public void setupGestureDetector(Context context) {
-        mGestureDetector = new GestureDetector(context, this);
-        mScaleGestureDetector = new ScaleGestureDetector(context, this);
-    }
-
-    @Override
-    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
-        int parentWidth = MeasureSpec.getSize(widthMeasureSpec);
-        int parentHeight = MeasureSpec.getSize(heightMeasureSpec);
-        setMeasuredDimension(parentWidth, parentHeight);
-    }
-
-    public ImageFilter getCurrentFilter() {
-        return MasterImage.getImage().getCurrentFilter();
-    }
-
-    /* consider moving the following 2 methods into a subclass */
-    /**
-     * This function calculates a Image to Screen Transformation matrix
-     *
-     * @param reflectRotation set true if you want the rotation encoded
-     * @return Image to Screen transformation matrix
-     */
-    protected Matrix getImageToScreenMatrix(boolean reflectRotation) {
-        MasterImage master = MasterImage.getImage();
-        if (master.getOriginalBounds() == null) {
-            return new Matrix();
-        }
-        Matrix m = GeometryMathUtils.getImageToScreenMatrix(master.getPreset().getGeometryFilters(),
-                reflectRotation, master.getOriginalBounds(), getWidth(), getHeight());
-        Point translate = master.getTranslation();
-        float scaleFactor = master.getScaleFactor();
-        m.postTranslate(translate.x, translate.y);
-        m.postScale(scaleFactor, scaleFactor, getWidth() / 2.0f, getHeight() / 2.0f);
-        return m;
-    }
-
-    /**
-     * This function calculates a to Screen Image Transformation matrix
-     *
-     * @param reflectRotation set true if you want the rotation encoded
-     * @return Screen to Image transformation matrix
-     */
-    protected Matrix getScreenToImageMatrix(boolean reflectRotation) {
-        Matrix m = getImageToScreenMatrix(reflectRotation);
-        Matrix invert = new Matrix();
-        m.invert(invert);
-        return invert;
-    }
-
-    public ImagePreset getImagePreset() {
-        return MasterImage.getImage().getPreset();
-    }
-
-    @Override
-    public void onDraw(Canvas canvas) {
-        MasterImage.getImage().setImageShowSize(getWidth(), getHeight());
-
-        float cx = canvas.getWidth()/2.0f;
-        float cy = canvas.getHeight()/2.0f;
-        float scaleFactor = MasterImage.getImage().getScaleFactor();
-        Point translation = MasterImage.getImage().getTranslation();
-
-        Matrix scalingMatrix = new Matrix();
-        scalingMatrix.postScale(scaleFactor, scaleFactor, cx, cy);
-        scalingMatrix.preTranslate(translation.x, translation.y);
-
-        RectF unscaledClipRect = new RectF(mImageBounds);
-        scalingMatrix.mapRect(unscaledClipRect, unscaledClipRect);
-
-        canvas.save();
-
-        boolean enablePartialRendering = false;
-
-        // For now, partial rendering is disabled for all filters,
-        // so no need to clip.
-        if (enablePartialRendering && !unscaledClipRect.isEmpty()) {
-            canvas.clipRect(unscaledClipRect);
-        }
-
-        canvas.save();
-        // TODO: center scale on gesture
-        canvas.scale(scaleFactor, scaleFactor, cx, cy);
-        canvas.translate(translation.x, translation.y);
-        drawImage(canvas, getFilteredImage(), true);
-        Bitmap highresPreview = MasterImage.getImage().getHighresImage();
-        if (highresPreview != null) {
-            drawImage(canvas, highresPreview, true);
-        }
-        canvas.restore();
-
-        Bitmap partialPreview = MasterImage.getImage().getPartialImage();
-        if (partialPreview != null) {
-            Rect src = new Rect(0, 0, partialPreview.getWidth(), partialPreview.getHeight());
-            Rect dest = new Rect(0, 0, getWidth(), getHeight());
-            canvas.drawBitmap(partialPreview, src, dest, mPaint);
-        }
-
-        canvas.save();
-        canvas.scale(scaleFactor, scaleFactor, cx, cy);
-        canvas.translate(translation.x, translation.y);
-        drawPartialImage(canvas, getGeometryOnlyImage());
-        canvas.restore();
-
-        canvas.restore();
-    }
-
-    public void resetImageCaches(ImageShow caller) {
-        MasterImage.getImage().updatePresets(true);
-    }
-
-    public Bitmap getFiltersOnlyImage() {
-        return MasterImage.getImage().getFiltersOnlyImage();
-    }
-
-    public Bitmap getGeometryOnlyImage() {
-        return MasterImage.getImage().getGeometryOnlyImage();
-    }
-
-    public Bitmap getFilteredImage() {
-        return MasterImage.getImage().getFilteredImage();
-    }
-
-    public void drawImage(Canvas canvas, Bitmap image, boolean updateBounds) {
-        if (image != null) {
-            Rect s = new Rect(0, 0, image.getWidth(),
-                    image.getHeight());
-
-            float scale = GeometryMathUtils.scale(image.getWidth(), image.getHeight(), getWidth(),
-                    getHeight());
-
-            float w = image.getWidth() * scale;
-            float h = image.getHeight() * scale;
-            float ty = (getHeight() - h) / 2.0f;
-            float tx = (getWidth() - w) / 2.0f;
-
-            Rect d = new Rect((int) tx, (int) ty, (int) (w + tx),
-                    (int) (h + ty));
-            if (updateBounds) {
-                mImageBounds = d;
-            }
-            canvas.drawBitmap(image, s, d, mPaint);
-        }
-    }
-
-    public void drawPartialImage(Canvas canvas, Bitmap image) {
-        boolean showsOriginal = MasterImage.getImage().showsOriginal();
-        if (!showsOriginal && !mTouchShowOriginal)
-            return;
-        canvas.save();
-        if (image != null) {
-            if (mShowOriginalDirection == 0) {
-                if (Math.abs(mTouch.y - mTouchDown.y) > Math.abs(mTouch.x - mTouchDown.x)) {
-                    mShowOriginalDirection = UNVEIL_VERTICAL;
-                } else {
-                    mShowOriginalDirection = UNVEIL_HORIZONTAL;
-                }
-            }
-
-            int px = 0;
-            int py = 0;
-            if (mShowOriginalDirection == UNVEIL_VERTICAL) {
-                px = mImageBounds.width();
-                py = mTouch.y - mImageBounds.top;
-            } else {
-                px = mTouch.x - mImageBounds.left;
-                py = mImageBounds.height();
-                if (showsOriginal) {
-                    px = mImageBounds.width();
-                }
-            }
-
-            Rect d = new Rect(mImageBounds.left, mImageBounds.top,
-                    mImageBounds.left + px, mImageBounds.top + py);
-            canvas.clipRect(d);
-            drawImage(canvas, image, false);
-            Paint paint = new Paint();
-            paint.setColor(Color.BLACK);
-            paint.setStrokeWidth(3);
-
-            if (mShowOriginalDirection == UNVEIL_VERTICAL) {
-                canvas.drawLine(mImageBounds.left, mTouch.y,
-                        mImageBounds.right, mTouch.y, paint);
-            } else {
-                canvas.drawLine(mTouch.x, mImageBounds.top,
-                        mTouch.x, mImageBounds.bottom, paint);
-            }
-
-            Rect bounds = new Rect();
-            paint.setAntiAlias(true);
-            paint.setTextSize(mOriginalTextSize);
-            paint.getTextBounds(mOriginalText, 0, mOriginalText.length(), bounds);
-            paint.setColor(Color.BLACK);
-            paint.setStyle(Paint.Style.STROKE);
-            paint.setStrokeWidth(3);
-            canvas.drawText(mOriginalText, mImageBounds.left + mOriginalTextMargin,
-                    mImageBounds.top + bounds.height() + mOriginalTextMargin, paint);
-            paint.setStyle(Paint.Style.FILL);
-            paint.setStrokeWidth(1);
-            paint.setColor(Color.WHITE);
-            canvas.drawText(mOriginalText, mImageBounds.left + mOriginalTextMargin,
-                    mImageBounds.top + bounds.height() + mOriginalTextMargin, paint);
-        }
-        canvas.restore();
-    }
-
-    public void bindAsImageLoadListener() {
-        MasterImage.getImage().addListener(this);
-    }
-
-    public void updateImage() {
-        invalidate();
-    }
-
-    public void imageLoaded() {
-        updateImage();
-    }
-
-    public void saveImage(FilterShowActivity filterShowActivity, File file) {
-        SaveImage.saveImage(getImagePreset(), filterShowActivity, file);
-    }
-
-
-    public boolean scaleInProgress() {
-        return mScaleGestureDetector.isInProgress();
-    }
-
-    @Override
-    public boolean onTouchEvent(MotionEvent event) {
-        super.onTouchEvent(event);
-        int action = event.getAction();
-        action = action & MotionEvent.ACTION_MASK;
-
-        mGestureDetector.onTouchEvent(event);
-        boolean scaleInProgress = scaleInProgress();
-        mScaleGestureDetector.onTouchEvent(event);
-        if (mInteractionMode == InteractionMode.SCALE) {
-            return true;
-        }
-        if (!scaleInProgress() && scaleInProgress) {
-            // If we were scaling, the scale will stop but we will
-            // still issue an ACTION_UP. Let the subclasses know.
-            mFinishedScalingOperation = true;
-        }
-
-        int ex = (int) event.getX();
-        int ey = (int) event.getY();
-        if (action == MotionEvent.ACTION_DOWN) {
-            mInteractionMode = InteractionMode.MOVE;
-            mTouchDown.x = ex;
-            mTouchDown.y = ey;
-            mTouchShowOriginalDate = System.currentTimeMillis();
-            mShowOriginalDirection = 0;
-            MasterImage.getImage().setOriginalTranslation(MasterImage.getImage().getTranslation());
-        }
-
-        if (action == MotionEvent.ACTION_MOVE && mInteractionMode == InteractionMode.MOVE) {
-            mTouch.x = ex;
-            mTouch.y = ey;
-
-            float scaleFactor = MasterImage.getImage().getScaleFactor();
-            if (scaleFactor > 1 && (!ENABLE_ZOOMED_COMPARISON || event.getPointerCount() == 2)) {
-                float translateX = (mTouch.x - mTouchDown.x) / scaleFactor;
-                float translateY = (mTouch.y - mTouchDown.y) / scaleFactor;
-                Point originalTranslation = MasterImage.getImage().getOriginalTranslation();
-                Point translation = MasterImage.getImage().getTranslation();
-                translation.x = (int) (originalTranslation.x + translateX);
-                translation.y = (int) (originalTranslation.y + translateY);
-                constrainTranslation(translation, scaleFactor);
-                MasterImage.getImage().setTranslation(translation);
-                mTouchShowOriginal = false;
-            } else if (enableComparison() && !mOriginalDisabled
-                    && (System.currentTimeMillis() - mTouchShowOriginalDate
-                            > mTouchShowOriginalDelayMin)
-                    && event.getPointerCount() == 1) {
-                mTouchShowOriginal = true;
-            }
-        }
-
-        if (action == MotionEvent.ACTION_UP) {
-            mInteractionMode = InteractionMode.NONE;
-            mTouchShowOriginal = false;
-            mTouchDown.x = 0;
-            mTouchDown.y = 0;
-            mTouch.x = 0;
-            mTouch.y = 0;
-            if (MasterImage.getImage().getScaleFactor() <= 1) {
-                MasterImage.getImage().setScaleFactor(1);
-                MasterImage.getImage().resetTranslation();
-            }
-        }
-        invalidate();
-        return true;
-    }
-
-    protected boolean enableComparison() {
-        return true;
-    }
-
-    @Override
-    public boolean onDoubleTap(MotionEvent arg0) {
-        mZoomIn = !mZoomIn;
-        float scale = 1.0f;
-        if (mZoomIn) {
-            scale = MasterImage.getImage().getMaxScaleFactor();
-        }
-        if (scale != MasterImage.getImage().getScaleFactor()) {
-            MasterImage.getImage().setScaleFactor(scale);
-            float translateX = (getWidth() / 2 - arg0.getX());
-            float translateY = (getHeight() / 2 - arg0.getY());
-            Point translation = MasterImage.getImage().getTranslation();
-            translation.x = (int) (mOriginalTranslation.x + translateX);
-            translation.y = (int) (mOriginalTranslation.y + translateY);
-            constrainTranslation(translation, scale);
-            MasterImage.getImage().setTranslation(translation);
-            invalidate();
-        }
-        return true;
-    }
-
-    private void constrainTranslation(Point translation, float scale) {
-        float maxTranslationX = getWidth() / scale;
-        float maxTranslationY = getHeight() / scale;
-        if (Math.abs(translation.x) > maxTranslationX) {
-            translation.x = (int) (Math.signum(translation.x) *
-                    maxTranslationX);
-            if (Math.abs(translation.y) > maxTranslationY) {
-                translation.y = (int) (Math.signum(translation.y) *
-                        maxTranslationY);
-            }
-
-        }
-    }
-
-    @Override
-    public boolean onDoubleTapEvent(MotionEvent arg0) {
-        return false;
-    }
-
-    @Override
-    public boolean onSingleTapConfirmed(MotionEvent arg0) {
-        return false;
-    }
-
-    @Override
-    public boolean onDown(MotionEvent arg0) {
-        return false;
-    }
-
-    @Override
-    public boolean onFling(MotionEvent startEvent, MotionEvent endEvent, float arg2, float arg3) {
-        if (mActivity == null) {
-            return false;
-        }
-        if (endEvent.getPointerCount() == 2) {
-            return false;
-        }
-        return true;
-    }
-
-    @Override
-    public void onLongPress(MotionEvent arg0) {
-    }
-
-    @Override
-    public boolean onScroll(MotionEvent arg0, MotionEvent arg1, float arg2, float arg3) {
-        return false;
-    }
-
-    @Override
-    public void onShowPress(MotionEvent arg0) {
-    }
-
-    @Override
-    public boolean onSingleTapUp(MotionEvent arg0) {
-        return false;
-    }
-
-    public boolean useUtilityPanel() {
-        return false;
-    }
-
-    public void openUtilityPanel(final LinearLayout accessoryViewList) {
-    }
-
-    @Override
-    public boolean onScale(ScaleGestureDetector detector) {
-        MasterImage img = MasterImage.getImage();
-        float scaleFactor = img.getScaleFactor();
-
-        scaleFactor = scaleFactor * detector.getScaleFactor();
-        if (scaleFactor > MasterImage.getImage().getMaxScaleFactor()) {
-            scaleFactor = MasterImage.getImage().getMaxScaleFactor();
-        }
-        if (scaleFactor < 0.5) {
-            scaleFactor = 0.5f;
-        }
-        MasterImage.getImage().setScaleFactor(scaleFactor);
-        scaleFactor = img.getScaleFactor();
-        float focusx = detector.getFocusX();
-        float focusy = detector.getFocusY();
-        float translateX = (focusx - mStartFocusX) / scaleFactor;
-        float translateY = (focusy - mStartFocusY) / scaleFactor;
-        Point translation = MasterImage.getImage().getTranslation();
-        translation.x = (int) (mOriginalTranslation.x + translateX);
-        translation.y = (int) (mOriginalTranslation.y + translateY);
-        constrainTranslation(translation, scaleFactor);
-        MasterImage.getImage().setTranslation(translation);
-
-        invalidate();
-        return true;
-    }
-
-    @Override
-    public boolean onScaleBegin(ScaleGestureDetector detector) {
-        Point pos = MasterImage.getImage().getTranslation();
-        mOriginalTranslation.x = pos.x;
-        mOriginalTranslation.y = pos.y;
-        mOriginalScale = MasterImage.getImage().getScaleFactor();
-        mStartFocusX = detector.getFocusX();
-        mStartFocusY = detector.getFocusY();
-        mInteractionMode = InteractionMode.SCALE;
-        return true;
-    }
-
-    @Override
-    public void onScaleEnd(ScaleGestureDetector detector) {
-        mInteractionMode = InteractionMode.NONE;
-        if (MasterImage.getImage().getScaleFactor() < 1) {
-            MasterImage.getImage().setScaleFactor(1);
-            invalidate();
-        }
-    }
-
-    public boolean didFinishScalingOperation() {
-        if (mFinishedScalingOperation) {
-            mFinishedScalingOperation = false;
-            return true;
-        }
-        return false;
-    }
-
-}
diff --git a/src/com/android/gallery3d/filtershow/imageshow/ImageStraighten.java b/src/com/android/gallery3d/filtershow/imageshow/ImageStraighten.java
deleted file mode 100644
index ff75dcc..0000000
--- a/src/com/android/gallery3d/filtershow/imageshow/ImageStraighten.java
+++ /dev/null
@@ -1,260 +0,0 @@
-/*
- * 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.gallery3d.filtershow.imageshow;
-
-import android.content.Context;
-import android.graphics.Bitmap;
-import android.graphics.Canvas;
-import android.graphics.Color;
-import android.graphics.Matrix;
-import android.graphics.Paint;
-import android.graphics.Paint.Style;
-import android.graphics.Path;
-import android.graphics.RectF;
-import android.util.AttributeSet;
-import android.view.MotionEvent;
-
-import com.android.gallery3d.filtershow.editors.EditorStraighten;
-import com.android.gallery3d.filtershow.filters.FilterCropRepresentation;
-import com.android.gallery3d.filtershow.filters.FilterRepresentation;
-import com.android.gallery3d.filtershow.filters.FilterStraightenRepresentation;
-import com.android.gallery3d.filtershow.imageshow.GeometryMathUtils.GeometryHolder;
-
-import java.util.ArrayList;
-import java.util.Collection;
-
-
-public class ImageStraighten extends ImageShow {
-    private static final String TAG = ImageStraighten.class.getSimpleName();
-    private float mBaseAngle = 0;
-    private float mAngle = 0;
-    private float mInitialAngle = 0;
-    private boolean mFirstDrawSinceUp = false;
-    private EditorStraighten mEditorStraighten;
-    private FilterStraightenRepresentation mLocalRep = new FilterStraightenRepresentation();
-    private RectF mPriorCropAtUp = new RectF();
-    private RectF mDrawRect = new RectF();
-    private Path mDrawPath = new Path();
-    private GeometryHolder mDrawHolder = new GeometryHolder();
-    private enum MODES {
-        NONE, MOVE
-    }
-    private MODES mState = MODES.NONE;
-    private static final float MAX_STRAIGHTEN_ANGLE
-        = FilterStraightenRepresentation.MAX_STRAIGHTEN_ANGLE;
-    private static final float MIN_STRAIGHTEN_ANGLE
-        = FilterStraightenRepresentation.MIN_STRAIGHTEN_ANGLE;
-    private float mCurrentX;
-    private float mCurrentY;
-    private float mTouchCenterX;
-    private float mTouchCenterY;
-    private RectF mCrop = new RectF();
-    private final Paint mPaint = new Paint();
-
-    public ImageStraighten(Context context) {
-        super(context);
-    }
-
-    public ImageStraighten(Context context, AttributeSet attrs) {
-        super(context, attrs);
-    }
-
-    public void setFilterStraightenRepresentation(FilterStraightenRepresentation rep) {
-        mLocalRep = (rep == null) ? new FilterStraightenRepresentation() : rep;
-        mInitialAngle = mBaseAngle = mAngle = mLocalRep.getStraighten();
-    }
-
-    public Collection<FilterRepresentation> getFinalRepresentation() {
-        ArrayList<FilterRepresentation> reps = new ArrayList<FilterRepresentation>(2);
-        reps.add(mLocalRep);
-        if (mInitialAngle != mLocalRep.getStraighten()) {
-            reps.add(new FilterCropRepresentation(mCrop));
-        }
-        return reps;
-    }
-
-    @Override
-    public boolean onTouchEvent(MotionEvent event) {
-        float x = event.getX();
-        float y = event.getY();
-
-        switch (event.getActionMasked()) {
-            case (MotionEvent.ACTION_DOWN):
-                if (mState == MODES.NONE) {
-                    mTouchCenterX = x;
-                    mTouchCenterY = y;
-                    mCurrentX = x;
-                    mCurrentY = y;
-                    mState = MODES.MOVE;
-                    mBaseAngle = mAngle;
-                }
-                break;
-            case (MotionEvent.ACTION_UP):
-                if (mState == MODES.MOVE) {
-                    mState = MODES.NONE;
-                    mCurrentX = x;
-                    mCurrentY = y;
-                    computeValue();
-                    mFirstDrawSinceUp = true;
-                }
-                break;
-            case (MotionEvent.ACTION_MOVE):
-                if (mState == MODES.MOVE) {
-                    mCurrentX = x;
-                    mCurrentY = y;
-                    computeValue();
-                }
-                break;
-            default:
-                break;
-        }
-        invalidate();
-        return true;
-    }
-
-    private static float angleFor(float dx, float dy) {
-        return (float) (Math.atan2(dx, dy) * 180 / Math.PI);
-    }
-
-    private float getCurrentTouchAngle() {
-        float centerX = getWidth() / 2f;
-        float centerY = getHeight() / 2f;
-        if (mCurrentX == mTouchCenterX && mCurrentY == mTouchCenterY) {
-            return 0;
-        }
-        float dX1 = mTouchCenterX - centerX;
-        float dY1 = mTouchCenterY - centerY;
-        float dX2 = mCurrentX - centerX;
-        float dY2 = mCurrentY - centerY;
-        float angleA = angleFor(dX1, dY1);
-        float angleB = angleFor(dX2, dY2);
-        return (angleB - angleA) % 360;
-    }
-
-    private void computeValue() {
-        float angle = getCurrentTouchAngle();
-        mAngle = (mBaseAngle - angle) % 360;
-        mAngle = Math.max(MIN_STRAIGHTEN_ANGLE, mAngle);
-        mAngle = Math.min(MAX_STRAIGHTEN_ANGLE, mAngle);
-    }
-
-    private static void getUntranslatedStraightenCropBounds(RectF outRect, float straightenAngle) {
-        float deg = straightenAngle;
-        if (deg < 0) {
-            deg = -deg;
-        }
-        double a = Math.toRadians(deg);
-        double sina = Math.sin(a);
-        double cosa = Math.cos(a);
-        double rw = outRect.width();
-        double rh = outRect.height();
-        double h1 = rh * rh / (rw * sina + rh * cosa);
-        double h2 = rh * rw / (rw * cosa + rh * sina);
-        double hh = Math.min(h1, h2);
-        double ww = hh * rw / rh;
-        float left = (float) ((rw - ww) * 0.5f);
-        float top = (float) ((rh - hh) * 0.5f);
-        float right = (float) (left + ww);
-        float bottom = (float) (top + hh);
-        outRect.set(left, top, right, bottom);
-    }
-
-    private void updateCurrentCrop(Matrix m, GeometryHolder h, RectF tmp, int imageWidth,
-            int imageHeight, int viewWidth, int viewHeight) {
-        if (GeometryMathUtils.needsDimensionSwap(h.rotation)) {
-            tmp.set(0, 0, imageHeight, imageWidth);
-        } else {
-            tmp.set(0, 0, imageWidth, imageHeight);
-        }
-        float scale = GeometryMathUtils.scale(imageWidth, imageHeight, viewWidth, viewHeight);
-        GeometryMathUtils.scaleRect(tmp, scale);
-        getUntranslatedStraightenCropBounds(tmp, mAngle);
-        tmp.offset(viewWidth / 2f - tmp.centerX(), viewHeight / 2f - tmp.centerY());
-        h.straighten = 0;
-        Matrix m1 = GeometryMathUtils.getFullGeometryToScreenMatrix(h, imageWidth,
-                imageHeight, viewWidth, viewHeight);
-        m.reset();
-        m1.invert(m);
-        mCrop.set(tmp);
-        m.mapRect(mCrop);
-        FilterCropRepresentation.findNormalizedCrop(mCrop, imageWidth, imageHeight);
-    }
-
-
-    @Override
-    public void onDraw(Canvas canvas) {
-        MasterImage master = MasterImage.getImage();
-        Bitmap image = master.getFiltersOnlyImage();
-        if (image == null) {
-            return;
-        }
-        GeometryMathUtils.initializeHolder(mDrawHolder, mLocalRep);
-        mDrawHolder.straighten = mAngle;
-        int imageWidth = image.getWidth();
-        int imageHeight = image.getHeight();
-        int viewWidth = canvas.getWidth();
-        int viewHeight = canvas.getHeight();
-
-        // Get matrix for drawing bitmap
-        Matrix m = GeometryMathUtils.getFullGeometryToScreenMatrix(mDrawHolder, imageWidth,
-                imageHeight, viewWidth, viewHeight);
-        mPaint.reset();
-        mPaint.setAntiAlias(true);
-        mPaint.setFilterBitmap(true);
-        canvas.drawBitmap(image, m, mPaint);
-
-        mPaint.setFilterBitmap(false);
-        mPaint.setColor(Color.WHITE);
-        mPaint.setStrokeWidth(2);
-        mPaint.setStyle(Paint.Style.FILL_AND_STROKE);
-        updateCurrentCrop(m, mDrawHolder, mDrawRect, imageWidth,
-                imageHeight, viewWidth, viewHeight);
-        if (mFirstDrawSinceUp) {
-            mPriorCropAtUp.set(mCrop);
-            mLocalRep.setStraighten(mAngle);
-            mFirstDrawSinceUp = false;
-        }
-
-        // Draw the grid
-        if (mState == MODES.MOVE) {
-            canvas.save();
-            canvas.clipRect(mDrawRect);
-            int n = 16;
-            float step = viewWidth / n;
-            float p = 0;
-            for (int i = 1; i < n; i++) {
-                p = i * step;
-                mPaint.setAlpha(60);
-                canvas.drawLine(p, 0, p, viewHeight, mPaint);
-                canvas.drawLine(0, p, viewHeight, p, mPaint);
-            }
-            canvas.restore();
-        }
-        mPaint.reset();
-        mPaint.setColor(Color.WHITE);
-        mPaint.setStyle(Style.STROKE);
-        mPaint.setStrokeWidth(3);
-        mDrawPath.reset();
-        mDrawPath.addRect(mDrawRect, Path.Direction.CW);
-        canvas.drawPath(mDrawPath, mPaint);
-    }
-
-    public void setEditor(EditorStraighten editorStraighten) {
-        mEditorStraighten = editorStraighten;
-    }
-
-}
diff --git a/src/com/android/gallery3d/filtershow/imageshow/ImageTinyPlanet.java b/src/com/android/gallery3d/filtershow/imageshow/ImageTinyPlanet.java
deleted file mode 100644
index 25a0a90..0000000
--- a/src/com/android/gallery3d/filtershow/imageshow/ImageTinyPlanet.java
+++ /dev/null
@@ -1,174 +0,0 @@
-/*
- * 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.gallery3d.filtershow.imageshow;
-
-import android.content.Context;
-import android.graphics.Bitmap;
-import android.graphics.Canvas;
-import android.graphics.RectF;
-import android.util.AttributeSet;
-import android.view.MotionEvent;
-import android.view.ScaleGestureDetector;
-import android.view.ScaleGestureDetector.OnScaleGestureListener;
-
-import com.android.gallery3d.filtershow.editors.BasicEditor;
-import com.android.gallery3d.filtershow.editors.EditorTinyPlanet;
-import com.android.gallery3d.filtershow.filters.FilterTinyPlanetRepresentation;
-
-public class ImageTinyPlanet extends ImageShow {
-    private static final String LOGTAG = "ImageTinyPlanet";
-
-    private float mTouchCenterX = 0;
-    private float mTouchCenterY = 0;
-    private float mCurrentX = 0;
-    private float mCurrentY = 0;
-    private float mCenterX = 0;
-    private float mCenterY = 0;
-    private float mStartAngle = 0;
-    private FilterTinyPlanetRepresentation mTinyPlanetRep;
-    private EditorTinyPlanet mEditorTinyPlanet;
-    private ScaleGestureDetector mScaleGestureDetector = null;
-    boolean mInScale = false;
-    RectF mDestRect = new RectF();
-
-    OnScaleGestureListener mScaleGestureListener = new OnScaleGestureListener() {
-        private float mScale = 100;
-        @Override
-        public void onScaleEnd(ScaleGestureDetector detector) {
-            mInScale = false;
-        }
-
-        @Override
-        public boolean onScaleBegin(ScaleGestureDetector detector) {
-            mInScale = true;
-            mScale = mTinyPlanetRep.getValue();
-            return true;
-        }
-
-        @Override
-        public boolean onScale(ScaleGestureDetector detector) {
-            int value = mTinyPlanetRep.getValue();
-            mScale *= detector.getScaleFactor();
-            value = (int) (mScale);
-            value = Math.min(mTinyPlanetRep.getMaximum(), value);
-            value = Math.max(mTinyPlanetRep.getMinimum(), value);
-            mTinyPlanetRep.setValue(value);
-            invalidate();
-            mEditorTinyPlanet.commitLocalRepresentation();
-            mEditorTinyPlanet.updateUI();
-            return true;
-        }
-    };
-
-    public ImageTinyPlanet(Context context) {
-        super(context);
-        mScaleGestureDetector = new ScaleGestureDetector(context, mScaleGestureListener);
-    }
-
-    public ImageTinyPlanet(Context context, AttributeSet attrs) {
-        super(context, attrs);
-        mScaleGestureDetector = new ScaleGestureDetector(context,mScaleGestureListener );
-    }
-
-    protected static float angleFor(float dx, float dy) {
-        return (float) (Math.atan2(dx, dy) * 180 / Math.PI);
-    }
-
-    protected float getCurrentTouchAngle() {
-        if (mCurrentX == mTouchCenterX && mCurrentY == mTouchCenterY) {
-            return 0;
-        }
-        float dX1 = mTouchCenterX - mCenterX;
-        float dY1 = mTouchCenterY - mCenterY;
-        float dX2 = mCurrentX - mCenterX;
-        float dY2 = mCurrentY - mCenterY;
-
-        float angleA = angleFor(dX1, dY1);
-        float angleB = angleFor(dX2, dY2);
-        return (float) (((angleB - angleA) % 360) * Math.PI / 180);
-    }
-
-    @Override
-    public boolean onTouchEvent(MotionEvent event) {
-        float x = event.getX();
-        float y = event.getY();
-        mCurrentX = x;
-        mCurrentY = y;
-        mCenterX = getWidth() / 2;
-        mCenterY = getHeight() / 2;
-        mScaleGestureDetector.onTouchEvent(event);
-        if (mInScale) {
-            return true;
-        }
-        switch (event.getActionMasked()) {
-            case (MotionEvent.ACTION_DOWN):
-                mTouchCenterX = x;
-                mTouchCenterY = y;
-                mStartAngle = mTinyPlanetRep.getAngle();
-                break;
-
-            case (MotionEvent.ACTION_MOVE):
-                mTinyPlanetRep.setAngle(mStartAngle + getCurrentTouchAngle());
-                break;
-        }
-        invalidate();
-        mEditorTinyPlanet.commitLocalRepresentation();
-        return true;
-    }
-
-    public void setRepresentation(FilterTinyPlanetRepresentation tinyPlanetRep) {
-        mTinyPlanetRep = tinyPlanetRep;
-    }
-
-    public void setEditor(BasicEditor editorTinyPlanet) {
-        mEditorTinyPlanet = (EditorTinyPlanet) editorTinyPlanet;
-    }
-
-    @Override
-    public void onDraw(Canvas canvas) {
-        Bitmap bitmap = MasterImage.getImage().getHighresImage();
-        if (bitmap == null) {
-            bitmap = MasterImage.getImage().getFilteredImage();
-        }
-
-        if (bitmap != null) {
-            display(canvas, bitmap);
-        }
-    }
-
-    private void display(Canvas canvas, Bitmap bitmap) {
-        float sw = canvas.getWidth();
-        float sh = canvas.getHeight();
-        float iw = bitmap.getWidth();
-        float ih = bitmap.getHeight();
-        float nsw = sw;
-        float nsh = sh;
-
-        if (sw * ih > sh * iw) {
-            nsw = sh * iw / ih;
-        } else {
-            nsh = sw * ih / iw;
-        }
-
-        mDestRect.left = (sw - nsw) / 2;
-        mDestRect.top = (sh - nsh) / 2;
-        mDestRect.right = sw - mDestRect.left;
-        mDestRect.bottom = sh - mDestRect.top;
-
-        canvas.drawBitmap(bitmap, null, mDestRect, mPaint);
-    }
-}
diff --git a/src/com/android/gallery3d/filtershow/imageshow/ImageVignette.java b/src/com/android/gallery3d/filtershow/imageshow/ImageVignette.java
deleted file mode 100644
index 518969e..0000000
--- a/src/com/android/gallery3d/filtershow/imageshow/ImageVignette.java
+++ /dev/null
@@ -1,165 +0,0 @@
-/*
- * Copyright (C) 2013 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.gallery3d.filtershow.imageshow;
-
-import android.content.Context;
-import android.graphics.Canvas;
-import android.graphics.Matrix;
-import android.util.AttributeSet;
-import android.util.Log;
-import android.view.MotionEvent;
-
-import com.android.gallery3d.filtershow.editors.EditorVignette;
-import com.android.gallery3d.filtershow.filters.FilterVignetteRepresentation;
-
-public class ImageVignette extends ImageShow {
-    private static final String LOGTAG = "ImageVignette";
-
-    private FilterVignetteRepresentation mVignetteRep;
-    private EditorVignette mEditorVignette;
-
-    private int mActiveHandle = -1;
-
-    EclipseControl mElipse;
-
-    public ImageVignette(Context context) {
-        super(context);
-        mElipse = new EclipseControl(context);
-    }
-
-    public ImageVignette(Context context, AttributeSet attrs) {
-        super(context, attrs);
-        mElipse = new EclipseControl(context);
-    }
-
-    @Override
-    public boolean onTouchEvent(MotionEvent event) {
-        int mask = event.getActionMasked();
-        if (mActiveHandle == -1) {
-            if (MotionEvent.ACTION_DOWN != mask) {
-                return super.onTouchEvent(event);
-            }
-            if (event.getPointerCount() == 1) {
-                mActiveHandle = mElipse.getCloseHandle(event.getX(), event.getY());
-            }
-            if (mActiveHandle == -1) {
-                return super.onTouchEvent(event);
-            }
-        } else {
-            switch (mask) {
-                case MotionEvent.ACTION_UP:
-                    mActiveHandle = -1;
-                    break;
-                case MotionEvent.ACTION_DOWN:
-                    break;
-            }
-        }
-        float x = event.getX();
-        float y = event.getY();
-
-        mElipse.setScrToImageMatrix(getScreenToImageMatrix(true));
-
-        boolean didComputeEllipses = false;
-        switch (mask) {
-            case (MotionEvent.ACTION_DOWN):
-                mElipse.actionDown(x, y, mVignetteRep);
-                break;
-            case (MotionEvent.ACTION_UP):
-            case (MotionEvent.ACTION_MOVE):
-                mElipse.actionMove(mActiveHandle, x, y, mVignetteRep);
-                setRepresentation(mVignetteRep);
-                didComputeEllipses = true;
-                break;
-        }
-        if (!didComputeEllipses) {
-            computeEllipses();
-        }
-        invalidate();
-        return true;
-    }
-
-    public void setRepresentation(FilterVignetteRepresentation vignetteRep) {
-        mVignetteRep = vignetteRep;
-        computeEllipses();
-    }
-
-    public void computeEllipses() {
-        if (mVignetteRep == null) {
-            return;
-        }
-        Matrix toImg = getScreenToImageMatrix(false);
-        Matrix toScr = new Matrix();
-        toImg.invert(toScr);
-
-        float[] c = new float[] {
-                mVignetteRep.getCenterX(), mVignetteRep.getCenterY() };
-        if (Float.isNaN(c[0])) {
-            float cx = MasterImage.getImage().getOriginalBounds().width() / 2;
-            float cy = MasterImage.getImage().getOriginalBounds().height() / 2;
-            float rx = Math.min(cx, cy) * .8f;
-            float ry = rx;
-            mVignetteRep.setCenter(cx, cy);
-            mVignetteRep.setRadius(rx, ry);
-
-            c[0] = cx;
-            c[1] = cy;
-            toScr.mapPoints(c);
-            if (getWidth() != 0) {
-                mElipse.setCenter(c[0], c[1]);
-                mElipse.setRadius(c[0] * 0.8f, c[1] * 0.8f);
-            }
-        } else {
-
-            toScr.mapPoints(c);
-
-            mElipse.setCenter(c[0], c[1]);
-            mElipse.setRadius(toScr.mapRadius(mVignetteRep.getRadiusX()),
-                    toScr.mapRadius(mVignetteRep.getRadiusY()));
-        }
-        mEditorVignette.commitLocalRepresentation();
-    }
-
-    public void setEditor(EditorVignette editorVignette) {
-        mEditorVignette = editorVignette;
-    }
-
-    @Override
-    public void onSizeChanged(int w, int h, int oldw, int oldh) {
-        super.onSizeChanged(w,  h, oldw, oldh);
-        computeEllipses();
-    }
-
-    @Override
-    public void onDraw(Canvas canvas) {
-        super.onDraw(canvas);
-        if (mVignetteRep == null) {
-            return;
-        }
-        Matrix toImg = getScreenToImageMatrix(false);
-        Matrix toScr = new Matrix();
-        toImg.invert(toScr);
-        float[] c = new float[] {
-                mVignetteRep.getCenterX(), mVignetteRep.getCenterY() };
-        toScr.mapPoints(c);
-        mElipse.setCenter(c[0], c[1]);
-        mElipse.setRadius(toScr.mapRadius(mVignetteRep.getRadiusX()),
-                toScr.mapRadius(mVignetteRep.getRadiusY()));
-
-        mElipse.draw(canvas);
-    }
-
-}
diff --git a/src/com/android/gallery3d/filtershow/imageshow/Line.java b/src/com/android/gallery3d/filtershow/imageshow/Line.java
deleted file mode 100644
index a767bd8..0000000
--- a/src/com/android/gallery3d/filtershow/imageshow/Line.java
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * 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.gallery3d.filtershow.imageshow;
-
-public interface Line {
-    void setPoint1(float x, float y);
-    void setPoint2(float x, float y);
-    float getPoint1X();
-    float getPoint1Y();
-    float getPoint2X();
-    float getPoint2Y();
-}
diff --git a/src/com/android/gallery3d/filtershow/imageshow/MasterImage.java b/src/com/android/gallery3d/filtershow/imageshow/MasterImage.java
deleted file mode 100644
index 92e57bf..0000000
--- a/src/com/android/gallery3d/filtershow/imageshow/MasterImage.java
+++ /dev/null
@@ -1,581 +0,0 @@
-/*
- * Copyright (C) 2013 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.gallery3d.filtershow.imageshow;
-
-import android.graphics.Bitmap;
-import android.graphics.Matrix;
-import android.graphics.Point;
-import android.graphics.Rect;
-import android.graphics.RectF;
-import android.net.Uri;
-import android.os.Handler;
-import android.os.Message;
-
-import com.android.gallery3d.filtershow.FilterShowActivity;
-import com.android.gallery3d.filtershow.cache.ImageLoader;
-import com.android.gallery3d.filtershow.filters.FilterRepresentation;
-import com.android.gallery3d.filtershow.filters.ImageFilter;
-import com.android.gallery3d.filtershow.history.HistoryItem;
-import com.android.gallery3d.filtershow.history.HistoryManager;
-import com.android.gallery3d.filtershow.pipeline.Buffer;
-import com.android.gallery3d.filtershow.pipeline.ImagePreset;
-import com.android.gallery3d.filtershow.pipeline.RenderingRequest;
-import com.android.gallery3d.filtershow.pipeline.RenderingRequestCaller;
-import com.android.gallery3d.filtershow.pipeline.SharedBuffer;
-import com.android.gallery3d.filtershow.pipeline.SharedPreset;
-import com.android.gallery3d.filtershow.state.StateAdapter;
-
-import java.util.Vector;
-
-public class MasterImage implements RenderingRequestCaller {
-
-    private static final String LOGTAG = "MasterImage";
-    private boolean DEBUG  = false;
-    private static final boolean DISABLEZOOM = false;
-    public static final int SMALL_BITMAP_DIM = 160;
-    public static final int MAX_BITMAP_DIM = 900;
-    private static MasterImage sMasterImage = null;
-
-    private boolean mSupportsHighRes = false;
-
-    private ImageFilter mCurrentFilter = null;
-    private ImagePreset mPreset = null;
-    private ImagePreset mLoadedPreset = null;
-    private ImagePreset mGeometryOnlyPreset = null;
-    private ImagePreset mFiltersOnlyPreset = null;
-
-    private SharedBuffer mPreviewBuffer = new SharedBuffer();
-    private SharedPreset mPreviewPreset = new SharedPreset();
-
-    private Bitmap mOriginalBitmapSmall = null;
-    private Bitmap mOriginalBitmapLarge = null;
-    private Bitmap mOriginalBitmapHighres = null;
-    private int mOrientation;
-    private Rect mOriginalBounds;
-    private final Vector<ImageShow> mLoadListeners = new Vector<ImageShow>();
-    private Uri mUri = null;
-    private int mZoomOrientation = ImageLoader.ORI_NORMAL;
-
-    private Bitmap mGeometryOnlyBitmap = null;
-    private Bitmap mFiltersOnlyBitmap = null;
-    private Bitmap mPartialBitmap = null;
-    private Bitmap mHighresBitmap = null;
-
-    private HistoryManager mHistory = null;
-    private StateAdapter mState = null;
-
-    private FilterShowActivity mActivity = null;
-
-    private Vector<ImageShow> mObservers = new Vector<ImageShow>();
-    private FilterRepresentation mCurrentFilterRepresentation;
-
-    private float mScaleFactor = 1.0f;
-    private float mMaxScaleFactor = 3.0f; // TODO: base this on the current view / image
-    private Point mTranslation = new Point();
-    private Point mOriginalTranslation = new Point();
-
-    private Point mImageShowSize = new Point();
-
-    private boolean mShowsOriginal;
-
-    private MasterImage() {
-    }
-
-    // TODO: remove singleton
-    public static void setMaster(MasterImage master) {
-        sMasterImage = master;
-    }
-
-    public static MasterImage getImage() {
-        if (sMasterImage == null) {
-            sMasterImage = new MasterImage();
-        }
-        return sMasterImage;
-    }
-
-    public Bitmap getOriginalBitmapSmall() {
-        return mOriginalBitmapSmall;
-    }
-
-    public Bitmap getOriginalBitmapLarge() {
-        return mOriginalBitmapLarge;
-    }
-
-    public Bitmap getOriginalBitmapHighres() {
-        return mOriginalBitmapHighres;
-    }
-
-    public void setOriginalBitmapHighres(Bitmap mOriginalBitmapHighres) {
-        this.mOriginalBitmapHighres = mOriginalBitmapHighres;
-    }
-
-    public int getOrientation() {
-        return mOrientation;
-    }
-
-    public Rect getOriginalBounds() {
-        return mOriginalBounds;
-    }
-
-    public void setOriginalBounds(Rect r) {
-        mOriginalBounds = r;
-    }
-
-    public Uri getUri() {
-        return mUri;
-    }
-
-    public void setUri(Uri uri) {
-        mUri = uri;
-    }
-
-    public int getZoomOrientation() {
-        return mZoomOrientation;
-    }
-
-    public void addListener(ImageShow imageShow) {
-        if (!mLoadListeners.contains(imageShow)) {
-            mLoadListeners.add(imageShow);
-        }
-    }
-
-    public void warnListeners() {
-        mActivity.runOnUiThread(mWarnListenersRunnable);
-    }
-
-    private Runnable mWarnListenersRunnable = new Runnable() {
-        @Override
-        public void run() {
-            for (int i = 0; i < mLoadListeners.size(); i++) {
-                ImageShow imageShow = mLoadListeners.elementAt(i);
-                imageShow.imageLoaded();
-            }
-            invalidatePreview();
-        }
-    };
-
-    public boolean loadBitmap(Uri uri, int size) {
-        setUri(uri);
-        mOrientation = ImageLoader.getMetadataOrientation(mActivity, uri);
-        Rect originalBounds = new Rect();
-        mOriginalBitmapLarge = ImageLoader.loadOrientedConstrainedBitmap(uri, mActivity,
-                Math.min(MAX_BITMAP_DIM, size),
-                mOrientation, originalBounds);
-        setOriginalBounds(originalBounds);
-        if (mOriginalBitmapLarge == null) {
-            return false;
-        }
-        int sw = SMALL_BITMAP_DIM;
-        int sh = (int) (sw * (float) mOriginalBitmapLarge.getHeight() / mOriginalBitmapLarge
-                .getWidth());
-        mOriginalBitmapSmall = Bitmap.createScaledBitmap(mOriginalBitmapLarge, sw, sh, true);
-        mZoomOrientation = mOrientation;
-        warnListeners();
-        return true;
-    }
-
-    public void setSupportsHighRes(boolean value) {
-        mSupportsHighRes = value;
-    }
-
-    public void addObserver(ImageShow observer) {
-        if (mObservers.contains(observer)) {
-            return;
-        }
-        mObservers.add(observer);
-    }
-
-    public void setActivity(FilterShowActivity activity) {
-        mActivity = activity;
-    }
-
-    public FilterShowActivity getActivity() {
-        return mActivity;
-    }
-
-    public synchronized ImagePreset getPreset() {
-        return mPreset;
-    }
-
-    public synchronized ImagePreset getGeometryPreset() {
-        return mGeometryOnlyPreset;
-    }
-
-    public synchronized ImagePreset getFiltersOnlyPreset() {
-        return mFiltersOnlyPreset;
-    }
-
-    public synchronized void setPreset(ImagePreset preset,
-                                       FilterRepresentation change,
-                                       boolean addToHistory) {
-        if (DEBUG) {
-            preset.showFilters();
-        }
-        mPreset = preset;
-        mPreset.fillImageStateAdapter(mState);
-        if (addToHistory) {
-            HistoryItem historyItem = new HistoryItem(mPreset, change);
-            mHistory.addHistoryItem(historyItem);
-        }
-        updatePresets(true);
-        mActivity.updateCategories();
-    }
-
-    public void onHistoryItemClick(int position) {
-        HistoryItem historyItem = mHistory.getItem(position);
-        // We need a copy from the history
-        ImagePreset newPreset = new ImagePreset(historyItem.getImagePreset());
-        // don't need to add it to the history
-        setPreset(newPreset, historyItem.getFilterRepresentation(), false);
-        mHistory.setCurrentPreset(position);
-    }
-
-    public HistoryManager getHistory() {
-        return mHistory;
-    }
-
-    public StateAdapter getState() {
-        return mState;
-    }
-
-    public void setHistoryManager(HistoryManager adapter) {
-        mHistory = adapter;
-    }
-
-    public void setStateAdapter(StateAdapter adapter) {
-        mState = adapter;
-    }
-
-    public void setCurrentFilter(ImageFilter filter) {
-        mCurrentFilter = filter;
-    }
-
-    public ImageFilter getCurrentFilter() {
-        return mCurrentFilter;
-    }
-
-    public synchronized boolean hasModifications() {
-        // TODO: We need to have a better same effects check to see if two
-        // presets are functionally the same. Right now, we are relying on a
-        // stricter check as equals().
-        ImagePreset loadedPreset = getLoadedPreset();
-        if (mPreset == null) {
-            if (loadedPreset == null) {
-                return false;
-            } else {
-                return loadedPreset.hasModifications();
-            }
-        } else {
-            if (loadedPreset == null) {
-                return mPreset.hasModifications();
-            } else {
-                return !mPreset.equals(loadedPreset);
-            }
-        }
-    }
-
-    public SharedBuffer getPreviewBuffer() {
-        return mPreviewBuffer;
-    }
-
-    public SharedPreset getPreviewPreset() {
-        return mPreviewPreset;
-    }
-
-    public Bitmap getFilteredImage() {
-        mPreviewBuffer.swapConsumerIfNeeded(); // get latest bitmap
-        Buffer consumer = mPreviewBuffer.getConsumer();
-        if (consumer != null) {
-            return consumer.getBitmap();
-        }
-        return null;
-    }
-
-    public Bitmap getFiltersOnlyImage() {
-        return mFiltersOnlyBitmap;
-    }
-
-    public Bitmap getGeometryOnlyImage() {
-        return mGeometryOnlyBitmap;
-    }
-
-    public Bitmap getPartialImage() {
-        return mPartialBitmap;
-    }
-
-    public Bitmap getHighresImage() {
-        return mHighresBitmap;
-    }
-
-    public void notifyObservers() {
-        for (ImageShow observer : mObservers) {
-            observer.invalidate();
-        }
-    }
-
-    public void updatePresets(boolean force) {
-        if (force || mGeometryOnlyPreset == null) {
-            ImagePreset newPreset = new ImagePreset(mPreset);
-            newPreset.setDoApplyFilters(false);
-            newPreset.setDoApplyGeometry(true);
-            if (force || mGeometryOnlyPreset == null
-                    || !newPreset.same(mGeometryOnlyPreset)) {
-                mGeometryOnlyPreset = newPreset;
-                RenderingRequest.post(mActivity, getOriginalBitmapLarge(),
-                        mGeometryOnlyPreset, RenderingRequest.GEOMETRY_RENDERING, this);
-            }
-        }
-        if (force || mFiltersOnlyPreset == null) {
-            ImagePreset newPreset = new ImagePreset(mPreset);
-            newPreset.setDoApplyFilters(true);
-            newPreset.setDoApplyGeometry(false);
-            if (force || mFiltersOnlyPreset == null
-                    || !newPreset.same(mFiltersOnlyPreset)) {
-                mFiltersOnlyPreset = newPreset;
-                RenderingRequest.post(mActivity, MasterImage.getImage().getOriginalBitmapLarge(),
-                        mFiltersOnlyPreset, RenderingRequest.FILTERS_RENDERING, this);
-            }
-        }
-        invalidatePreview();
-    }
-
-    public FilterRepresentation getCurrentFilterRepresentation() {
-        return mCurrentFilterRepresentation;
-    }
-
-    public void setCurrentFilterRepresentation(FilterRepresentation currentFilterRepresentation) {
-        mCurrentFilterRepresentation = currentFilterRepresentation;
-    }
-
-    public void invalidateFiltersOnly() {
-        mFiltersOnlyPreset = null;
-        updatePresets(false);
-    }
-
-    public void invalidatePartialPreview() {
-        if (mPartialBitmap != null) {
-            mPartialBitmap = null;
-            notifyObservers();
-        }
-    }
-
-    public void invalidateHighresPreview() {
-        if (mHighresBitmap != null) {
-            mHighresBitmap = null;
-            notifyObservers();
-        }
-    }
-
-    public void invalidatePreview() {
-        mPreviewPreset.enqueuePreset(mPreset);
-        mPreviewBuffer.invalidate();
-        invalidatePartialPreview();
-        invalidateHighresPreview();
-        needsUpdatePartialPreview();
-        needsUpdateHighResPreview();
-        mActivity.getProcessingService().updatePreviewBuffer();
-    }
-
-    public void setImageShowSize(int w, int h) {
-        if (mImageShowSize.x != w || mImageShowSize.y != h) {
-            mImageShowSize.set(w, h);
-            needsUpdatePartialPreview();
-            needsUpdateHighResPreview();
-        }
-    }
-
-    private Matrix getImageToScreenMatrix(boolean reflectRotation) {
-        if (getOriginalBounds() == null || mImageShowSize.x == 0 || mImageShowSize.y == 0) {
-            return new Matrix();
-        }
-        Matrix m = GeometryMathUtils.getImageToScreenMatrix(mPreset.getGeometryFilters(),
-                reflectRotation, getOriginalBounds(), mImageShowSize.x, mImageShowSize.y);
-        if (m == null) {
-            m = new Matrix();
-            m.reset();
-            return m;
-        }
-        Point translate = getTranslation();
-        float scaleFactor = getScaleFactor();
-        m.postTranslate(translate.x, translate.y);
-        m.postScale(scaleFactor, scaleFactor, mImageShowSize.x / 2.0f, mImageShowSize.y / 2.0f);
-        return m;
-    }
-
-    private Matrix getScreenToImageMatrix(boolean reflectRotation) {
-        Matrix m = getImageToScreenMatrix(reflectRotation);
-        Matrix invert = new Matrix();
-        m.invert(invert);
-        return invert;
-    }
-
-    public void needsUpdateHighResPreview() {
-        if (!mSupportsHighRes) {
-            return;
-        }
-        if (mActivity.getProcessingService() == null) {
-            return;
-        }
-        mActivity.getProcessingService().postHighresRenderingRequest(mPreset,
-                getScaleFactor(), this);
-        invalidateHighresPreview();
-    }
-
-    public void needsUpdatePartialPreview() {
-        if (mPreset == null) {
-            return;
-        }
-        if (!mPreset.canDoPartialRendering()) {
-            invalidatePartialPreview();
-            return;
-        }
-        Matrix m = getScreenToImageMatrix(true);
-        RectF r = new RectF(0, 0, mImageShowSize.x, mImageShowSize.y);
-        RectF dest = new RectF();
-        m.mapRect(dest, r);
-        Rect bounds = new Rect();
-        dest.roundOut(bounds);
-        RenderingRequest.post(mActivity, null, mPreset, RenderingRequest.PARTIAL_RENDERING,
-                this, bounds, new Rect(0, 0, mImageShowSize.x, mImageShowSize.y));
-        invalidatePartialPreview();
-    }
-
-    @Override
-    public void available(RenderingRequest request) {
-        if (request.getBitmap() == null) {
-            return;
-        }
-
-        boolean needsCheckModification = false;
-        if (request.getType() == RenderingRequest.GEOMETRY_RENDERING) {
-            mGeometryOnlyBitmap = request.getBitmap();
-            needsCheckModification = true;
-        }
-        if (request.getType() == RenderingRequest.FILTERS_RENDERING) {
-            mFiltersOnlyBitmap = request.getBitmap();
-            notifyObservers();
-            needsCheckModification = true;
-        }
-        if (request.getType() == RenderingRequest.PARTIAL_RENDERING
-                && request.getScaleFactor() == getScaleFactor()) {
-            mPartialBitmap = request.getBitmap();
-            notifyObservers();
-            needsCheckModification = true;
-        }
-        if (request.getType() == RenderingRequest.HIGHRES_RENDERING) {
-            mHighresBitmap = request.getBitmap();
-            notifyObservers();
-            needsCheckModification = true;
-        }
-        if (needsCheckModification) {
-            mActivity.enableSave(hasModifications());
-        }
-    }
-
-    public static void reset() {
-        sMasterImage = null;
-    }
-
-    public float getScaleFactor() {
-        return mScaleFactor;
-    }
-
-    public void setScaleFactor(float scaleFactor) {
-        if (DISABLEZOOM) {
-            return;
-        }
-        if (scaleFactor == mScaleFactor) {
-            return;
-        }
-        mScaleFactor = scaleFactor;
-        invalidatePartialPreview();
-    }
-
-    public Point getTranslation() {
-        return mTranslation;
-    }
-
-    public void setTranslation(Point translation) {
-        if (DISABLEZOOM) {
-            mTranslation.x = 0;
-            mTranslation.y = 0;
-            return;
-        }
-        mTranslation.x = translation.x;
-        mTranslation.y = translation.y;
-        needsUpdatePartialPreview();
-    }
-
-    public Point getOriginalTranslation() {
-        return mOriginalTranslation;
-    }
-
-    public void setOriginalTranslation(Point originalTranslation) {
-        if (DISABLEZOOM) {
-            return;
-        }
-        mOriginalTranslation.x = originalTranslation.x;
-        mOriginalTranslation.y = originalTranslation.y;
-    }
-
-    public void resetTranslation() {
-        mTranslation.x = 0;
-        mTranslation.y = 0;
-        needsUpdatePartialPreview();
-    }
-
-    public Bitmap getThumbnailBitmap() {
-        return getOriginalBitmapSmall();
-    }
-
-    public Bitmap getLargeThumbnailBitmap() {
-        return getOriginalBitmapLarge();
-    }
-
-    public float getMaxScaleFactor() {
-        if (DISABLEZOOM) {
-            return 1;
-        }
-        return mMaxScaleFactor;
-    }
-
-    public void setMaxScaleFactor(float maxScaleFactor) {
-        mMaxScaleFactor = maxScaleFactor;
-    }
-
-    public boolean supportsHighRes() {
-        return mSupportsHighRes;
-    }
-
-    public void setShowsOriginal(boolean value) {
-        mShowsOriginal = value;
-        notifyObservers();
-    }
-
-    public boolean showsOriginal() {
-        return mShowsOriginal;
-    }
-
-    public void setLoadedPreset(ImagePreset preset) {
-        mLoadedPreset = preset;
-    }
-
-    public ImagePreset getLoadedPreset() {
-        return mLoadedPreset;
-    }
-
-}
diff --git a/src/com/android/gallery3d/filtershow/imageshow/Oval.java b/src/com/android/gallery3d/filtershow/imageshow/Oval.java
deleted file mode 100644
index 28f278f..0000000
--- a/src/com/android/gallery3d/filtershow/imageshow/Oval.java
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * 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.gallery3d.filtershow.imageshow;
-
-public interface Oval {
-    void setCenter(float x, float y);
-    void setRadius(float w, float h);
-    float getCenterX();
-    float getCenterY();
-    float getRadiusX();
-    float getRadiusY();
-    void setRadiusY(float y);
-    void setRadiusX(float x);
-
-}
diff --git a/src/com/android/gallery3d/filtershow/imageshow/Spline.java b/src/com/android/gallery3d/filtershow/imageshow/Spline.java
deleted file mode 100644
index 3c27a4d..0000000
--- a/src/com/android/gallery3d/filtershow/imageshow/Spline.java
+++ /dev/null
@@ -1,450 +0,0 @@
-/*
- * 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.gallery3d.filtershow.imageshow;
-
-import android.graphics.Canvas;
-import android.graphics.Color;
-import android.graphics.Paint;
-import android.graphics.Path;
-import android.graphics.drawable.Drawable;
-import android.util.Log;
-
-import java.util.Collections;
-import java.util.Vector;
-
-public class Spline {
-    private final Vector<ControlPoint> mPoints;
-    private static Drawable mCurveHandle;
-    private static int mCurveHandleSize;
-    private static int mCurveWidth;
-
-    public static final int RGB = 0;
-    public static final int RED = 1;
-    public static final int GREEN = 2;
-    public static final int BLUE = 3;
-    private static final String LOGTAG = "Spline";
-
-    private final Paint gPaint = new Paint();
-    private ControlPoint mCurrentControlPoint = null;
-
-    public Spline() {
-        mPoints = new Vector<ControlPoint>();
-    }
-
-    public Spline(Spline spline) {
-        mPoints = new Vector<ControlPoint>();
-        for (int i = 0; i < spline.mPoints.size(); i++) {
-            ControlPoint p = spline.mPoints.elementAt(i);
-            ControlPoint newPoint = new ControlPoint(p);
-            mPoints.add(newPoint);
-            if (spline.mCurrentControlPoint == p) {
-                mCurrentControlPoint = newPoint;
-            }
-        }
-        Collections.sort(mPoints);
-    }
-
-    public static void setCurveHandle(Drawable drawable, int size) {
-        mCurveHandle = drawable;
-        mCurveHandleSize = size;
-    }
-
-    public static void setCurveWidth(int width) {
-        mCurveWidth = width;
-    }
-
-    public static int curveHandleSize() {
-        return mCurveHandleSize;
-    }
-
-    public static int colorForCurve(int curveIndex) {
-        switch (curveIndex) {
-            case Spline.RED:
-                return Color.RED;
-            case GREEN:
-                return Color.GREEN;
-            case BLUE:
-                return Color.BLUE;
-        }
-        return Color.WHITE;
-    }
-
-    public boolean sameValues(Spline other) {
-        if (this == other) {
-            return true;
-        }
-        if (other == null) {
-            return false;
-        }
-
-        if (getNbPoints() != other.getNbPoints()) {
-            return false;
-        }
-
-        for (int i = 0; i < getNbPoints(); i++) {
-            ControlPoint p = mPoints.elementAt(i);
-            ControlPoint otherPoint = other.mPoints.elementAt(i);
-            if (!p.sameValues(otherPoint)) {
-                return false;
-            }
-        }
-        return true;
-    }
-
-    private void didMovePoint(ControlPoint point) {
-        mCurrentControlPoint = point;
-    }
-
-    public void movePoint(int pick, float x, float y) {
-        if (pick < 0 || pick > mPoints.size() - 1) {
-            return;
-        }
-        ControlPoint point = mPoints.elementAt(pick);
-        point.x = x;
-        point.y = y;
-        didMovePoint(point);
-    }
-
-    public boolean isOriginal() {
-        if (this.getNbPoints() != 2) {
-            return false;
-        }
-        if (mPoints.elementAt(0).x != 0 || mPoints.elementAt(0).y != 1) {
-            return false;
-        }
-        if (mPoints.elementAt(1).x != 1 || mPoints.elementAt(1).y != 0) {
-            return false;
-        }
-        return true;
-    }
-
-    public void reset() {
-        mPoints.clear();
-        addPoint(0.0f, 1.0f);
-        addPoint(1.0f, 0.0f);
-    }
-
-    private void drawHandles(Canvas canvas, Drawable indicator, float centerX, float centerY) {
-        int left = (int) centerX - mCurveHandleSize / 2;
-        int top = (int) centerY - mCurveHandleSize / 2;
-        indicator.setBounds(left, top, left + mCurveHandleSize, top + mCurveHandleSize);
-        indicator.draw(canvas);
-    }
-
-    public float[] getAppliedCurve() {
-        float[] curve = new float[256];
-        ControlPoint[] points = new ControlPoint[mPoints.size()];
-        for (int i = 0; i < mPoints.size(); i++) {
-            ControlPoint p = mPoints.get(i);
-            points[i] = new ControlPoint(p.x, p.y);
-        }
-        double[] derivatives = solveSystem(points);
-        int start = 0;
-        int end = 256;
-        if (points[0].x != 0) {
-            start = (int) (points[0].x * 256);
-        }
-        if (points[points.length - 1].x != 1) {
-            end = (int) (points[points.length - 1].x * 256);
-        }
-        for (int i = 0; i < start; i++) {
-            curve[i] = 1.0f - points[0].y;
-        }
-        for (int i = end; i < 256; i++) {
-            curve[i] = 1.0f - points[points.length - 1].y;
-        }
-        for (int i = start; i < end; i++) {
-            ControlPoint cur = null;
-            ControlPoint next = null;
-            double x = i / 256.0;
-            int pivot = 0;
-            for (int j = 0; j < points.length - 1; j++) {
-                if (x >= points[j].x && x <= points[j + 1].x) {
-                    pivot = j;
-                }
-            }
-            cur = points[pivot];
-            next = points[pivot + 1];
-            if (x <= next.x) {
-                double x1 = cur.x;
-                double x2 = next.x;
-                double y1 = cur.y;
-                double y2 = next.y;
-
-                // Use the second derivatives to apply the cubic spline
-                // equation:
-                double delta = (x2 - x1);
-                double delta2 = delta * delta;
-                double b = (x - x1) / delta;
-                double a = 1 - b;
-                double ta = a * y1;
-                double tb = b * y2;
-                double tc = (a * a * a - a) * derivatives[pivot];
-                double td = (b * b * b - b) * derivatives[pivot + 1];
-                double y = ta + tb + (delta2 / 6) * (tc + td);
-                if (y > 1.0f) {
-                    y = 1.0f;
-                }
-                if (y < 0) {
-                    y = 0;
-                }
-                curve[i] = (float) (1.0f - y);
-            } else {
-                curve[i] = 1.0f - next.y;
-            }
-        }
-        return curve;
-    }
-
-    private void drawGrid(Canvas canvas, float w, float h) {
-        // Grid
-        gPaint.setARGB(128, 150, 150, 150);
-        gPaint.setStrokeWidth(1);
-
-        float stepH = h / 9;
-        float stepW = w / 9;
-
-        // central diagonal
-        gPaint.setARGB(255, 100, 100, 100);
-        gPaint.setStrokeWidth(2);
-        canvas.drawLine(0, h, w, 0, gPaint);
-
-        gPaint.setARGB(128, 200, 200, 200);
-        gPaint.setStrokeWidth(4);
-        stepH = h / 3;
-        stepW = w / 3;
-        for (int j = 1; j < 3; j++) {
-            canvas.drawLine(0, j * stepH, w, j * stepH, gPaint);
-            canvas.drawLine(j * stepW, 0, j * stepW, h, gPaint);
-        }
-        canvas.drawLine(0, 0, 0, h, gPaint);
-        canvas.drawLine(w, 0, w, h, gPaint);
-        canvas.drawLine(0, 0, w, 0, gPaint);
-        canvas.drawLine(0, h, w, h, gPaint);
-    }
-
-    public void draw(Canvas canvas, int color, int canvasWidth, int canvasHeight,
-            boolean showHandles, boolean moving) {
-        float w = canvasWidth - mCurveHandleSize;
-        float h = canvasHeight - mCurveHandleSize;
-        float dx = mCurveHandleSize / 2;
-        float dy = mCurveHandleSize / 2;
-
-        // The cubic spline equation is (from numerical recipes in C):
-        // y = a(y_i) + b(y_i+1) + c(y"_i) + d(y"_i+1)
-        //
-        // with c(y"_i) and d(y"_i+1):
-        // c(y"_i) = 1/6 (a^3 - a) delta^2 (y"_i)
-        // d(y"_i_+1) = 1/6 (b^3 - b) delta^2 (y"_i+1)
-        //
-        // and delta:
-        // delta = x_i+1 - x_i
-        //
-        // To find the second derivatives y", we can rearrange the equation as:
-        // A(y"_i-1) + B(y"_i) + C(y"_i+1) = D
-        //
-        // With the coefficients A, B, C, D:
-        // A = 1/6 (x_i - x_i-1)
-        // B = 1/3 (x_i+1 - x_i-1)
-        // C = 1/6 (x_i+1 - x_i)
-        // D = (y_i+1 - y_i)/(x_i+1 - x_i) - (y_i - y_i-1)/(x_i - x_i-1)
-        //
-        // We can now easily solve the equation to find the second derivatives:
-        ControlPoint[] points = new ControlPoint[mPoints.size()];
-        for (int i = 0; i < mPoints.size(); i++) {
-            ControlPoint p = mPoints.get(i);
-            points[i] = new ControlPoint(p.x * w, p.y * h);
-        }
-        double[] derivatives = solveSystem(points);
-
-        Path path = new Path();
-        path.moveTo(0, points[0].y);
-        for (int i = 0; i < points.length - 1; i++) {
-            double x1 = points[i].x;
-            double x2 = points[i + 1].x;
-            double y1 = points[i].y;
-            double y2 = points[i + 1].y;
-
-            for (double x = x1; x < x2; x += 20) {
-                // Use the second derivatives to apply the cubic spline
-                // equation:
-                double delta = (x2 - x1);
-                double delta2 = delta * delta;
-                double b = (x - x1) / delta;
-                double a = 1 - b;
-                double ta = a * y1;
-                double tb = b * y2;
-                double tc = (a * a * a - a) * derivatives[i];
-                double td = (b * b * b - b) * derivatives[i + 1];
-                double y = ta + tb + (delta2 / 6) * (tc + td);
-                if (y > h) {
-                    y = h;
-                }
-                if (y < 0) {
-                    y = 0;
-                }
-                path.lineTo((float) x, (float) y);
-            }
-        }
-        canvas.save();
-        canvas.translate(dx, dy);
-        drawGrid(canvas, w, h);
-        ControlPoint lastPoint = points[points.length - 1];
-        path.lineTo(lastPoint.x, lastPoint.y);
-        path.lineTo(w, lastPoint.y);
-        Paint paint = new Paint();
-        paint.setAntiAlias(true);
-        paint.setFilterBitmap(true);
-        paint.setDither(true);
-        paint.setStyle(Paint.Style.STROKE);
-        int curveWidth = mCurveWidth;
-        if (showHandles) {
-            curveWidth *= 1.5;
-        }
-        paint.setStrokeWidth(curveWidth + 2);
-        paint.setColor(Color.BLACK);
-        canvas.drawPath(path, paint);
-
-        if (moving && mCurrentControlPoint != null) {
-            float px = mCurrentControlPoint.x * w;
-            float py = mCurrentControlPoint.y * h;
-            paint.setStrokeWidth(3);
-            paint.setColor(Color.BLACK);
-            canvas.drawLine(px, py, px, h, paint);
-            canvas.drawLine(0, py, px, py, paint);
-            paint.setStrokeWidth(1);
-            paint.setColor(color);
-            canvas.drawLine(px, py, px, h, paint);
-            canvas.drawLine(0, py, px, py, paint);
-        }
-
-        paint.setStrokeWidth(curveWidth);
-        paint.setColor(color);
-        canvas.drawPath(path, paint);
-        if (showHandles) {
-            for (int i = 0; i < points.length; i++) {
-                float x = points[i].x;
-                float y = points[i].y;
-                drawHandles(canvas, mCurveHandle, x, y);
-            }
-        }
-        canvas.restore();
-    }
-
-    double[] solveSystem(ControlPoint[] points) {
-        int n = points.length;
-        double[][] system = new double[n][3];
-        double[] result = new double[n]; // d
-        double[] solution = new double[n]; // returned coefficients
-        system[0][1] = 1;
-        system[n - 1][1] = 1;
-        double d6 = 1.0 / 6.0;
-        double d3 = 1.0 / 3.0;
-
-        // let's create a tridiagonal matrix representing the
-        // system, and apply the TDMA algorithm to solve it
-        // (see http://en.wikipedia.org/wiki/Tridiagonal_matrix_algorithm)
-        for (int i = 1; i < n - 1; i++) {
-            double deltaPrevX = points[i].x - points[i - 1].x;
-            double deltaX = points[i + 1].x - points[i - 1].x;
-            double deltaNextX = points[i + 1].x - points[i].x;
-            double deltaNextY = points[i + 1].y - points[i].y;
-            double deltaPrevY = points[i].y - points[i - 1].y;
-            system[i][0] = d6 * deltaPrevX; // a_i
-            system[i][1] = d3 * deltaX; // b_i
-            system[i][2] = d6 * deltaNextX; // c_i
-            result[i] = (deltaNextY / deltaNextX) - (deltaPrevY / deltaPrevX); // d_i
-        }
-
-        // Forward sweep
-        for (int i = 1; i < n; i++) {
-            // m = a_i/b_i-1
-            double m = system[i][0] / system[i - 1][1];
-            // b_i = b_i - m(c_i-1)
-            system[i][1] = system[i][1] - m * system[i - 1][2];
-            // d_i = d_i - m(d_i-1)
-            result[i] = result[i] - m * result[i - 1];
-        }
-
-        // Back substitution
-        solution[n - 1] = result[n - 1] / system[n - 1][1];
-        for (int i = n - 2; i >= 0; --i) {
-            solution[i] = (result[i] - system[i][2] * solution[i + 1]) / system[i][1];
-        }
-        return solution;
-    }
-
-    public int addPoint(float x, float y) {
-        return addPoint(new ControlPoint(x, y));
-    }
-
-    public int addPoint(ControlPoint v) {
-        mPoints.add(v);
-        Collections.sort(mPoints);
-        return mPoints.indexOf(v);
-    }
-
-    public void deletePoint(int n) {
-        mPoints.remove(n);
-        if (mPoints.size() < 2) {
-            reset();
-        }
-        Collections.sort(mPoints);
-    }
-
-    public int getNbPoints() {
-        return mPoints.size();
-    }
-
-    public ControlPoint getPoint(int n) {
-        return mPoints.elementAt(n);
-    }
-
-    public boolean isPointContained(float x, int n) {
-        for (int i = 0; i < n; i++) {
-            ControlPoint point = mPoints.elementAt(i);
-            if (point.x > x) {
-                return false;
-            }
-        }
-        for (int i = n + 1; i < mPoints.size(); i++) {
-            ControlPoint point = mPoints.elementAt(i);
-            if (point.x < x) {
-                return false;
-            }
-        }
-        return true;
-    }
-
-    public Spline copy() {
-        Spline spline = new Spline();
-        for (int i = 0; i < mPoints.size(); i++) {
-            ControlPoint point = mPoints.elementAt(i);
-            spline.addPoint(point.copy());
-        }
-        return spline;
-    }
-
-    public void show() {
-        Log.v(LOGTAG, "show curve " + this);
-        for (int i = 0; i < mPoints.size(); i++) {
-            ControlPoint point = mPoints.elementAt(i);
-            Log.v(LOGTAG, "point " + i + " is (" + point.x + ", " + point.y + ")");
-        }
-    }
-
-}
diff --git a/src/com/android/gallery3d/filtershow/pipeline/Buffer.java b/src/com/android/gallery3d/filtershow/pipeline/Buffer.java
deleted file mode 100644
index 7444512..0000000
--- a/src/com/android/gallery3d/filtershow/pipeline/Buffer.java
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * Copyright (C) 2013 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.gallery3d.filtershow.pipeline;
-
-import android.graphics.Bitmap;
-import android.support.v8.renderscript.Allocation;
-import android.support.v8.renderscript.RenderScript;
-
-public class Buffer {
-    private static final String LOGTAG = "Buffer";
-    private Bitmap mBitmap;
-    private Allocation mAllocation;
-    private boolean mUseAllocation = false;
-    private static final Bitmap.Config BITMAP_CONFIG = Bitmap.Config.ARGB_8888;
-    private ImagePreset mPreset;
-
-    public Buffer(Bitmap bitmap) {
-        RenderScript rs = CachingPipeline.getRenderScriptContext();
-        if (bitmap != null) {
-            mBitmap = bitmap.copy(BITMAP_CONFIG, true);
-        }
-        if (mUseAllocation) {
-            // TODO: recreate the allocation when the RS context changes
-            mAllocation = Allocation.createFromBitmap(rs, mBitmap,
-                    Allocation.MipmapControl.MIPMAP_NONE,
-                    Allocation.USAGE_SHARED | Allocation.USAGE_SCRIPT);
-        }
-    }
-
-    public void setBitmap(Bitmap bitmap) {
-        mBitmap = bitmap.copy(BITMAP_CONFIG, true);
-    }
-
-    public Bitmap getBitmap() {
-        return mBitmap;
-    }
-
-    public Allocation getAllocation() {
-        return mAllocation;
-    }
-
-    public void sync() {
-        if (mUseAllocation) {
-            mAllocation.copyTo(mBitmap);
-        }
-    }
-
-    public ImagePreset getPreset() {
-        return mPreset;
-    }
-
-    public void setPreset(ImagePreset preset) {
-        if ((mPreset == null) || (!mPreset.same(preset))) {
-            mPreset = new ImagePreset(preset);
-        } else {
-            mPreset.updateWith(preset);
-        }
-    }
-}
-
diff --git a/src/com/android/gallery3d/filtershow/pipeline/CacheProcessing.java b/src/com/android/gallery3d/filtershow/pipeline/CacheProcessing.java
deleted file mode 100644
index e0269e9..0000000
--- a/src/com/android/gallery3d/filtershow/pipeline/CacheProcessing.java
+++ /dev/null
@@ -1,193 +0,0 @@
-/*
- * Copyright (C) 2013 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.gallery3d.filtershow.pipeline;
-
-import android.graphics.Bitmap;
-import android.util.Log;
-import com.android.gallery3d.filtershow.filters.FilterRepresentation;
-
-import java.util.Vector;
-
-public class CacheProcessing {
-    private static final String LOGTAG = "CacheProcessing";
-    private static final boolean DEBUG = false;
-    private Vector<CacheStep> mSteps = new Vector<CacheStep>();
-
-    static class CacheStep {
-        FilterRepresentation representation;
-        Bitmap cache;
-    }
-
-    public Bitmap process(Bitmap originalBitmap,
-                          Vector<FilterRepresentation> filters,
-                          FilterEnvironment environment) {
-
-        if (filters.size() == 0) {
-            return originalBitmap;
-        }
-
-        // New set of filters, let's clear the cache and rebuild it.
-        if (filters.size() != mSteps.size()) {
-            mSteps.clear();
-            for (int i = 0; i < filters.size(); i++) {
-                FilterRepresentation representation = filters.elementAt(i);
-                CacheStep step = new CacheStep();
-                step.representation = representation.copy();
-                mSteps.add(step);
-            }
-        }
-
-        if (DEBUG) {
-            displayFilters(filters);
-        }
-
-        // First, let's find how similar we are in our cache
-        // compared to the current list of filters
-        int similarUpToIndex = -1;
-        for (int i = 0; i < filters.size(); i++) {
-            FilterRepresentation representation = filters.elementAt(i);
-            CacheStep step = mSteps.elementAt(i);
-            boolean similar = step.representation.equals(representation);
-            if (similar) {
-                similarUpToIndex = i;
-            } else {
-                break;
-            }
-        }
-        if (DEBUG) {
-            Log.v(LOGTAG, "similar up to index " + similarUpToIndex);
-        }
-
-        // Now, let's get the earliest cached result in our pipeline
-        Bitmap cacheBitmap = null;
-        int findBaseImageIndex = similarUpToIndex;
-        if (findBaseImageIndex > -1) {
-            while (findBaseImageIndex > 0
-                    && mSteps.elementAt(findBaseImageIndex).cache == null) {
-                findBaseImageIndex--;
-            }
-            cacheBitmap = mSteps.elementAt(findBaseImageIndex).cache;
-        }
-        boolean emptyStack = false;
-        if (cacheBitmap == null) {
-            emptyStack = true;
-            // Damn, it's an empty stack, we have to start from scratch
-            // TODO: use a bitmap cache + RS allocation instead of Bitmap.copy()
-            cacheBitmap = originalBitmap.copy(Bitmap.Config.ARGB_8888, true);
-            if (findBaseImageIndex > -1) {
-                FilterRepresentation representation = filters.elementAt(findBaseImageIndex);
-                if (representation.getFilterType() != FilterRepresentation.TYPE_GEOMETRY) {
-                    cacheBitmap = environment.applyRepresentation(representation, cacheBitmap);
-                }
-                mSteps.elementAt(findBaseImageIndex).representation = representation.copy();
-                mSteps.elementAt(findBaseImageIndex).cache = cacheBitmap;
-            }
-            if (DEBUG) {
-                Log.v(LOGTAG, "empty stack");
-            }
-        }
-
-        // Ok, so sadly the earliest cached result is before the index we want.
-        // We have to rebuild a new result for this position, and then cache it.
-        if (findBaseImageIndex != similarUpToIndex) {
-            if (DEBUG) {
-                Log.v(LOGTAG, "rebuild cacheBitmap from " + findBaseImageIndex
-                        + " to " + similarUpToIndex);
-            }
-            // rebuild the cache image for this step
-            if (!emptyStack) {
-                cacheBitmap = cacheBitmap.copy(Bitmap.Config.ARGB_8888, true);
-            } else {
-                // if it was an empty stack, we already applied it
-                findBaseImageIndex ++;
-            }
-            for (int i = findBaseImageIndex; i <= similarUpToIndex; i++) {
-                FilterRepresentation representation = filters.elementAt(i);
-                if (representation.getFilterType() != FilterRepresentation.TYPE_GEOMETRY) {
-                    cacheBitmap = environment.applyRepresentation(representation, cacheBitmap);
-                }
-                if (DEBUG) {
-                    Log.v(LOGTAG, " - " + i  + " => apply " + representation.getName());
-                }
-            }
-            // Let's cache it!
-            mSteps.elementAt(similarUpToIndex).cache = cacheBitmap;
-        }
-
-        if (DEBUG) {
-            Log.v(LOGTAG, "process pipeline from " + similarUpToIndex
-                    + " to " + (filters.size() - 1));
-        }
-
-        // Now we are good to go, let's use the cacheBitmap as a starting point
-        for (int i = similarUpToIndex + 1; i < filters.size(); i++) {
-            FilterRepresentation representation = filters.elementAt(i);
-            CacheStep currentStep = mSteps.elementAt(i);
-            cacheBitmap = cacheBitmap.copy(Bitmap.Config.ARGB_8888, true);
-            if (representation.getFilterType() != FilterRepresentation.TYPE_GEOMETRY) {
-                cacheBitmap = environment.applyRepresentation(representation, cacheBitmap);
-            }
-            currentStep.representation = representation.copy();
-            currentStep.cache = cacheBitmap;
-            if (DEBUG) {
-                Log.v(LOGTAG, " - " + i  + " => apply " + representation.getName());
-            }
-        }
-
-        if (DEBUG) {
-            Log.v(LOGTAG, "now let's cleanup the cache...");
-            displayNbBitmapsInCache();
-        }
-
-        // Let's see if we can cleanup the cache for unused bitmaps
-        for (int i = 0; i < similarUpToIndex; i++) {
-            CacheStep currentStep = mSteps.elementAt(i);
-            currentStep.cache = null;
-        }
-
-        if (DEBUG) {
-            Log.v(LOGTAG, "cleanup done...");
-            displayNbBitmapsInCache();
-        }
-        return cacheBitmap;
-    }
-
-    private void displayFilters(Vector<FilterRepresentation> filters) {
-        Log.v(LOGTAG, "------>>>");
-        for (int i = 0; i < filters.size(); i++) {
-            FilterRepresentation representation = filters.elementAt(i);
-            CacheStep step = mSteps.elementAt(i);
-            boolean similar = step.representation.equals(representation);
-            Log.v(LOGTAG, "[" + i + "] - " + representation.getName()
-                    + " similar rep ? " + (similar ? "YES" : "NO")
-                    + " -- bitmap: " + step.cache);
-        }
-        Log.v(LOGTAG, "<<<------");
-    }
-
-    private void displayNbBitmapsInCache() {
-        int nbBitmapsCached = 0;
-        for (int i = 0; i < mSteps.size(); i++) {
-            CacheStep step = mSteps.elementAt(i);
-            if (step.cache != null) {
-                nbBitmapsCached++;
-            }
-        }
-        Log.v(LOGTAG, "nb bitmaps in cache: " + nbBitmapsCached + " / " + mSteps.size());
-    }
-
-}
diff --git a/src/com/android/gallery3d/filtershow/pipeline/CachingPipeline.java b/src/com/android/gallery3d/filtershow/pipeline/CachingPipeline.java
deleted file mode 100644
index fc0d6ce..0000000
--- a/src/com/android/gallery3d/filtershow/pipeline/CachingPipeline.java
+++ /dev/null
@@ -1,469 +0,0 @@
-/*
- * Copyright (C) 2013 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.gallery3d.filtershow.pipeline;
-
-import android.content.Context;
-import android.content.res.Resources;
-import android.graphics.Bitmap;
-import android.support.v8.renderscript.Allocation;
-import android.support.v8.renderscript.RenderScript;
-import android.util.Log;
-
-import com.android.gallery3d.filtershow.cache.ImageLoader;
-import com.android.gallery3d.filtershow.filters.FilterRepresentation;
-import com.android.gallery3d.filtershow.filters.FiltersManager;
-import com.android.gallery3d.filtershow.imageshow.GeometryMathUtils;
-import com.android.gallery3d.filtershow.imageshow.MasterImage;
-
-import java.util.Vector;
-
-public class CachingPipeline implements PipelineInterface {
-    private static final String LOGTAG = "CachingPipeline";
-    private boolean DEBUG = false;
-
-    private static final Bitmap.Config BITMAP_CONFIG = Bitmap.Config.ARGB_8888;
-
-    private static volatile RenderScript sRS = null;
-
-    private FiltersManager mFiltersManager = null;
-    private volatile Bitmap mOriginalBitmap = null;
-    private volatile Bitmap mResizedOriginalBitmap = null;
-
-    private FilterEnvironment mEnvironment = new FilterEnvironment();
-    private CacheProcessing mCachedProcessing = new CacheProcessing();
-
-
-    private volatile Allocation mOriginalAllocation = null;
-    private volatile Allocation mFiltersOnlyOriginalAllocation =  null;
-
-    protected volatile Allocation mInPixelsAllocation;
-    protected volatile Allocation mOutPixelsAllocation;
-    private volatile int mWidth = 0;
-    private volatile int mHeight = 0;
-
-    private volatile float mPreviewScaleFactor = 1.0f;
-    private volatile float mHighResPreviewScaleFactor = 1.0f;
-    private volatile String mName = "";
-
-    public CachingPipeline(FiltersManager filtersManager, String name) {
-        mFiltersManager = filtersManager;
-        mName = name;
-    }
-
-    public static synchronized RenderScript getRenderScriptContext() {
-        return sRS;
-    }
-
-    public static synchronized void createRenderscriptContext(Context context) {
-        if (sRS != null) {
-            Log.w(LOGTAG, "A prior RS context exists when calling setRenderScriptContext");
-            destroyRenderScriptContext();
-        }
-        sRS = RenderScript.create(context);
-    }
-
-    public static synchronized void destroyRenderScriptContext() {
-        if (sRS != null) {
-            sRS.destroy();
-        }
-        sRS = null;
-    }
-
-    public void stop() {
-        mEnvironment.setStop(true);
-    }
-
-    public synchronized void reset() {
-        synchronized (CachingPipeline.class) {
-            if (getRenderScriptContext() == null) {
-                return;
-            }
-            mOriginalBitmap = null; // just a reference to the bitmap in ImageLoader
-            if (mResizedOriginalBitmap != null) {
-                mResizedOriginalBitmap.recycle();
-                mResizedOriginalBitmap = null;
-            }
-            if (mOriginalAllocation != null) {
-                mOriginalAllocation.destroy();
-                mOriginalAllocation = null;
-            }
-            if (mFiltersOnlyOriginalAllocation != null) {
-                mFiltersOnlyOriginalAllocation.destroy();
-                mFiltersOnlyOriginalAllocation = null;
-            }
-            mPreviewScaleFactor = 1.0f;
-            mHighResPreviewScaleFactor = 1.0f;
-
-            destroyPixelAllocations();
-        }
-    }
-
-    public Resources getResources() {
-        return sRS.getApplicationContext().getResources();
-    }
-
-    private synchronized void destroyPixelAllocations() {
-        if (DEBUG) {
-            Log.v(LOGTAG, "destroyPixelAllocations in " + getName());
-        }
-        if (mInPixelsAllocation != null) {
-            mInPixelsAllocation.destroy();
-            mInPixelsAllocation = null;
-        }
-        if (mOutPixelsAllocation != null) {
-            mOutPixelsAllocation.destroy();
-            mOutPixelsAllocation = null;
-        }
-        mWidth = 0;
-        mHeight = 0;
-    }
-
-    private String getType(RenderingRequest request) {
-        if (request.getType() == RenderingRequest.ICON_RENDERING) {
-            return "ICON_RENDERING";
-        }
-        if (request.getType() == RenderingRequest.FILTERS_RENDERING) {
-            return "FILTERS_RENDERING";
-        }
-        if (request.getType() == RenderingRequest.FULL_RENDERING) {
-            return "FULL_RENDERING";
-        }
-        if (request.getType() == RenderingRequest.GEOMETRY_RENDERING) {
-            return "GEOMETRY_RENDERING";
-        }
-        if (request.getType() == RenderingRequest.PARTIAL_RENDERING) {
-            return "PARTIAL_RENDERING";
-        }
-        if (request.getType() == RenderingRequest.HIGHRES_RENDERING) {
-            return "HIGHRES_RENDERING";
-        }
-        return "UNKNOWN TYPE!";
-    }
-
-    private void setupEnvironment(ImagePreset preset, boolean highResPreview) {
-        mEnvironment.setPipeline(this);
-        mEnvironment.setFiltersManager(mFiltersManager);
-        if (highResPreview) {
-            mEnvironment.setScaleFactor(mHighResPreviewScaleFactor);
-        } else {
-            mEnvironment.setScaleFactor(mPreviewScaleFactor);
-        }
-        mEnvironment.setQuality(FilterEnvironment.QUALITY_PREVIEW);
-        mEnvironment.setImagePreset(preset);
-        mEnvironment.setStop(false);
-    }
-
-    public void setOriginal(Bitmap bitmap) {
-        mOriginalBitmap = bitmap;
-        Log.v(LOGTAG,"setOriginal, size " + bitmap.getWidth() + " x " + bitmap.getHeight());
-        ImagePreset preset = MasterImage.getImage().getPreset();
-        setupEnvironment(preset, false);
-        updateOriginalAllocation(preset);
-    }
-
-    private synchronized boolean updateOriginalAllocation(ImagePreset preset) {
-        Bitmap originalBitmap = mOriginalBitmap;
-
-        if (originalBitmap == null) {
-            return false;
-        }
-
-        RenderScript RS = getRenderScriptContext();
-
-        Allocation filtersOnlyOriginalAllocation = mFiltersOnlyOriginalAllocation;
-        mFiltersOnlyOriginalAllocation = Allocation.createFromBitmap(RS, originalBitmap,
-                Allocation.MipmapControl.MIPMAP_NONE, Allocation.USAGE_SCRIPT);
-        if (filtersOnlyOriginalAllocation != null) {
-            filtersOnlyOriginalAllocation.destroy();
-        }
-
-        Allocation originalAllocation = mOriginalAllocation;
-        mResizedOriginalBitmap = preset.applyGeometry(originalBitmap, mEnvironment);
-        mOriginalAllocation = Allocation.createFromBitmap(RS, mResizedOriginalBitmap,
-                Allocation.MipmapControl.MIPMAP_NONE, Allocation.USAGE_SCRIPT);
-        if (originalAllocation != null) {
-            originalAllocation.destroy();
-        }
-
-        return true;
-    }
-
-    public void renderHighres(RenderingRequest request) {
-        synchronized (CachingPipeline.class) {
-            if (getRenderScriptContext() == null) {
-                return;
-            }
-            ImagePreset preset = request.getImagePreset();
-            setupEnvironment(preset, false);
-            Bitmap bitmap = MasterImage.getImage().getOriginalBitmapHighres();
-            if (bitmap == null) {
-                return;
-            }
-            // TODO: use a cache of bitmaps
-            bitmap = bitmap.copy(Bitmap.Config.ARGB_8888, true);
-            bitmap = preset.applyGeometry(bitmap, mEnvironment);
-
-            mEnvironment.setQuality(FilterEnvironment.QUALITY_PREVIEW);
-            Bitmap bmp = preset.apply(bitmap, mEnvironment);
-            if (!mEnvironment.needsStop()) {
-                request.setBitmap(bmp);
-            }
-            mFiltersManager.freeFilterResources(preset);
-        }
-    }
-
-    public synchronized void render(RenderingRequest request) {
-        synchronized (CachingPipeline.class) {
-            if (getRenderScriptContext() == null) {
-                return;
-            }
-            if (((request.getType() != RenderingRequest.PARTIAL_RENDERING
-                    && request.getType() != RenderingRequest.HIGHRES_RENDERING)
-                    && request.getBitmap() == null)
-                    || request.getImagePreset() == null) {
-                return;
-            }
-
-            if (DEBUG) {
-                Log.v(LOGTAG, "render image of type " + getType(request));
-            }
-
-            Bitmap bitmap = request.getBitmap();
-            ImagePreset preset = request.getImagePreset();
-            setupEnvironment(preset,
-                    request.getType() != RenderingRequest.HIGHRES_RENDERING);
-            mFiltersManager.freeFilterResources(preset);
-
-            if (request.getType() == RenderingRequest.PARTIAL_RENDERING) {
-                MasterImage master = MasterImage.getImage();
-                bitmap = ImageLoader.getScaleOneImageForPreset(master.getActivity(),
-                        master.getUri(), request.getBounds(),
-                        request.getDestination());
-                if (bitmap == null) {
-                    Log.w(LOGTAG, "could not get bitmap for: " + getType(request));
-                    return;
-                }
-            }
-
-            if (request.getType() == RenderingRequest.HIGHRES_RENDERING) {
-                bitmap = MasterImage.getImage().getOriginalBitmapHighres();
-                if (bitmap != null) {
-                    bitmap = preset.applyGeometry(bitmap, mEnvironment);
-                }
-            }
-
-            if (request.getType() == RenderingRequest.FULL_RENDERING
-                    || request.getType() == RenderingRequest.GEOMETRY_RENDERING
-                    || request.getType() == RenderingRequest.FILTERS_RENDERING) {
-                updateOriginalAllocation(preset);
-            }
-
-            if (DEBUG) {
-                Log.v(LOGTAG, "after update, req bitmap (" + bitmap.getWidth() + "x" + bitmap.getHeight()
-                        + " ? resizeOriginal (" + mResizedOriginalBitmap.getWidth() + "x"
-                        + mResizedOriginalBitmap.getHeight());
-            }
-
-            if (request.getType() == RenderingRequest.FULL_RENDERING
-                    || request.getType() == RenderingRequest.GEOMETRY_RENDERING) {
-                mOriginalAllocation.copyTo(bitmap);
-            } else if (request.getType() == RenderingRequest.FILTERS_RENDERING) {
-                mFiltersOnlyOriginalAllocation.copyTo(bitmap);
-            }
-
-            if (request.getType() == RenderingRequest.FULL_RENDERING
-                    || request.getType() == RenderingRequest.FILTERS_RENDERING
-                    || request.getType() == RenderingRequest.ICON_RENDERING
-                    || request.getType() == RenderingRequest.PARTIAL_RENDERING
-                    || request.getType() == RenderingRequest.HIGHRES_RENDERING
-                    || request.getType() == RenderingRequest.STYLE_ICON_RENDERING) {
-
-                if (request.getType() == RenderingRequest.ICON_RENDERING) {
-                    mEnvironment.setQuality(FilterEnvironment.QUALITY_ICON);
-                } else {
-                    mEnvironment.setQuality(FilterEnvironment.QUALITY_PREVIEW);
-                }
-
-                Bitmap bmp = preset.apply(bitmap, mEnvironment);
-                if (!mEnvironment.needsStop()) {
-                    request.setBitmap(bmp);
-                }
-                mFiltersManager.freeFilterResources(preset);
-            }
-        }
-    }
-
-    public synchronized void renderImage(ImagePreset preset, Allocation in, Allocation out) {
-        synchronized (CachingPipeline.class) {
-            if (getRenderScriptContext() == null) {
-                return;
-            }
-            setupEnvironment(preset, false);
-            mFiltersManager.freeFilterResources(preset);
-            preset.applyFilters(-1, -1, in, out, mEnvironment);
-            boolean copyOut = false;
-            if (preset.nbFilters() > 0) {
-                copyOut = true;
-            }
-            preset.applyBorder(in, out, copyOut, mEnvironment);
-        }
-    }
-
-    public synchronized Bitmap renderFinalImage(Bitmap bitmap, ImagePreset preset) {
-        synchronized (CachingPipeline.class) {
-            if (getRenderScriptContext() == null) {
-                return bitmap;
-            }
-            setupEnvironment(preset, false);
-            mEnvironment.setQuality(FilterEnvironment.QUALITY_FINAL);
-            mEnvironment.setScaleFactor(1.0f);
-            mFiltersManager.freeFilterResources(preset);
-            bitmap = preset.applyGeometry(bitmap, mEnvironment);
-            bitmap = preset.apply(bitmap, mEnvironment);
-            return bitmap;
-        }
-    }
-
-    public Bitmap renderGeometryIcon(Bitmap bitmap, ImagePreset preset) {
-        return GeometryMathUtils.applyGeometryRepresentations(preset.getGeometryFilters(), bitmap);
-    }
-
-    public void compute(SharedBuffer buffer, ImagePreset preset, int type) {
-        if (getRenderScriptContext() == null) {
-            return;
-        }
-        setupEnvironment(preset, false);
-        Vector<FilterRepresentation> filters = preset.getFilters();
-        Bitmap result = mCachedProcessing.process(mOriginalBitmap, filters, mEnvironment);
-        buffer.setProducer(result);
-    }
-
-    public synchronized void computeOld(SharedBuffer buffer, ImagePreset preset, int type) {
-        synchronized (CachingPipeline.class) {
-            if (getRenderScriptContext() == null) {
-                return;
-            }
-            if (DEBUG) {
-                Log.v(LOGTAG, "compute preset " + preset);
-                preset.showFilters();
-            }
-
-            String thread = Thread.currentThread().getName();
-            long time = System.currentTimeMillis();
-            setupEnvironment(preset, false);
-            mFiltersManager.freeFilterResources(preset);
-
-            Bitmap resizedOriginalBitmap = mResizedOriginalBitmap;
-            if (updateOriginalAllocation(preset) || buffer.getProducer() == null) {
-                resizedOriginalBitmap = mResizedOriginalBitmap;
-                buffer.setProducer(resizedOriginalBitmap);
-                mEnvironment.cache(buffer.getProducer());
-            }
-
-            Bitmap bitmap = buffer.getProducer().getBitmap();
-            long time2 = System.currentTimeMillis();
-
-            if (bitmap == null || (bitmap.getWidth() != resizedOriginalBitmap.getWidth())
-                    || (bitmap.getHeight() != resizedOriginalBitmap.getHeight())) {
-                mEnvironment.cache(buffer.getProducer());
-                buffer.setProducer(resizedOriginalBitmap);
-                bitmap = buffer.getProducer().getBitmap();
-            }
-            mOriginalAllocation.copyTo(bitmap);
-
-            Bitmap tmpbitmap = preset.apply(bitmap, mEnvironment);
-            if (tmpbitmap != bitmap) {
-                mEnvironment.cache(buffer.getProducer());
-                buffer.setProducer(tmpbitmap);
-            }
-
-            mFiltersManager.freeFilterResources(preset);
-
-            time = System.currentTimeMillis() - time;
-            time2 = System.currentTimeMillis() - time2;
-            if (DEBUG) {
-                Log.v(LOGTAG, "Applying type " + type + " filters to bitmap "
-                        + bitmap + " (" + bitmap.getWidth() + " x " + bitmap.getHeight()
-                        + ") took " + time + " ms, " + time2 + " ms for the filter, on thread " + thread);
-            }
-        }
-    }
-
-    public boolean needsRepaint() {
-        SharedBuffer buffer = MasterImage.getImage().getPreviewBuffer();
-        return buffer.checkRepaintNeeded();
-    }
-
-    public void setPreviewScaleFactor(float previewScaleFactor) {
-        mPreviewScaleFactor = previewScaleFactor;
-    }
-
-    public void setHighResPreviewScaleFactor(float highResPreviewScaleFactor) {
-        mHighResPreviewScaleFactor = highResPreviewScaleFactor;
-    }
-
-    public synchronized boolean isInitialized() {
-        return getRenderScriptContext() != null && mOriginalBitmap != null;
-    }
-
-    public boolean prepareRenderscriptAllocations(Bitmap bitmap) {
-        RenderScript RS = getRenderScriptContext();
-        boolean needsUpdate = false;
-        if (mOutPixelsAllocation == null || mInPixelsAllocation == null ||
-                bitmap.getWidth() != mWidth || bitmap.getHeight() != mHeight) {
-            destroyPixelAllocations();
-            Bitmap bitmapBuffer = bitmap;
-            if (bitmap.getConfig() == null || bitmap.getConfig() != BITMAP_CONFIG) {
-                bitmapBuffer = bitmap.copy(BITMAP_CONFIG, true);
-            }
-            mOutPixelsAllocation = Allocation.createFromBitmap(RS, bitmapBuffer,
-                    Allocation.MipmapControl.MIPMAP_NONE, Allocation.USAGE_SCRIPT);
-            mInPixelsAllocation = Allocation.createTyped(RS,
-                    mOutPixelsAllocation.getType());
-            needsUpdate = true;
-        }
-        if (RS != null) {
-            mInPixelsAllocation.copyFrom(bitmap);
-        }
-        if (bitmap.getWidth() != mWidth
-                || bitmap.getHeight() != mHeight) {
-            mWidth = bitmap.getWidth();
-            mHeight = bitmap.getHeight();
-            needsUpdate = true;
-        }
-        if (DEBUG) {
-            Log.v(LOGTAG, "prepareRenderscriptAllocations: " + needsUpdate + " in " + getName());
-        }
-        return needsUpdate;
-    }
-
-    public synchronized Allocation getInPixelsAllocation() {
-        return mInPixelsAllocation;
-    }
-
-    public synchronized Allocation getOutPixelsAllocation() {
-        return mOutPixelsAllocation;
-    }
-
-    public String getName() {
-        return mName;
-    }
-
-    public RenderScript getRSContext() {
-        return CachingPipeline.getRenderScriptContext();
-    }
-}
diff --git a/src/com/android/gallery3d/filtershow/pipeline/FilterEnvironment.java b/src/com/android/gallery3d/filtershow/pipeline/FilterEnvironment.java
deleted file mode 100644
index 4fac956..0000000
--- a/src/com/android/gallery3d/filtershow/pipeline/FilterEnvironment.java
+++ /dev/null
@@ -1,178 +0,0 @@
-/*
- * Copyright (C) 2013 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.gallery3d.filtershow.pipeline;
-
-import android.graphics.Bitmap;
-import android.graphics.Canvas;
-import android.graphics.Matrix;
-import android.graphics.Paint;
-import android.support.v8.renderscript.Allocation;
-
-import com.android.gallery3d.filtershow.filters.FilterRepresentation;
-import com.android.gallery3d.filtershow.filters.FilterUserPresetRepresentation;
-import com.android.gallery3d.filtershow.filters.FilterRotateRepresentation.Rotation;
-import com.android.gallery3d.filtershow.filters.FiltersManagerInterface;
-import com.android.gallery3d.filtershow.filters.ImageFilter;
-
-import java.lang.ref.WeakReference;
-import java.util.HashMap;
-
-public class FilterEnvironment {
-    private static final String LOGTAG = "FilterEnvironment";
-    private ImagePreset mImagePreset;
-    private float mScaleFactor;
-    private int mQuality;
-    private FiltersManagerInterface mFiltersManager;
-    private PipelineInterface mPipeline;
-    private volatile boolean mStop = false;
-
-    public static final int QUALITY_ICON = 0;
-    public static final int QUALITY_PREVIEW = 1;
-    public static final int QUALITY_FINAL = 2;
-
-    public synchronized boolean needsStop() {
-        return mStop;
-    }
-
-    public synchronized void setStop(boolean stop) {
-        this.mStop = stop;
-    }
-
-    private HashMap<Long, WeakReference<Bitmap>>
-            bitmapCach = new HashMap<Long, WeakReference<Bitmap>>();
-
-    private HashMap<Integer, Integer>
-                    generalParameters = new HashMap<Integer, Integer>();
-
-    public void cache(Buffer buffer) {
-        if (buffer == null) {
-            return;
-        }
-        Bitmap bitmap = buffer.getBitmap();
-        if (bitmap == null) {
-            return;
-        }
-        Long key = calcKey(bitmap.getWidth(), bitmap.getHeight());
-        bitmapCach.put(key, new WeakReference<Bitmap>(bitmap));
-    }
-
-    public Bitmap getBitmap(int w, int h) {
-        Long key = calcKey(w, h);
-        WeakReference<Bitmap> ref = bitmapCach.remove(key);
-        Bitmap bitmap = null;
-        if (ref != null) {
-            bitmap = ref.get();
-        }
-        if (bitmap == null) {
-            bitmap = Bitmap.createBitmap(
-                    w, h, Bitmap.Config.ARGB_8888);
-        }
-        return bitmap;
-    }
-
-    private Long calcKey(long w, long h) {
-        return (w << 32) | (h << 32);
-    }
-
-    public void setImagePreset(ImagePreset imagePreset) {
-        mImagePreset = imagePreset;
-    }
-
-    public ImagePreset getImagePreset() {
-        return mImagePreset;
-    }
-
-    public void setScaleFactor(float scaleFactor) {
-        mScaleFactor = scaleFactor;
-    }
-
-    public float getScaleFactor() {
-        return mScaleFactor;
-    }
-
-    public void setQuality(int quality) {
-        mQuality = quality;
-    }
-
-    public int getQuality() {
-        return mQuality;
-    }
-
-    public void setFiltersManager(FiltersManagerInterface filtersManager) {
-        mFiltersManager = filtersManager;
-    }
-
-    public FiltersManagerInterface getFiltersManager() {
-        return mFiltersManager;
-    }
-
-    public void applyRepresentation(FilterRepresentation representation,
-                                    Allocation in, Allocation out) {
-        ImageFilter filter = mFiltersManager.getFilterForRepresentation(representation);
-        filter.useRepresentation(representation);
-        filter.setEnvironment(this);
-        if (filter.supportsAllocationInput()) {
-            filter.apply(in, out);
-        }
-        filter.setGeneralParameters();
-        filter.setEnvironment(null);
-    }
-
-    public Bitmap applyRepresentation(FilterRepresentation representation, Bitmap bitmap) {
-        if (representation instanceof FilterUserPresetRepresentation) {
-            // we allow instances of FilterUserPresetRepresentation in a preset only to know if one
-            // has been applied (so we can show this in the UI). But as all the filters in them are
-            // applied directly they do not themselves need to do any kind of filtering.
-            return bitmap;
-        }
-        ImageFilter filter = mFiltersManager.getFilterForRepresentation(representation);
-        filter.useRepresentation(representation);
-        filter.setEnvironment(this);
-        Bitmap ret = filter.apply(bitmap, mScaleFactor, mQuality);
-        filter.setGeneralParameters();
-        filter.setEnvironment(null);
-        return ret;
-    }
-
-    public PipelineInterface getPipeline() {
-        return mPipeline;
-    }
-
-    public void setPipeline(PipelineInterface cachingPipeline) {
-        mPipeline = cachingPipeline;
-    }
-
-    public synchronized void clearGeneralParameters() {
-        generalParameters = null;
-    }
-
-    public synchronized Integer getGeneralParameter(int id) {
-        if (generalParameters == null || !generalParameters.containsKey(id)) {
-            return null;
-        }
-        return generalParameters.get(id);
-    }
-
-    public synchronized void setGeneralParameter(int id, int value) {
-        if (generalParameters == null) {
-            generalParameters = new HashMap<Integer, Integer>();
-        }
-
-        generalParameters.put(id, value);
-    }
-
-}
diff --git a/src/com/android/gallery3d/filtershow/pipeline/HighresRenderingRequestTask.java b/src/com/android/gallery3d/filtershow/pipeline/HighresRenderingRequestTask.java
deleted file mode 100644
index 5a0eb4d..0000000
--- a/src/com/android/gallery3d/filtershow/pipeline/HighresRenderingRequestTask.java
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * Copyright (C) 2013 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.gallery3d.filtershow.pipeline;
-
-import android.graphics.Bitmap;
-import com.android.gallery3d.filtershow.filters.FiltersManager;
-
-public class HighresRenderingRequestTask extends ProcessingTask {
-
-    private CachingPipeline mHighresPreviewPipeline = null;
-    private boolean mPipelineIsOn = false;
-
-    public void setHighresPreviewScaleFactor(float highResPreviewScale) {
-        mHighresPreviewPipeline.setHighResPreviewScaleFactor(highResPreviewScale);
-    }
-
-    public void setPreviewScaleFactor(float previewScale) {
-        mHighresPreviewPipeline.setPreviewScaleFactor(previewScale);
-    }
-
-    static class Render implements Request {
-        RenderingRequest request;
-    }
-
-    static class RenderResult implements Result {
-        RenderingRequest request;
-    }
-
-    public HighresRenderingRequestTask() {
-        mHighresPreviewPipeline = new CachingPipeline(
-                FiltersManager.getHighresManager(), "Highres");
-    }
-
-    public void setOriginal(Bitmap bitmap) {
-        mHighresPreviewPipeline.setOriginal(bitmap);
-    }
-
-    public void setOriginalBitmapHighres(Bitmap originalHires) {
-        mPipelineIsOn = true;
-    }
-
-    public void stop() {
-        mHighresPreviewPipeline.stop();
-    }
-
-    public void postRenderingRequest(RenderingRequest request) {
-        if (!mPipelineIsOn) {
-            return;
-        }
-        Render render = new Render();
-        render.request = request;
-        postRequest(render);
-    }
-
-    @Override
-    public Result doInBackground(Request message) {
-        RenderingRequest request = ((Render) message).request;
-        RenderResult result = null;
-        mHighresPreviewPipeline.renderHighres(request);
-        result = new RenderResult();
-        result.request = request;
-        return result;
-    }
-
-    @Override
-    public void onResult(Result message) {
-        if (message == null) {
-            return;
-        }
-        RenderingRequest request = ((RenderResult) message).request;
-        request.markAvailable();
-    }
-
-    @Override
-    public boolean isDelayedTask() { return true; }
-}
diff --git a/src/com/android/gallery3d/filtershow/pipeline/ImagePreset.java b/src/com/android/gallery3d/filtershow/pipeline/ImagePreset.java
deleted file mode 100644
index d34216a..0000000
--- a/src/com/android/gallery3d/filtershow/pipeline/ImagePreset.java
+++ /dev/null
@@ -1,694 +0,0 @@
-/*
- * 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.gallery3d.filtershow.pipeline;
-
-import android.graphics.Bitmap;
-import android.graphics.Rect;
-import android.support.v8.renderscript.Allocation;
-import android.util.JsonReader;
-import android.util.JsonWriter;
-import android.util.Log;
-
-import com.android.gallery3d.R;
-import com.android.gallery3d.filtershow.cache.ImageLoader;
-import com.android.gallery3d.filtershow.filters.BaseFiltersManager;
-import com.android.gallery3d.filtershow.filters.FilterCropRepresentation;
-import com.android.gallery3d.filtershow.filters.FilterFxRepresentation;
-import com.android.gallery3d.filtershow.filters.FilterImageBorderRepresentation;
-import com.android.gallery3d.filtershow.filters.FilterMirrorRepresentation;
-import com.android.gallery3d.filtershow.filters.FilterRepresentation;
-import com.android.gallery3d.filtershow.filters.FilterRotateRepresentation;
-import com.android.gallery3d.filtershow.filters.FilterStraightenRepresentation;
-import com.android.gallery3d.filtershow.filters.FilterUserPresetRepresentation;
-import com.android.gallery3d.filtershow.filters.FiltersManager;
-import com.android.gallery3d.filtershow.filters.ImageFilter;
-import com.android.gallery3d.filtershow.imageshow.GeometryMathUtils;
-import com.android.gallery3d.filtershow.imageshow.MasterImage;
-import com.android.gallery3d.filtershow.state.State;
-import com.android.gallery3d.filtershow.state.StateAdapter;
-import com.android.gallery3d.util.UsageStatistics;
-
-import java.io.IOException;
-import java.io.StringReader;
-import java.io.StringWriter;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Vector;
-
-public class ImagePreset {
-
-    private static final String LOGTAG = "ImagePreset";
-
-    private Vector<FilterRepresentation> mFilters = new Vector<FilterRepresentation>();
-
-    private boolean mDoApplyGeometry = true;
-    private boolean mDoApplyFilters = true;
-
-    private boolean mPartialRendering = false;
-    private Rect mPartialRenderingBounds;
-    private static final boolean DEBUG = false;
-
-    public ImagePreset() {
-    }
-
-    public ImagePreset(ImagePreset source) {
-        for (int i = 0; i < source.mFilters.size(); i++) {
-            FilterRepresentation sourceRepresentation = source.mFilters.elementAt(i);
-            mFilters.add(sourceRepresentation.copy());
-        }
-    }
-
-    public Vector<FilterRepresentation> getFilters() {
-        return mFilters;
-    }
-
-    public FilterRepresentation getFilterRepresentation(int position) {
-        FilterRepresentation representation = null;
-
-        representation = mFilters.elementAt(position).copy();
-
-        return representation;
-    }
-
-    private static boolean sameSerializationName(String a, String b) {
-        if (a != null && b != null) {
-            return a.equals(b);
-        } else {
-            return a == null && b == null;
-        }
-    }
-
-    public static boolean sameSerializationName(FilterRepresentation a, FilterRepresentation b) {
-        if (a == null || b == null) {
-            return false;
-        }
-        return sameSerializationName(a.getSerializationName(), b.getSerializationName());
-    }
-
-    public int getPositionForRepresentation(FilterRepresentation representation) {
-        for (int i = 0; i < mFilters.size(); i++) {
-            if (sameSerializationName(mFilters.elementAt(i), representation)) {
-                return i;
-            }
-        }
-        return -1;
-    }
-
-    private FilterRepresentation getFilterRepresentationForType(int type) {
-        for (int i = 0; i < mFilters.size(); i++) {
-            if (mFilters.elementAt(i).getFilterType() == type) {
-                return mFilters.elementAt(i);
-            }
-        }
-        return null;
-    }
-
-    public int getPositionForType(int type) {
-        for (int i = 0; i < mFilters.size(); i++) {
-            if (mFilters.elementAt(i).getFilterType() == type) {
-                return i;
-            }
-        }
-        return -1;
-    }
-
-    public FilterRepresentation getFilterRepresentationCopyFrom(
-            FilterRepresentation filterRepresentation) {
-        // TODO: add concept of position in the filters (to allow multiple instances)
-        if (filterRepresentation == null) {
-            return null;
-        }
-        int position = getPositionForRepresentation(filterRepresentation);
-        if (position == -1) {
-            return null;
-        }
-        FilterRepresentation representation = mFilters.elementAt(position);
-        if (representation != null) {
-            representation = representation.copy();
-        }
-        return representation;
-    }
-
-    public void updateFilterRepresentations(Collection<FilterRepresentation> reps) {
-        for (FilterRepresentation r : reps) {
-            updateOrAddFilterRepresentation(r);
-        }
-    }
-
-    public void updateOrAddFilterRepresentation(FilterRepresentation rep) {
-        int pos = getPositionForRepresentation(rep);
-        if (pos != -1) {
-            mFilters.elementAt(pos).useParametersFrom(rep);
-        } else {
-            addFilter(rep.copy());
-        }
-    }
-
-    public void setDoApplyGeometry(boolean value) {
-        mDoApplyGeometry = value;
-    }
-
-    public void setDoApplyFilters(boolean value) {
-        mDoApplyFilters = value;
-    }
-
-    public boolean getDoApplyFilters() {
-        return mDoApplyFilters;
-    }
-
-    public boolean hasModifications() {
-        for (int i = 0; i < mFilters.size(); i++) {
-            FilterRepresentation filter = mFilters.elementAt(i);
-            if (!filter.isNil()) {
-                return true;
-            }
-        }
-        return false;
-    }
-
-    public boolean isPanoramaSafe() {
-        for (FilterRepresentation representation : mFilters) {
-            if (representation.getFilterType() == FilterRepresentation.TYPE_GEOMETRY
-                    && !representation.isNil()) {
-                return false;
-            }
-            if (representation.getFilterType() == FilterRepresentation.TYPE_BORDER
-                    && !representation.isNil()) {
-                return false;
-            }
-            if (representation.getFilterType() == FilterRepresentation.TYPE_VIGNETTE
-                    && !representation.isNil()) {
-                return false;
-            }
-            if (representation.getFilterType() == FilterRepresentation.TYPE_TINYPLANET
-                    && !representation.isNil()) {
-                return false;
-            }
-        }
-        return true;
-    }
-
-    public boolean same(ImagePreset preset) {
-        if (preset == null) {
-            return false;
-        }
-
-        if (preset.mFilters.size() != mFilters.size()) {
-            return false;
-        }
-
-        if (mDoApplyGeometry != preset.mDoApplyGeometry) {
-            return false;
-        }
-
-        if (mDoApplyFilters != preset.mDoApplyFilters) {
-            if (mFilters.size() > 0 || preset.mFilters.size() > 0) {
-                return false;
-            }
-        }
-
-        if (mDoApplyFilters && preset.mDoApplyFilters) {
-            for (int i = 0; i < preset.mFilters.size(); i++) {
-                FilterRepresentation a = preset.mFilters.elementAt(i);
-                FilterRepresentation b = mFilters.elementAt(i);
-
-                if (!a.same(b)) {
-                    return false;
-                }
-            }
-        }
-
-        return true;
-    }
-
-    public int similarUpTo(ImagePreset preset) {
-        for (int i = 0; i < preset.mFilters.size(); i++) {
-            FilterRepresentation a = preset.mFilters.elementAt(i);
-            if (i < mFilters.size()) {
-                FilterRepresentation b = mFilters.elementAt(i);
-                if (!a.same(b)) {
-                    return i;
-                }
-                if (!a.equals(b)) {
-                    return i;
-                }
-            } else {
-                return i;
-            }
-        }
-        return preset.mFilters.size();
-    }
-
-    public void showFilters() {
-        Log.v(LOGTAG, "\\\\\\ showFilters -- " + mFilters.size() + " filters");
-        int n = 0;
-        for (FilterRepresentation representation : mFilters) {
-            Log.v(LOGTAG, " filter " + n + " : " + representation.toString());
-            n++;
-        }
-        Log.v(LOGTAG, "/// showFilters -- " + mFilters.size() + " filters");
-    }
-
-    public FilterRepresentation getLastRepresentation() {
-        if (mFilters.size() > 0) {
-            return mFilters.lastElement();
-        }
-        return null;
-    }
-
-    public void removeFilter(FilterRepresentation filterRepresentation) {
-        if (filterRepresentation.getFilterType() == FilterRepresentation.TYPE_BORDER) {
-            for (int i = 0; i < mFilters.size(); i++) {
-                if (mFilters.elementAt(i).getFilterType()
-                == filterRepresentation.getFilterType()) {
-                    mFilters.remove(i);
-                    break;
-                }
-            }
-        } else {
-            for (int i = 0; i < mFilters.size(); i++) {
-                if (sameSerializationName(mFilters.elementAt(i), filterRepresentation)) {
-                    mFilters.remove(i);
-                    break;
-                }
-            }
-        }
-    }
-
-    // If the filter is an "None" effect or border, then just don't add this filter.
-    public void addFilter(FilterRepresentation representation) {
-        if (representation instanceof FilterUserPresetRepresentation) {
-            ImagePreset preset = ((FilterUserPresetRepresentation) representation).getImagePreset();
-            // user preset replace everything but geometry
-            mFilters.clear();
-            for (int i = 0; i < preset.nbFilters(); i++) {
-                addFilter(preset.getFilterRepresentation(i));
-            }
-            mFilters.add(representation);
-        } else if (representation.getFilterType() == FilterRepresentation.TYPE_GEOMETRY) {
-            // Add geometry filter, removing duplicates and do-nothing operations.
-            for (int i = 0; i < mFilters.size(); i++) {
-                if (sameSerializationName(representation, mFilters.elementAt(i))) {
-                    mFilters.remove(i);
-                }
-            }
-            if (!representation.isNil()) {
-                mFilters.add(representation);
-            }
-        } else if (representation.getFilterType() == FilterRepresentation.TYPE_BORDER) {
-            removeFilter(representation);
-            if (!isNoneBorderFilter(representation)) {
-                mFilters.add(representation);
-            }
-        } else if (representation.getFilterType() == FilterRepresentation.TYPE_FX) {
-            boolean found = false;
-            for (int i = 0; i < mFilters.size(); i++) {
-                FilterRepresentation current = mFilters.elementAt(i);
-                int type = current.getFilterType();
-                if (found) {
-                    if (type != FilterRepresentation.TYPE_VIGNETTE) {
-                        mFilters.remove(i);
-                        continue;
-                    }
-                }
-                if (type == FilterRepresentation.TYPE_FX) {
-                    if (current instanceof FilterUserPresetRepresentation) {
-                        ImagePreset preset = ((FilterUserPresetRepresentation) current)
-                                .getImagePreset();
-                        // If we had an existing user preset, let's remove all the presets that
-                        // were added by it
-                        for (int j = 0; j < preset.nbFilters(); j++) {
-                            FilterRepresentation rep = preset.getFilterRepresentation(j);
-                            int pos = getPositionForRepresentation(rep);
-                            if (pos != -1) {
-                                mFilters.remove(pos);
-                            }
-                        }
-                        int pos = getPositionForRepresentation(current);
-                        if (pos != -1) {
-                            mFilters.remove(pos);
-                        } else {
-                            pos = 0;
-                        }
-                        if (!isNoneFxFilter(representation)) {
-                            mFilters.add(pos, representation);
-                        }
-
-                    } else {
-                        mFilters.remove(i);
-                        if (!isNoneFxFilter(representation)) {
-                            mFilters.add(i, representation);
-                        }
-                    }
-                    found = true;
-                }
-            }
-            if (!found) {
-                if (!isNoneFxFilter(representation)) {
-                    mFilters.add(representation);
-                }
-            }
-        } else {
-            mFilters.add(representation);
-        }
-    }
-
-    private boolean isNoneBorderFilter(FilterRepresentation representation) {
-        return representation instanceof FilterImageBorderRepresentation &&
-                ((FilterImageBorderRepresentation) representation).getDrawableResource() == 0;
-    }
-
-    private boolean isNoneFxFilter(FilterRepresentation representation) {
-        return representation instanceof FilterFxRepresentation &&
-                ((FilterFxRepresentation) representation).getNameResource() == R.string.none;
-    }
-
-    public FilterRepresentation getRepresentation(FilterRepresentation filterRepresentation) {
-        for (int i = 0; i < mFilters.size(); i++) {
-            FilterRepresentation representation = mFilters.elementAt(i);
-            if (sameSerializationName(representation, filterRepresentation)) {
-                return representation;
-            }
-        }
-        return null;
-    }
-
-    public Bitmap apply(Bitmap original, FilterEnvironment environment) {
-        Bitmap bitmap = original;
-        bitmap = applyFilters(bitmap, -1, -1, environment);
-        return applyBorder(bitmap, environment);
-    }
-
-    public Collection<FilterRepresentation> getGeometryFilters() {
-        ArrayList<FilterRepresentation> geometry = new ArrayList<FilterRepresentation>();
-        for (FilterRepresentation r : mFilters) {
-            if (r.getFilterType() == FilterRepresentation.TYPE_GEOMETRY) {
-                geometry.add(r);
-            }
-        }
-        return geometry;
-    }
-
-    public FilterRepresentation getFilterWithSerializationName(String serializationName) {
-        for (FilterRepresentation r : mFilters) {
-            if (r != null) {
-                if (sameSerializationName(r.getSerializationName(), serializationName)) {
-                    return r.copy();
-                }
-            }
-        }
-        return null;
-    }
-
-    public Bitmap applyGeometry(Bitmap bitmap, FilterEnvironment environment) {
-        // Apply any transform -- 90 rotate, flip, straighten, crop
-        // Returns a new bitmap.
-        if (mDoApplyGeometry) {
-            bitmap = GeometryMathUtils.applyGeometryRepresentations(getGeometryFilters(), bitmap);
-        }
-        return bitmap;
-    }
-
-    public Bitmap applyBorder(Bitmap bitmap, FilterEnvironment environment) {
-        // get the border from the list of filters.
-        FilterRepresentation border = getFilterRepresentationForType(
-                FilterRepresentation.TYPE_BORDER);
-        if (border != null && mDoApplyGeometry) {
-            bitmap = environment.applyRepresentation(border, bitmap);
-            if (environment.getQuality() == FilterEnvironment.QUALITY_FINAL) {
-                UsageStatistics.onEvent(UsageStatistics.COMPONENT_EDITOR,
-                        "SaveBorder", border.getSerializationName(), 1);
-            }
-        }
-        return bitmap;
-    }
-
-    public int nbFilters() {
-        return mFilters.size();
-    }
-
-    public Bitmap applyFilters(Bitmap bitmap, int from, int to, FilterEnvironment environment) {
-        if (mDoApplyFilters) {
-            if (from < 0) {
-                from = 0;
-            }
-            if (to == -1) {
-                to = mFilters.size();
-            }
-            if (environment.getQuality() == FilterEnvironment.QUALITY_FINAL) {
-                UsageStatistics.onEvent(UsageStatistics.COMPONENT_EDITOR,
-                        "SaveFilters", "Total", to - from + 1);
-            }
-            for (int i = from; i < to; i++) {
-                FilterRepresentation representation = mFilters.elementAt(i);
-                if (representation.getFilterType() == FilterRepresentation.TYPE_GEOMETRY) {
-                    // skip the geometry as it's already applied.
-                    continue;
-                }
-                if (representation.getFilterType() == FilterRepresentation.TYPE_BORDER) {
-                    // for now, let's skip the border as it will be applied in
-                    // applyBorder()
-                    // TODO: might be worth getting rid of applyBorder.
-                    continue;
-                }
-                bitmap = environment.applyRepresentation(representation, bitmap);
-                if (environment.getQuality() == FilterEnvironment.QUALITY_FINAL) {
-                    UsageStatistics.onEvent(UsageStatistics.COMPONENT_EDITOR,
-                            "SaveFilter", representation.getSerializationName(), 1);
-                }
-                if (environment.needsStop()) {
-                    return bitmap;
-                }
-            }
-        }
-
-        return bitmap;
-    }
-
-    public void applyBorder(Allocation in, Allocation out,
-            boolean copyOut, FilterEnvironment environment) {
-        FilterRepresentation border = getFilterRepresentationForType(
-                FilterRepresentation.TYPE_BORDER);
-        if (border != null && mDoApplyGeometry) {
-            // TODO: should keep the bitmap around
-            Allocation bitmapIn = in;
-            if (copyOut) {
-                bitmapIn = Allocation.createTyped(
-                        CachingPipeline.getRenderScriptContext(), in.getType());
-                bitmapIn.copyFrom(out);
-            }
-            environment.applyRepresentation(border, bitmapIn, out);
-        }
-    }
-
-    public void applyFilters(int from, int to, Allocation in, Allocation out,
-            FilterEnvironment environment) {
-        if (mDoApplyFilters) {
-            if (from < 0) {
-                from = 0;
-            }
-            if (to == -1) {
-                to = mFilters.size();
-            }
-            for (int i = from; i < to; i++) {
-                FilterRepresentation representation = mFilters.elementAt(i);
-                if (representation.getFilterType() == FilterRepresentation.TYPE_GEOMETRY
-                        || representation.getFilterType() == FilterRepresentation.TYPE_BORDER) {
-                    continue;
-                }
-                if (i > from) {
-                    in.copyFrom(out);
-                }
-                environment.applyRepresentation(representation, in, out);
-            }
-        }
-    }
-
-    public boolean canDoPartialRendering() {
-        if (MasterImage.getImage().getZoomOrientation() != ImageLoader.ORI_NORMAL) {
-            return false;
-        }
-        for (int i = 0; i < mFilters.size(); i++) {
-            FilterRepresentation representation = mFilters.elementAt(i);
-            if (representation.getFilterType() == FilterRepresentation.TYPE_GEOMETRY
-                    && !representation.isNil()) {
-                return false;
-            }
-            if (!representation.supportsPartialRendering()) {
-                return false;
-            }
-        }
-        return true;
-    }
-
-    public void fillImageStateAdapter(StateAdapter imageStateAdapter) {
-        if (imageStateAdapter == null) {
-            return;
-        }
-        Vector<State> states = new Vector<State>();
-        for (FilterRepresentation filter : mFilters) {
-            if (filter.getFilterType() == FilterRepresentation.TYPE_GEOMETRY) {
-                // TODO: supports Geometry representations in the state panel.
-                continue;
-            }
-            if (filter instanceof FilterUserPresetRepresentation) {
-                // do not show the user preset itself in the state panel
-                continue;
-            }
-            State state = new State(filter.getName());
-            state.setFilterRepresentation(filter);
-            states.add(state);
-        }
-        imageStateAdapter.fill(states);
-    }
-
-    public void setPartialRendering(boolean partialRendering, Rect bounds) {
-        mPartialRendering = partialRendering;
-        mPartialRenderingBounds = bounds;
-    }
-
-    public boolean isPartialRendering() {
-        return mPartialRendering;
-    }
-
-    public Rect getPartialRenderingBounds() {
-        return mPartialRenderingBounds;
-    }
-
-    public Vector<ImageFilter> getUsedFilters(BaseFiltersManager filtersManager) {
-        Vector<ImageFilter> usedFilters = new Vector<ImageFilter>();
-        for (int i = 0; i < mFilters.size(); i++) {
-            FilterRepresentation representation = mFilters.elementAt(i);
-            ImageFilter filter = filtersManager.getFilterForRepresentation(representation);
-            usedFilters.add(filter);
-        }
-        return usedFilters;
-    }
-
-    public String getJsonString(String name) {
-        StringWriter swriter = new StringWriter();
-        try {
-            JsonWriter writer = new JsonWriter(swriter);
-            writeJson(writer, name);
-            writer.close();
-        } catch (IOException e) {
-            return null;
-        }
-        return swriter.toString();
-    }
-
-    public void writeJson(JsonWriter writer, String name) {
-        int numFilters = mFilters.size();
-        try {
-            writer.beginObject();
-            for (int i = 0; i < numFilters; i++) {
-                FilterRepresentation filter = mFilters.get(i);
-                if (filter instanceof FilterUserPresetRepresentation) {
-                    continue;
-                }
-                String sname = filter.getSerializationName();
-                if (DEBUG) {
-                    Log.v(LOGTAG, "Serialization: " + sname);
-                    if (sname == null) {
-                        Log.v(LOGTAG, "Serialization name null for filter: " + filter);
-                    }
-                }
-                writer.name(sname);
-                filter.serializeRepresentation(writer);
-            }
-            writer.endObject();
-
-        } catch (IOException e) {
-           Log.e(LOGTAG,"Error encoding JASON",e);
-        }
-    }
-
-    /**
-     * populates preset from JSON string
-     *
-     * @param filterString a JSON string
-     * @return true on success if false ImagePreset is undefined
-     */
-    public boolean readJsonFromString(String filterString) {
-        if (DEBUG) {
-            Log.v(LOGTAG, "reading preset: \"" + filterString + "\"");
-        }
-        StringReader sreader = new StringReader(filterString);
-        try {
-            JsonReader reader = new JsonReader(sreader);
-            boolean ok = readJson(reader);
-            if (!ok) {
-                reader.close();
-                return false;
-            }
-            reader.close();
-        } catch (Exception e) {
-            Log.e(LOGTAG, "parsing the filter parameters:", e);
-            return false;
-        }
-        return true;
-    }
-
-    /**
-     * populates preset from JSON stream
-     *
-     * @param sreader a JSON string
-     * @return true on success if false ImagePreset is undefined
-     */
-    public boolean readJson(JsonReader sreader) throws IOException {
-        sreader.beginObject();
-
-        while (sreader.hasNext()) {
-            String name = sreader.nextName();
-            FilterRepresentation filter = creatFilterFromName(name);
-            if (filter == null) {
-                Log.w(LOGTAG, "UNKNOWN FILTER! " + name);
-                return false;
-            }
-            filter.deSerializeRepresentation(sreader);
-            addFilter(filter);
-        }
-        sreader.endObject();
-        return true;
-    }
-
-    FilterRepresentation creatFilterFromName(String name) {
-        if (FilterRotateRepresentation.SERIALIZATION_NAME.equals(name)) {
-            return new FilterRotateRepresentation();
-        } else if (FilterMirrorRepresentation.SERIALIZATION_NAME.equals(name)) {
-            return new FilterMirrorRepresentation();
-        } else if (FilterStraightenRepresentation.SERIALIZATION_NAME.equals(name)) {
-            return new FilterStraightenRepresentation();
-        } else if (FilterCropRepresentation.SERIALIZATION_NAME.equals(name)) {
-            return new FilterCropRepresentation();
-        }
-        FiltersManager filtersManager = FiltersManager.getManager();
-        return filtersManager.createFilterFromName(name);
-    }
-
-    public void updateWith(ImagePreset preset) {
-        if (preset.mFilters.size() != mFilters.size()) {
-            Log.e(LOGTAG, "Updating a preset with an incompatible one");
-            return;
-        }
-        for (int i = 0; i < mFilters.size(); i++) {
-            FilterRepresentation destRepresentation = mFilters.elementAt(i);
-            FilterRepresentation sourceRepresentation = preset.mFilters.elementAt(i);
-            destRepresentation.useParametersFrom(sourceRepresentation);
-        }
-    }
-}
diff --git a/src/com/android/gallery3d/filtershow/pipeline/ImageSavingTask.java b/src/com/android/gallery3d/filtershow/pipeline/ImageSavingTask.java
deleted file mode 100644
index b760edd..0000000
--- a/src/com/android/gallery3d/filtershow/pipeline/ImageSavingTask.java
+++ /dev/null
@@ -1,125 +0,0 @@
-/*
- * Copyright (C) 2013 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.gallery3d.filtershow.pipeline;
-
-import android.content.res.Resources;
-import android.graphics.Bitmap;
-import android.net.Uri;
-import com.android.gallery3d.filtershow.cache.ImageLoader;
-import com.android.gallery3d.filtershow.filters.FiltersManager;
-import com.android.gallery3d.filtershow.tools.SaveImage;
-
-import java.io.File;
-
-public class ImageSavingTask extends ProcessingTask {
-    private ProcessingService mProcessingService;
-
-    static class SaveRequest implements Request {
-        Uri sourceUri;
-        Uri selectedUri;
-        File destinationFile;
-        ImagePreset preset;
-        boolean flatten;
-        int quality;
-    }
-
-    static class UpdateBitmap implements Update {
-        Bitmap bitmap;
-    }
-
-    static class UpdateProgress implements Update {
-        int max;
-        int current;
-    }
-
-    static class URIResult implements Result {
-        Uri uri;
-    }
-
-    public ImageSavingTask(ProcessingService service) {
-        mProcessingService = service;
-    }
-
-    public void saveImage(Uri sourceUri, Uri selectedUri,
-                          File destinationFile, ImagePreset preset, boolean flatten, int quality) {
-        SaveRequest request = new SaveRequest();
-        request.sourceUri = sourceUri;
-        request.selectedUri = selectedUri;
-        request.destinationFile = destinationFile;
-        request.preset = preset;
-        request.flatten = flatten;
-        request.quality = quality;
-        postRequest(request);
-    }
-
-    public Result doInBackground(Request message) {
-        SaveRequest request = (SaveRequest) message;
-        Uri sourceUri = request.sourceUri;
-        Uri selectedUri = request.selectedUri;
-        File destinationFile = request.destinationFile;
-        ImagePreset preset = request.preset;
-        boolean flatten = request.flatten;
-        // We create a small bitmap showing the result that we can
-        // give to the notification
-        UpdateBitmap updateBitmap = new UpdateBitmap();
-        updateBitmap.bitmap = createNotificationBitmap(sourceUri, preset);
-        postUpdate(updateBitmap);
-        SaveImage saveImage = new SaveImage(mProcessingService, sourceUri,
-                selectedUri, destinationFile,
-                new SaveImage.Callback() {
-                    @Override
-                    public void onProgress(int max, int current) {
-                        UpdateProgress updateProgress = new UpdateProgress();
-                        updateProgress.max = max;
-                        updateProgress.current = current;
-                        postUpdate(updateProgress);
-                    }
-                });
-        Uri uri = saveImage.processAndSaveImage(preset, !flatten, request.quality);
-        URIResult result = new URIResult();
-        result.uri = uri;
-        return result;
-    }
-
-    @Override
-    public void onResult(Result message) {
-        URIResult result = (URIResult) message;
-        mProcessingService.completeSaveImage(result.uri);
-    }
-
-    @Override
-    public void onUpdate(Update message) {
-        if (message instanceof UpdateBitmap) {
-            Bitmap bitmap = ((UpdateBitmap) message).bitmap;
-            mProcessingService.updateNotificationWithBitmap(bitmap);
-        }
-        if (message instanceof UpdateProgress) {
-            UpdateProgress progress = (UpdateProgress) message;
-            mProcessingService.updateProgress(progress.max, progress.current);
-        }
-    }
-
-    private Bitmap createNotificationBitmap(Uri sourceUri, ImagePreset preset) {
-        int notificationBitmapSize = Resources.getSystem().getDimensionPixelSize(
-                android.R.dimen.notification_large_icon_width);
-        Bitmap bitmap = ImageLoader.loadConstrainedBitmap(sourceUri, getContext(),
-                notificationBitmapSize, null, true);
-        CachingPipeline pipeline = new CachingPipeline(FiltersManager.getManager(), "Thumb");
-        return pipeline.renderFinalImage(bitmap, preset);
-    }
-
-}
diff --git a/src/com/android/gallery3d/filtershow/pipeline/PipelineInterface.java b/src/com/android/gallery3d/filtershow/pipeline/PipelineInterface.java
deleted file mode 100644
index d53768c..0000000
--- a/src/com/android/gallery3d/filtershow/pipeline/PipelineInterface.java
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright (C) 2013 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.gallery3d.filtershow.pipeline;
-
-import android.content.res.Resources;
-import android.graphics.Bitmap;
-import android.support.v8.renderscript.Allocation;
-import android.support.v8.renderscript.RenderScript;
-
-public interface PipelineInterface {
-    public String getName();
-    public Resources getResources();
-    public Allocation getInPixelsAllocation();
-    public Allocation getOutPixelsAllocation();
-    public boolean prepareRenderscriptAllocations(Bitmap bitmap);
-    public RenderScript getRSContext();
-}
diff --git a/src/com/android/gallery3d/filtershow/pipeline/ProcessingService.java b/src/com/android/gallery3d/filtershow/pipeline/ProcessingService.java
deleted file mode 100644
index d0504d1..0000000
--- a/src/com/android/gallery3d/filtershow/pipeline/ProcessingService.java
+++ /dev/null
@@ -1,283 +0,0 @@
-/*
- * Copyright (C) 2013 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.gallery3d.filtershow.pipeline;
-
-import android.app.Notification;
-import android.app.NotificationManager;
-import android.app.Service;
-import android.content.Context;
-import android.content.Intent;
-import android.content.res.Resources;
-import android.graphics.Bitmap;
-import android.net.Uri;
-import android.os.Binder;
-import android.os.IBinder;
-import android.util.Log;
-import com.android.gallery3d.R;
-import com.android.gallery3d.filtershow.FilterShowActivity;
-import com.android.gallery3d.filtershow.filters.FiltersManager;
-import com.android.gallery3d.filtershow.filters.ImageFilter;
-import com.android.gallery3d.filtershow.imageshow.MasterImage;
-import com.android.gallery3d.filtershow.tools.SaveImage;
-
-import java.io.File;
-
-public class ProcessingService extends Service {
-    private static final String LOGTAG = "ProcessingService";
-    private static final boolean SHOW_IMAGE = false;
-    private int mNotificationId;
-    private NotificationManager mNotifyMgr = null;
-    private Notification.Builder mBuilder = null;
-
-    private static final String PRESET = "preset";
-    private static final String QUALITY = "quality";
-    private static final String SOURCE_URI = "sourceUri";
-    private static final String SELECTED_URI = "selectedUri";
-    private static final String DESTINATION_FILE = "destinationFile";
-    private static final String SAVING = "saving";
-    private static final String FLATTEN = "flatten";
-
-    private ProcessingTaskController mProcessingTaskController;
-    private ImageSavingTask mImageSavingTask;
-    private UpdatePreviewTask mUpdatePreviewTask;
-    private HighresRenderingRequestTask mHighresRenderingRequestTask;
-    private RenderingRequestTask mRenderingRequestTask;
-
-    private final IBinder mBinder = new LocalBinder();
-    private FilterShowActivity mFiltershowActivity;
-
-    private boolean mSaving = false;
-    private boolean mNeedsAlive = false;
-
-    public void setFiltershowActivity(FilterShowActivity filtershowActivity) {
-        mFiltershowActivity = filtershowActivity;
-    }
-
-    public void setOriginalBitmap(Bitmap originalBitmap) {
-        if (mUpdatePreviewTask == null) {
-            return;
-        }
-        mUpdatePreviewTask.setOriginal(originalBitmap);
-        mHighresRenderingRequestTask.setOriginal(originalBitmap);
-        mRenderingRequestTask.setOriginal(originalBitmap);
-    }
-
-    public void updatePreviewBuffer() {
-        mHighresRenderingRequestTask.stop();
-        mUpdatePreviewTask.updatePreview();
-    }
-
-    public void postRenderingRequest(RenderingRequest request) {
-        mRenderingRequestTask.postRenderingRequest(request);
-    }
-
-    public void postHighresRenderingRequest(ImagePreset preset, float scaleFactor,
-                                            RenderingRequestCaller caller) {
-        RenderingRequest request = new RenderingRequest();
-        // TODO: use the triple buffer preset as UpdatePreviewTask does instead of creating a copy
-        ImagePreset passedPreset = new ImagePreset(preset);
-        request.setOriginalImagePreset(preset);
-        request.setScaleFactor(scaleFactor);
-        request.setImagePreset(passedPreset);
-        request.setType(RenderingRequest.HIGHRES_RENDERING);
-        request.setCaller(caller);
-        mHighresRenderingRequestTask.postRenderingRequest(request);
-    }
-
-    public void setHighresPreviewScaleFactor(float highResPreviewScale) {
-        mHighresRenderingRequestTask.setHighresPreviewScaleFactor(highResPreviewScale);
-    }
-
-    public void setPreviewScaleFactor(float previewScale) {
-        mHighresRenderingRequestTask.setPreviewScaleFactor(previewScale);
-        mRenderingRequestTask.setPreviewScaleFactor(previewScale);
-    }
-
-    public void setOriginalBitmapHighres(Bitmap originalHires) {
-        mHighresRenderingRequestTask.setOriginalBitmapHighres(originalHires);
-    }
-
-    public class LocalBinder extends Binder {
-        public ProcessingService getService() {
-            return ProcessingService.this;
-        }
-    }
-
-    public static Intent getSaveIntent(Context context, ImagePreset preset, File destination,
-            Uri selectedImageUri, Uri sourceImageUri, boolean doFlatten, int quality) {
-        Intent processIntent = new Intent(context, ProcessingService.class);
-        processIntent.putExtra(ProcessingService.SOURCE_URI,
-                sourceImageUri.toString());
-        processIntent.putExtra(ProcessingService.SELECTED_URI,
-                selectedImageUri.toString());
-        processIntent.putExtra(ProcessingService.QUALITY, quality);
-        if (destination != null) {
-            processIntent.putExtra(ProcessingService.DESTINATION_FILE, destination.toString());
-        }
-        processIntent.putExtra(ProcessingService.PRESET,
-                preset.getJsonString(context.getString(R.string.saved)));
-        processIntent.putExtra(ProcessingService.SAVING, true);
-        if (doFlatten) {
-            processIntent.putExtra(ProcessingService.FLATTEN, true);
-        }
-        return processIntent;
-    }
-
-
-    @Override
-    public void onCreate() {
-        mProcessingTaskController = new ProcessingTaskController(this);
-        mImageSavingTask = new ImageSavingTask(this);
-        mUpdatePreviewTask = new UpdatePreviewTask();
-        mHighresRenderingRequestTask = new HighresRenderingRequestTask();
-        mRenderingRequestTask = new RenderingRequestTask();
-        mProcessingTaskController.add(mImageSavingTask);
-        mProcessingTaskController.add(mUpdatePreviewTask);
-        mProcessingTaskController.add(mHighresRenderingRequestTask);
-        mProcessingTaskController.add(mRenderingRequestTask);
-        setupPipeline();
-    }
-
-    @Override
-    public void onDestroy() {
-        tearDownPipeline();
-        mProcessingTaskController.quit();
-    }
-
-    @Override
-    public int onStartCommand(Intent intent, int flags, int startId) {
-        mNeedsAlive = true;
-        if (intent != null && intent.getBooleanExtra(SAVING, false)) {
-            // we save using an intent to keep the service around after the
-            // activity has been destroyed.
-            String presetJson = intent.getStringExtra(PRESET);
-            String source = intent.getStringExtra(SOURCE_URI);
-            String selected = intent.getStringExtra(SELECTED_URI);
-            String destination = intent.getStringExtra(DESTINATION_FILE);
-            int quality = intent.getIntExtra(QUALITY, 100);
-            boolean flatten = intent.getBooleanExtra(FLATTEN, false);
-            Uri sourceUri = Uri.parse(source);
-            Uri selectedUri = null;
-            if (selected != null) {
-                selectedUri = Uri.parse(selected);
-            }
-            File destinationFile = null;
-            if (destination != null) {
-                destinationFile = new File(destination);
-            }
-            ImagePreset preset = new ImagePreset();
-            preset.readJsonFromString(presetJson);
-            mNeedsAlive = false;
-            mSaving = true;
-            handleSaveRequest(sourceUri, selectedUri, destinationFile, preset, flatten, quality);
-        }
-        return START_REDELIVER_INTENT;
-    }
-
-    @Override
-    public IBinder onBind(Intent intent) {
-        return mBinder;
-    }
-
-    public void onStart() {
-        mNeedsAlive = true;
-        if (!mSaving && mFiltershowActivity != null) {
-            mFiltershowActivity.updateUIAfterServiceStarted();
-        }
-    }
-
-    public void handleSaveRequest(Uri sourceUri, Uri selectedUri,
-            File destinationFile, ImagePreset preset, boolean flatten, int quality) {
-        mNotifyMgr = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
-
-        mNotificationId++;
-
-        mBuilder =
-                new Notification.Builder(this)
-                        .setSmallIcon(R.drawable.filtershow_button_fx)
-                        .setContentTitle(getString(R.string.filtershow_notification_label))
-                        .setContentText(getString(R.string.filtershow_notification_message));
-
-        startForeground(mNotificationId, mBuilder.build());
-
-        updateProgress(SaveImage.MAX_PROCESSING_STEPS, 0);
-
-        // Process the image
-
-        mImageSavingTask.saveImage(sourceUri, selectedUri, destinationFile,
-                preset, flatten, quality);
-    }
-
-    public void updateNotificationWithBitmap(Bitmap bitmap) {
-        mBuilder.setLargeIcon(bitmap);
-        mNotifyMgr.notify(mNotificationId, mBuilder.build());
-    }
-
-    public void updateProgress(int max, int current) {
-        mBuilder.setProgress(max, current, false);
-        mNotifyMgr.notify(mNotificationId, mBuilder.build());
-    }
-
-    public void completeSaveImage(Uri result) {
-        if (SHOW_IMAGE) {
-            // TODO: we should update the existing image in Gallery instead
-            Intent viewImage = new Intent(Intent.ACTION_VIEW, result);
-            viewImage.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
-            startActivity(viewImage);
-        }
-        stopForeground(true);
-        stopSelf();
-        if (mNeedsAlive) {
-            // If the app has been restarted while we were saving...
-            mFiltershowActivity.updateUIAfterServiceStarted();
-        } else if (mFiltershowActivity.isSimpleEditAction()) {
-            // terminate now
-            mFiltershowActivity.completeSaveImage(result);
-        }
-    }
-
-    private void setupPipeline() {
-        Resources res = getResources();
-        FiltersManager.setResources(res);
-        CachingPipeline.createRenderscriptContext(this);
-
-        FiltersManager filtersManager = FiltersManager.getManager();
-        filtersManager.addLooks(this);
-        filtersManager.addBorders(this);
-        filtersManager.addTools(this);
-        filtersManager.addEffects();
-
-        FiltersManager highresFiltersManager = FiltersManager.getHighresManager();
-        highresFiltersManager.addLooks(this);
-        highresFiltersManager.addBorders(this);
-        highresFiltersManager.addTools(this);
-        highresFiltersManager.addEffects();
-    }
-
-    private void tearDownPipeline() {
-        ImageFilter.resetStatics();
-        FiltersManager.getPreviewManager().freeRSFilterScripts();
-        FiltersManager.getManager().freeRSFilterScripts();
-        FiltersManager.getHighresManager().freeRSFilterScripts();
-        FiltersManager.reset();
-        CachingPipeline.destroyRenderScriptContext();
-    }
-
-    static {
-        System.loadLibrary("jni_filtershow_filters");
-    }
-}
diff --git a/src/com/android/gallery3d/filtershow/pipeline/ProcessingTask.java b/src/com/android/gallery3d/filtershow/pipeline/ProcessingTask.java
deleted file mode 100644
index 8d3e811..0000000
--- a/src/com/android/gallery3d/filtershow/pipeline/ProcessingTask.java
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- * Copyright (C) 2013 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.gallery3d.filtershow.pipeline;
-
-import android.content.Context;
-import android.os.Handler;
-import android.os.Message;
-
-public abstract class ProcessingTask {
-    private ProcessingTaskController mTaskController;
-    private Handler mProcessingHandler;
-    private Handler mResultHandler;
-    private int mType;
-    private static final int DELAY = 300;
-
-    static interface Request {}
-    static interface Update {}
-    static interface Result {}
-
-    public boolean postRequest(Request message) {
-        Message msg = mProcessingHandler.obtainMessage(mType);
-        msg.obj = message;
-        if (isPriorityTask()) {
-            if (mProcessingHandler.hasMessages(getType())) {
-                return false;
-            }
-            mProcessingHandler.sendMessageAtFrontOfQueue(msg);
-        } else if (isDelayedTask()) {
-            if (mProcessingHandler.hasMessages(getType())) {
-                mProcessingHandler.removeMessages(getType());
-            }
-            mProcessingHandler.sendMessageDelayed(msg, DELAY);
-        } else {
-            mProcessingHandler.sendMessage(msg);
-        }
-        return true;
-    }
-
-    public void postUpdate(Update message) {
-        Message msg = mResultHandler.obtainMessage(mType);
-        msg.obj = message;
-        msg.arg1 = ProcessingTaskController.UPDATE;
-        mResultHandler.sendMessage(msg);
-    }
-
-    public void processRequest(Request message) {
-        Object result = doInBackground(message);
-        Message msg = mResultHandler.obtainMessage(mType);
-        msg.obj = result;
-        msg.arg1 = ProcessingTaskController.RESULT;
-        mResultHandler.sendMessage(msg);
-    }
-
-    public void added(ProcessingTaskController taskController) {
-        mTaskController = taskController;
-        mResultHandler = taskController.getResultHandler();
-        mProcessingHandler = taskController.getProcessingHandler();
-        mType = taskController.getReservedType();
-    }
-
-    public int getType() {
-        return mType;
-    }
-
-    public Context getContext() {
-        return mTaskController.getContext();
-    }
-
-    public abstract Result doInBackground(Request message);
-    public abstract void onResult(Result message);
-    public void onUpdate(Update message) {}
-    public boolean isPriorityTask() { return false; }
-    public boolean isDelayedTask() { return false; }
-}
diff --git a/src/com/android/gallery3d/filtershow/pipeline/ProcessingTaskController.java b/src/com/android/gallery3d/filtershow/pipeline/ProcessingTaskController.java
deleted file mode 100644
index b54bbb0..0000000
--- a/src/com/android/gallery3d/filtershow/pipeline/ProcessingTaskController.java
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- * Copyright (C) 2013 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.gallery3d.filtershow.pipeline;
-
-import android.content.Context;
-import android.os.Handler;
-import android.os.HandlerThread;
-import android.os.Message;
-import android.util.Log;
-
-import java.util.HashMap;
-
-public class ProcessingTaskController implements Handler.Callback {
-    private static final String LOGTAG = "ProcessingTaskController";
-
-    private Context mContext;
-    private HandlerThread mHandlerThread = null;
-    private Handler mProcessingHandler = null;
-    private int mCurrentType;
-    private HashMap<Integer, ProcessingTask> mTasks = new HashMap<Integer, ProcessingTask>();
-
-    public final static int RESULT = 1;
-    public final static int UPDATE = 2;
-
-    private final Handler mResultHandler = new Handler() {
-        @Override
-        public void handleMessage(Message msg) {
-            ProcessingTask task = mTasks.get(msg.what);
-            if (task != null) {
-                if (msg.arg1 == RESULT) {
-                    task.onResult((ProcessingTask.Result) msg.obj);
-                } else if (msg.arg1 == UPDATE) {
-                    task.onUpdate((ProcessingTask.Update) msg.obj);
-                } else {
-                    Log.w(LOGTAG, "received unknown message! " + msg.arg1);
-                }
-            }
-        }
-    };
-
-    @Override
-    public boolean handleMessage(Message msg) {
-        ProcessingTask task = mTasks.get(msg.what);
-        if (task != null) {
-            task.processRequest((ProcessingTask.Request) msg.obj);
-            return true;
-        }
-        return false;
-    }
-
-    public ProcessingTaskController(Context context) {
-        mContext = context;
-        mHandlerThread = new HandlerThread("ProcessingTaskController",
-                android.os.Process.THREAD_PRIORITY_FOREGROUND);
-        mHandlerThread.start();
-        mProcessingHandler = new Handler(mHandlerThread.getLooper(), this);
-    }
-
-    public Handler getProcessingHandler() {
-        return mProcessingHandler;
-    }
-
-    public Handler getResultHandler() {
-        return mResultHandler;
-    }
-
-    public int getReservedType() {
-        return mCurrentType++;
-    }
-
-    public Context getContext() {
-        return mContext;
-    }
-
-    public void add(ProcessingTask task) {
-        task.added(this);
-        mTasks.put(task.getType(), task);
-    }
-
-    public void quit() {
-        mHandlerThread.quit();
-    }
-}
diff --git a/src/com/android/gallery3d/filtershow/pipeline/RenderingRequest.java b/src/com/android/gallery3d/filtershow/pipeline/RenderingRequest.java
deleted file mode 100644
index ef4bb9b..0000000
--- a/src/com/android/gallery3d/filtershow/pipeline/RenderingRequest.java
+++ /dev/null
@@ -1,174 +0,0 @@
-/*
- * Copyright (C) 2013 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.gallery3d.filtershow.pipeline;
-
-import android.content.Context;
-import android.graphics.Bitmap;
-import android.graphics.Rect;
-import com.android.gallery3d.app.Log;
-import com.android.gallery3d.filtershow.FilterShowActivity;
-import com.android.gallery3d.filtershow.filters.FiltersManager;
-import com.android.gallery3d.filtershow.imageshow.MasterImage;
-
-public class RenderingRequest {
-    private static final String LOGTAG = "RenderingRequest";
-    private boolean mIsDirect = false;
-    private Bitmap mBitmap = null;
-    private ImagePreset mImagePreset = null;
-    private ImagePreset mOriginalImagePreset = null;
-    private RenderingRequestCaller mCaller = null;
-    private float mScaleFactor = 1.0f;
-    private Rect mBounds = null;
-    private Rect mDestination = null;
-    private int mType = FULL_RENDERING;
-    public static final int FULL_RENDERING = 0;
-    public static final int FILTERS_RENDERING = 1;
-    public static final int GEOMETRY_RENDERING = 2;
-    public static final int ICON_RENDERING = 3;
-    public static final int PARTIAL_RENDERING = 4;
-    public static final int HIGHRES_RENDERING = 5;
-    public static final int STYLE_ICON_RENDERING = 6;
-
-    private static final Bitmap.Config mConfig = Bitmap.Config.ARGB_8888;
-
-    public static void post(Context context, Bitmap source, ImagePreset preset,
-                            int type, RenderingRequestCaller caller) {
-        RenderingRequest.post(context, source, preset, type, caller, null, null);
-    }
-
-    public static void post(Context context, Bitmap source, ImagePreset preset, int type,
-                            RenderingRequestCaller caller, Rect bounds, Rect destination) {
-        if (((type != PARTIAL_RENDERING && type != HIGHRES_RENDERING) && source == null)
-                || preset == null || caller == null) {
-            Log.v(LOGTAG, "something null: source: " + source
-                    + " or preset: " + preset + " or caller: " + caller);
-            return;
-        }
-        RenderingRequest request = new RenderingRequest();
-        Bitmap bitmap = null;
-        if (type == FULL_RENDERING
-                || type == GEOMETRY_RENDERING
-                || type == ICON_RENDERING
-                || type == STYLE_ICON_RENDERING) {
-            CachingPipeline pipeline = new CachingPipeline(
-                    FiltersManager.getManager(), "Icon");
-            bitmap = pipeline.renderGeometryIcon(source, preset);
-        } else if (type != PARTIAL_RENDERING && type != HIGHRES_RENDERING) {
-            bitmap = Bitmap.createBitmap(source.getWidth(), source.getHeight(), mConfig);
-        }
-
-        request.setBitmap(bitmap);
-        ImagePreset passedPreset = new ImagePreset(preset);
-        request.setOriginalImagePreset(preset);
-        request.setScaleFactor(MasterImage.getImage().getScaleFactor());
-
-        if (type == PARTIAL_RENDERING) {
-            request.setBounds(bounds);
-            request.setDestination(destination);
-            passedPreset.setPartialRendering(true, bounds);
-        }
-
-        request.setImagePreset(passedPreset);
-        request.setType(type);
-        request.setCaller(caller);
-        request.post(context);
-    }
-
-    public void post(Context context) {
-        if (context instanceof FilterShowActivity) {
-            FilterShowActivity activity = (FilterShowActivity) context;
-            ProcessingService service = activity.getProcessingService();
-            service.postRenderingRequest(this);
-        }
-    }
-
-    public void markAvailable() {
-        if (mBitmap == null || mImagePreset == null
-                || mCaller == null) {
-            return;
-        }
-        mCaller.available(this);
-    }
-
-    public boolean isDirect() {
-        return mIsDirect;
-    }
-
-    public void setDirect(boolean isDirect) {
-        mIsDirect = isDirect;
-    }
-
-    public Bitmap getBitmap() {
-        return mBitmap;
-    }
-
-    public void setBitmap(Bitmap bitmap) {
-        mBitmap = bitmap;
-    }
-
-    public ImagePreset getImagePreset() {
-        return mImagePreset;
-    }
-
-    public void setImagePreset(ImagePreset imagePreset) {
-        mImagePreset = imagePreset;
-    }
-
-    public int getType() {
-        return mType;
-    }
-
-    public void setType(int type) {
-        mType = type;
-    }
-
-    public void setCaller(RenderingRequestCaller caller) {
-        mCaller = caller;
-    }
-
-    public Rect getBounds() {
-        return mBounds;
-    }
-
-    public void setBounds(Rect bounds) {
-        mBounds = bounds;
-    }
-
-    public void setScaleFactor(float scaleFactor) {
-        mScaleFactor = scaleFactor;
-    }
-
-    public float getScaleFactor() {
-        return mScaleFactor;
-    }
-
-    public Rect getDestination() {
-        return mDestination;
-    }
-
-    public void setDestination(Rect destination) {
-        mDestination = destination;
-    }
-
-    public ImagePreset getOriginalImagePreset() {
-        return mOriginalImagePreset;
-    }
-
-    public void setOriginalImagePreset(ImagePreset originalImagePreset) {
-        mOriginalImagePreset = originalImagePreset;
-    }
-}
diff --git a/src/com/android/gallery3d/filtershow/pipeline/RenderingRequestCaller.java b/src/com/android/gallery3d/filtershow/pipeline/RenderingRequestCaller.java
deleted file mode 100644
index b978e70..0000000
--- a/src/com/android/gallery3d/filtershow/pipeline/RenderingRequestCaller.java
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- * Copyright (C) 2013 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.gallery3d.filtershow.pipeline;
-
-public interface RenderingRequestCaller {
-    public void available(RenderingRequest request);
-}
diff --git a/src/com/android/gallery3d/filtershow/pipeline/RenderingRequestTask.java b/src/com/android/gallery3d/filtershow/pipeline/RenderingRequestTask.java
deleted file mode 100644
index 7a83f70..0000000
--- a/src/com/android/gallery3d/filtershow/pipeline/RenderingRequestTask.java
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * Copyright (C) 2013 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.gallery3d.filtershow.pipeline;
-
-import android.graphics.Bitmap;
-import com.android.gallery3d.filtershow.filters.FiltersManager;
-
-public class RenderingRequestTask extends ProcessingTask {
-
-    private CachingPipeline mPreviewPipeline = null;
-    private boolean mPipelineIsOn = false;
-
-    public void setPreviewScaleFactor(float previewScale) {
-        mPreviewPipeline.setPreviewScaleFactor(previewScale);
-    }
-
-    static class Render implements Request {
-        RenderingRequest request;
-    }
-
-    static class RenderResult implements Result {
-        RenderingRequest request;
-    }
-
-    public RenderingRequestTask() {
-        mPreviewPipeline = new CachingPipeline(
-                FiltersManager.getManager(), "Normal");
-    }
-
-    public void setOriginal(Bitmap bitmap) {
-        mPreviewPipeline.setOriginal(bitmap);
-        mPipelineIsOn = true;
-    }
-
-    public void stop() {
-        mPreviewPipeline.stop();
-    }
-
-    public void postRenderingRequest(RenderingRequest request) {
-        if (!mPipelineIsOn) {
-            return;
-        }
-        Render render = new Render();
-        render.request = request;
-        postRequest(render);
-    }
-
-    @Override
-    public Result doInBackground(Request message) {
-        RenderingRequest request = ((Render) message).request;
-        RenderResult result = null;
-        mPreviewPipeline.render(request);
-        result = new RenderResult();
-        result.request = request;
-        return result;
-    }
-
-    @Override
-    public void onResult(Result message) {
-        if (message == null) {
-            return;
-        }
-        RenderingRequest request = ((RenderResult) message).request;
-        request.markAvailable();
-    }
-
-}
diff --git a/src/com/android/gallery3d/filtershow/pipeline/SharedBuffer.java b/src/com/android/gallery3d/filtershow/pipeline/SharedBuffer.java
deleted file mode 100644
index 98e69f6..0000000
--- a/src/com/android/gallery3d/filtershow/pipeline/SharedBuffer.java
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * Copyright (C) 2013 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.gallery3d.filtershow.pipeline;
-
-import android.graphics.Bitmap;
-
-public class SharedBuffer {
-
-    private static final String LOGTAG = "SharedBuffer";
-
-    private volatile Buffer mProducer = null;
-    private volatile Buffer mConsumer = null;
-    private volatile Buffer mIntermediate = null;
-
-    private volatile boolean mNeedsSwap = false;
-    private volatile boolean mNeedsRepaint = true;
-
-    public void setProducer(Bitmap producer) {
-        Buffer buffer = new Buffer(producer);
-        synchronized (this) {
-            mProducer = buffer;
-        }
-    }
-
-    public synchronized Buffer getProducer() {
-        return mProducer;
-    }
-
-    public synchronized Buffer getConsumer() {
-        return mConsumer;
-    }
-
-    public synchronized void swapProducer() {
-        Buffer intermediate = mIntermediate;
-        mIntermediate = mProducer;
-        mProducer = intermediate;
-        mNeedsSwap = true;
-    }
-
-    public synchronized void swapConsumerIfNeeded() {
-        if (!mNeedsSwap) {
-            return;
-        }
-        Buffer intermediate = mIntermediate;
-        mIntermediate = mConsumer;
-        mConsumer = intermediate;
-        mNeedsSwap = false;
-    }
-
-    public synchronized void invalidate() {
-        mNeedsRepaint = true;
-    }
-
-    public synchronized boolean checkRepaintNeeded() {
-        if (mNeedsRepaint) {
-            mNeedsRepaint = false;
-            return true;
-        }
-        return false;
-    }
-
-}
-
diff --git a/src/com/android/gallery3d/filtershow/pipeline/SharedPreset.java b/src/com/android/gallery3d/filtershow/pipeline/SharedPreset.java
deleted file mode 100644
index 3f850fe..0000000
--- a/src/com/android/gallery3d/filtershow/pipeline/SharedPreset.java
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Copyright (C) 2013 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.gallery3d.filtershow.pipeline;
-
-public class SharedPreset {
-
-    private volatile ImagePreset mProducerPreset = null;
-    private volatile ImagePreset mConsumerPreset = null;
-    private volatile ImagePreset mIntermediatePreset = null;
-
-    public synchronized void enqueuePreset(ImagePreset preset) {
-        if (mProducerPreset == null || (!mProducerPreset.same(preset))) {
-            mProducerPreset = new ImagePreset(preset);
-        } else {
-            mProducerPreset.updateWith(preset);
-        }
-        ImagePreset temp = mIntermediatePreset;
-        mIntermediatePreset = mProducerPreset;
-        mProducerPreset = temp;
-    }
-
-    public synchronized ImagePreset dequeuePreset() {
-        ImagePreset temp = mConsumerPreset;
-        mConsumerPreset = mIntermediatePreset;
-        mIntermediatePreset = temp;
-        return mConsumerPreset;
-    }
-}
diff --git a/src/com/android/gallery3d/filtershow/pipeline/UpdatePreviewTask.java b/src/com/android/gallery3d/filtershow/pipeline/UpdatePreviewTask.java
deleted file mode 100644
index 406cc9b..0000000
--- a/src/com/android/gallery3d/filtershow/pipeline/UpdatePreviewTask.java
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * Copyright (C) 2013 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.gallery3d.filtershow.pipeline;
-
-import android.graphics.Bitmap;
-import com.android.gallery3d.filtershow.filters.FiltersManager;
-import com.android.gallery3d.filtershow.imageshow.MasterImage;
-
-public class UpdatePreviewTask extends ProcessingTask {
-    private CachingPipeline mPreviewPipeline = null;
-    private boolean mHasUnhandledPreviewRequest = false;
-    private boolean mPipelineIsOn = false;
-
-    public UpdatePreviewTask() {
-        mPreviewPipeline = new CachingPipeline(
-                FiltersManager.getPreviewManager(), "Preview");
-    }
-
-    public void setOriginal(Bitmap bitmap) {
-        mPreviewPipeline.setOriginal(bitmap);
-        mPipelineIsOn = true;
-    }
-
-    public void updatePreview() {
-        if (!mPipelineIsOn) {
-            return;
-        }
-        mHasUnhandledPreviewRequest = true;
-        if (postRequest(null)) {
-            mHasUnhandledPreviewRequest = false;
-        }
-    }
-
-    @Override
-    public boolean isPriorityTask() {
-        return true;
-    }
-
-    @Override
-    public Result doInBackground(Request message) {
-        SharedBuffer buffer = MasterImage.getImage().getPreviewBuffer();
-        SharedPreset preset = MasterImage.getImage().getPreviewPreset();
-        ImagePreset renderingPreset = preset.dequeuePreset();
-        if (renderingPreset != null) {
-            mPreviewPipeline.compute(buffer, renderingPreset, 0);
-            // set the preset we used in the buffer for later inspection UI-side
-            buffer.getProducer().setPreset(renderingPreset);
-            buffer.getProducer().sync();
-            buffer.swapProducer(); // push back the result
-        }
-        return null;
-    }
-
-    @Override
-    public void onResult(Result message) {
-        MasterImage.getImage().notifyObservers();
-        if (mHasUnhandledPreviewRequest) {
-            updatePreview();
-        }
-    }
-
-    public void setPipelineIsOn(boolean pipelineIsOn) {
-        mPipelineIsOn = pipelineIsOn;
-    }
-}
diff --git a/src/com/android/gallery3d/filtershow/presets/PresetManagementDialog.java b/src/com/android/gallery3d/filtershow/presets/PresetManagementDialog.java
deleted file mode 100644
index 7ab61fc..0000000
--- a/src/com/android/gallery3d/filtershow/presets/PresetManagementDialog.java
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * Copyright (C) 2013 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.gallery3d.filtershow.presets;
-
-import android.os.Bundle;
-import android.support.v4.app.DialogFragment;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.ListView;
-import com.android.gallery3d.R;
-import com.android.gallery3d.filtershow.FilterShowActivity;
-
-public class PresetManagementDialog extends DialogFragment implements View.OnClickListener {
-    private UserPresetsAdapter mAdapter;
-
-    @Override
-    public View onCreateView(LayoutInflater inflater, ViewGroup container,
-                             Bundle savedInstanceState) {
-        View view = inflater.inflate(R.layout.filtershow_presets_management_dialog, container);
-
-        FilterShowActivity activity = (FilterShowActivity) getActivity();
-        mAdapter = activity.getUserPresetsAdapter();
-        ListView panel = (ListView) view.findViewById(R.id.listItems);
-        panel.setAdapter(mAdapter);
-
-        view.findViewById(R.id.cancel).setOnClickListener(this);
-        view.findViewById(R.id.addpreset).setOnClickListener(this);
-        view.findViewById(R.id.ok).setOnClickListener(this);
-        getDialog().setTitle(getString(R.string.filtershow_manage_preset));
-        return view;
-    }
-
-    @Override
-    public void onClick(View v) {
-        FilterShowActivity activity = (FilterShowActivity) getActivity();
-        switch (v.getId()) {
-            case R.id.cancel:
-                mAdapter.clearChangedRepresentations();
-                mAdapter.clearDeletedRepresentations();
-                activity.updateUserPresetsFromAdapter(mAdapter);
-                dismiss();
-                break;
-            case R.id.addpreset:
-                activity.saveCurrentImagePreset();
-                dismiss();
-                break;
-            case R.id.ok:
-                mAdapter.updateCurrent();
-                activity.updateUserPresetsFromAdapter(mAdapter);
-                dismiss();
-                break;
-        }
-    }
-}
diff --git a/src/com/android/gallery3d/filtershow/presets/UserPresetsAdapter.java b/src/com/android/gallery3d/filtershow/presets/UserPresetsAdapter.java
deleted file mode 100644
index dab9ea4..0000000
--- a/src/com/android/gallery3d/filtershow/presets/UserPresetsAdapter.java
+++ /dev/null
@@ -1,171 +0,0 @@
-/*
- * Copyright (C) 2013 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.gallery3d.filtershow.presets;
-
-import android.content.Context;
-import android.graphics.Rect;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.ArrayAdapter;
-import android.widget.EditText;
-import android.widget.ImageButton;
-import android.widget.ImageView;
-import com.android.gallery3d.R;
-import com.android.gallery3d.filtershow.category.Action;
-import com.android.gallery3d.filtershow.category.CategoryView;
-import com.android.gallery3d.filtershow.filters.FilterRepresentation;
-import com.android.gallery3d.filtershow.filters.FilterUserPresetRepresentation;
-
-import java.util.ArrayList;
-
-public class UserPresetsAdapter extends ArrayAdapter<Action>
-        implements View.OnClickListener, View.OnFocusChangeListener {
-    private static final String LOGTAG = "UserPresetsAdapter";
-    private LayoutInflater mInflater;
-    private int mIconSize = 160;
-    private ArrayList<FilterUserPresetRepresentation> mDeletedRepresentations =
-            new ArrayList<FilterUserPresetRepresentation>();
-    private ArrayList<FilterUserPresetRepresentation> mChangedRepresentations =
-            new ArrayList<FilterUserPresetRepresentation>();
-    private EditText mCurrentEditText;
-
-    public UserPresetsAdapter(Context context, int textViewResourceId) {
-        super(context, textViewResourceId);
-        mInflater = LayoutInflater.from(context);
-        mIconSize = context.getResources().getDimensionPixelSize(R.dimen.category_panel_icon_size);
-    }
-
-    public UserPresetsAdapter(Context context) {
-        this(context, 0);
-    }
-
-    @Override
-    public void add(Action action) {
-        super.add(action);
-        action.setAdapter(this);
-    }
-
-    private void deletePreset(Action action) {
-        FilterRepresentation rep = action.getRepresentation();
-        if (rep instanceof FilterUserPresetRepresentation) {
-            mDeletedRepresentations.add((FilterUserPresetRepresentation) rep);
-        }
-        remove(action);
-        notifyDataSetChanged();
-    }
-
-    private void changePreset(Action action) {
-        FilterRepresentation rep = action.getRepresentation();
-        rep.setName(action.getName());
-        if (rep instanceof FilterUserPresetRepresentation) {
-            mChangedRepresentations.add((FilterUserPresetRepresentation) rep);
-        }
-    }
-
-    public void updateCurrent() {
-        if (mCurrentEditText != null) {
-            updateActionFromEditText(mCurrentEditText);
-        }
-    }
-
-    static class UserPresetViewHolder {
-        ImageView imageView;
-        EditText editText;
-        ImageButton deleteButton;
-    }
-
-    @Override
-    public View getView(int position, View convertView, ViewGroup parent) {
-        UserPresetViewHolder viewHolder;
-        if (convertView == null) {
-            convertView = mInflater.inflate(R.layout.filtershow_presets_management_row, null);
-            viewHolder = new UserPresetViewHolder();
-            viewHolder.imageView = (ImageView) convertView.findViewById(R.id.imageView);
-            viewHolder.editText = (EditText) convertView.findViewById(R.id.editView);
-            viewHolder.deleteButton = (ImageButton) convertView.findViewById(R.id.deleteUserPreset);
-            viewHolder.editText.setOnClickListener(this);
-            viewHolder.editText.setOnFocusChangeListener(this);
-            viewHolder.deleteButton.setOnClickListener(this);
-            convertView.setTag(viewHolder);
-        } else {
-            viewHolder = (UserPresetViewHolder) convertView.getTag();
-        }
-        Action action = getItem(position);
-        viewHolder.imageView.setImageBitmap(action.getImage());
-        if (action.getImage() == null) {
-            // queue image rendering for this action
-            action.setImageFrame(new Rect(0, 0, mIconSize, mIconSize), CategoryView.VERTICAL);
-        }
-        viewHolder.deleteButton.setTag(action);
-        viewHolder.editText.setTag(action);
-        viewHolder.editText.setHint(action.getName());
-
-        return convertView;
-    }
-
-    public ArrayList<FilterUserPresetRepresentation> getDeletedRepresentations() {
-        return mDeletedRepresentations;
-    }
-
-    public void clearDeletedRepresentations() {
-        mDeletedRepresentations.clear();
-    }
-
-    public ArrayList<FilterUserPresetRepresentation> getChangedRepresentations() {
-        return mChangedRepresentations;
-    }
-
-    public void clearChangedRepresentations() {
-        mChangedRepresentations.clear();
-    }
-
-    @Override
-    public void onClick(View v) {
-        switch (v.getId()) {
-            case R.id.editView:
-                v.requestFocus();
-                break;
-            case R.id.deleteUserPreset:
-                Action action = (Action) v.getTag();
-                deletePreset(action);
-                break;
-        }
-    }
-
-    @Override
-    public void onFocusChange(View v, boolean hasFocus) {
-        if (v.getId() != R.id.editView) {
-            return;
-        }
-        EditText editText = (EditText) v;
-        if (!hasFocus) {
-            updateActionFromEditText(editText);
-        } else {
-            mCurrentEditText = editText;
-        }
-    }
-
-    private void updateActionFromEditText(EditText editText) {
-        Action action = (Action) editText.getTag();
-        String newName = editText.getText().toString();
-        if (newName.length() > 0) {
-            action.setName(editText.getText().toString());
-            changePreset(action);
-        }
-    }
-}
diff --git a/src/com/android/gallery3d/filtershow/provider/SharedImageProvider.java b/src/com/android/gallery3d/filtershow/provider/SharedImageProvider.java
deleted file mode 100644
index bc17a6e..0000000
--- a/src/com/android/gallery3d/filtershow/provider/SharedImageProvider.java
+++ /dev/null
@@ -1,137 +0,0 @@
-/*
- * 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.gallery3d.filtershow.provider;
-
-import android.content.ContentProvider;
-import android.content.ContentValues;
-import android.database.Cursor;
-import android.database.MatrixCursor;
-import android.net.Uri;
-import android.os.ConditionVariable;
-import android.os.ParcelFileDescriptor;
-import android.provider.BaseColumns;
-import android.provider.MediaStore;
-import android.provider.OpenableColumns;
-
-import java.io.File;
-import java.io.FileNotFoundException;
-
-public class SharedImageProvider extends ContentProvider {
-
-    private static final String LOGTAG = "SharedImageProvider";
-
-    public static final String MIME_TYPE = "image/jpeg";
-    public static final String AUTHORITY = "com.android.gallery3d.filtershow.provider.SharedImageProvider";
-    public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY + "/image");
-    public static final String PREPARE = "prepare";
-
-    private final String[] mMimeStreamType = {
-            MIME_TYPE
-    };
-
-    private static ConditionVariable mImageReadyCond = new ConditionVariable(false);
-
-    @Override
-    public int delete(Uri arg0, String arg1, String[] arg2) {
-        return 0;
-    }
-
-    @Override
-    public String getType(Uri arg0) {
-        return MIME_TYPE;
-    }
-
-    @Override
-    public String[] getStreamTypes(Uri arg0, String mimeTypeFilter) {
-        return mMimeStreamType;
-    }
-
-    @Override
-    public Uri insert(Uri uri, ContentValues values) {
-        if (values.containsKey(PREPARE)) {
-            if (values.getAsBoolean(PREPARE)) {
-                mImageReadyCond.close();
-            } else {
-                mImageReadyCond.open();
-            }
-        }
-        return null;
-    }
-
-    @Override
-    public int update(Uri arg0, ContentValues arg1, String arg2, String[] arg3) {
-        return 0;
-    }
-
-    @Override
-    public boolean onCreate() {
-        return true;
-    }
-
-    @Override
-    public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
-        String uriPath = uri.getLastPathSegment();
-        if (uriPath == null) {
-            return null;
-        }
-        if (projection == null) {
-            projection = new String[] {
-                    BaseColumns._ID,
-                    MediaStore.MediaColumns.DATA,
-                    OpenableColumns.DISPLAY_NAME,
-                    OpenableColumns.SIZE
-            };
-        }
-        // If we receive a query on display name or size,
-        // we should block until the image is ready
-        mImageReadyCond.block();
-
-        File path = new File(uriPath);
-
-        MatrixCursor cursor = new MatrixCursor(projection);
-        Object[] columns = new Object[projection.length];
-        for (int i = 0; i < projection.length; i++) {
-            if (projection[i].equalsIgnoreCase(BaseColumns._ID)) {
-                columns[i] = 0;
-            } else if (projection[i].equalsIgnoreCase(MediaStore.MediaColumns.DATA)) {
-                columns[i] = uri;
-            } else if (projection[i].equalsIgnoreCase(OpenableColumns.DISPLAY_NAME)) {
-                columns[i] = path.getName();
-            } else if (projection[i].equalsIgnoreCase(OpenableColumns.SIZE)) {
-                columns[i] = path.length();
-            }
-        }
-        cursor.addRow(columns);
-
-        return cursor;
-    }
-
-    @Override
-    public ParcelFileDescriptor openFile(Uri uri, String mode)
-            throws FileNotFoundException {
-        String uriPath = uri.getLastPathSegment();
-        if (uriPath == null) {
-            return null;
-        }
-        // Here we need to block until the image is ready
-        mImageReadyCond.block();
-        File path = new File(uriPath);
-        int imode = 0;
-        imode |= ParcelFileDescriptor.MODE_READ_ONLY;
-        return ParcelFileDescriptor.open(path, imode);
-    }
-}
diff --git a/src/com/android/gallery3d/filtershow/state/DragListener.java b/src/com/android/gallery3d/filtershow/state/DragListener.java
deleted file mode 100644
index 1aa81ed..0000000
--- a/src/com/android/gallery3d/filtershow/state/DragListener.java
+++ /dev/null
@@ -1,110 +0,0 @@
-/*
- * Copyright (C) 2013 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.gallery3d.filtershow.state;
-
-import android.view.DragEvent;
-import android.view.View;
-import android.widget.ArrayAdapter;
-import android.widget.LinearLayout;
-
-class DragListener implements View.OnDragListener {
-
-    private static final String LOGTAG = "DragListener";
-    private PanelTrack mStatePanelTrack;
-    private static float sSlope = 0.2f;
-
-    public DragListener(PanelTrack statePanelTrack) {
-        mStatePanelTrack = statePanelTrack;
-    }
-
-    private void setState(DragEvent event) {
-        float translation = event.getY() - mStatePanelTrack.getTouchPoint().y;
-        float alpha = 1.0f - (Math.abs(translation)
-                / mStatePanelTrack.getCurrentView().getHeight());
-        if (mStatePanelTrack.getOrientation() == LinearLayout.VERTICAL) {
-            translation = event.getX() - mStatePanelTrack.getTouchPoint().x;
-            alpha = 1.0f - (Math.abs(translation)
-                    / mStatePanelTrack.getCurrentView().getWidth());
-            mStatePanelTrack.getCurrentView().setTranslationX(translation);
-        } else {
-            mStatePanelTrack.getCurrentView().setTranslationY(translation);
-        }
-        mStatePanelTrack.getCurrentView().setBackgroundAlpha(alpha);
-    }
-
-    @Override
-    public boolean onDrag(View v, DragEvent event) {
-        switch (event.getAction()) {
-            case DragEvent.ACTION_DRAG_STARTED: {
-                break;
-            }
-            case DragEvent.ACTION_DRAG_LOCATION: {
-                if (mStatePanelTrack.getCurrentView() != null) {
-                    setState(event);
-                    View over = mStatePanelTrack.findChildAt((int) event.getX(),
-                                                             (int) event.getY());
-                    if (over != null && over != mStatePanelTrack.getCurrentView()) {
-                        StateView stateView = (StateView) over;
-                        if (stateView != mStatePanelTrack.getCurrentView()) {
-                            int pos = mStatePanelTrack.findChild(over);
-                            int origin = mStatePanelTrack.findChild(
-                                    mStatePanelTrack.getCurrentView());
-                            ArrayAdapter array = (ArrayAdapter) mStatePanelTrack.getAdapter();
-                            if (origin != -1 && pos != -1) {
-                                State current = (State) array.getItem(origin);
-                                array.remove(current);
-                                array.insert(current, pos);
-                                mStatePanelTrack.fillContent(false);
-                                mStatePanelTrack.setCurrentView(mStatePanelTrack.getChildAt(pos));
-                            }
-                        }
-                    }
-                }
-                break;
-            }
-            case DragEvent.ACTION_DRAG_ENTERED: {
-                mStatePanelTrack.setExited(false);
-                if (mStatePanelTrack.getCurrentView() != null) {
-                    mStatePanelTrack.getCurrentView().setVisibility(View.VISIBLE);
-                }
-                return true;
-            }
-            case DragEvent.ACTION_DRAG_EXITED: {
-                if (mStatePanelTrack.getCurrentView() != null) {
-                    setState(event);
-                    mStatePanelTrack.getCurrentView().setVisibility(View.INVISIBLE);
-                }
-                mStatePanelTrack.setExited(true);
-                break;
-            }
-            case DragEvent.ACTION_DROP: {
-                break;
-            }
-            case DragEvent.ACTION_DRAG_ENDED: {
-                if (mStatePanelTrack.getCurrentView() != null
-                        && mStatePanelTrack.getCurrentView().getAlpha() > sSlope) {
-                    setState(event);
-                }
-                mStatePanelTrack.checkEndState();
-                break;
-            }
-            default:
-                break;
-        }
-        return true;
-    }
-}
diff --git a/src/com/android/gallery3d/filtershow/state/PanelTrack.java b/src/com/android/gallery3d/filtershow/state/PanelTrack.java
deleted file mode 100644
index d02207d..0000000
--- a/src/com/android/gallery3d/filtershow/state/PanelTrack.java
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright (C) 2013 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.gallery3d.filtershow.state;
-
-import android.graphics.Point;
-import android.view.MotionEvent;
-import android.view.View;
-import android.widget.Adapter;
-
-public interface PanelTrack {
-    public int getOrientation();
-    public void onTouch(MotionEvent event, StateView view);
-    public StateView getCurrentView();
-    public void setCurrentView(View view);
-    public Point getTouchPoint();
-    public View findChildAt(int x, int y);
-    public int findChild(View view);
-    public Adapter getAdapter();
-    public void fillContent(boolean value);
-    public View getChildAt(int pos);
-    public void setExited(boolean value);
-    public void checkEndState();
-}
diff --git a/src/com/android/gallery3d/filtershow/state/State.java b/src/com/android/gallery3d/filtershow/state/State.java
deleted file mode 100644
index e7dedd6..0000000
--- a/src/com/android/gallery3d/filtershow/state/State.java
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * Copyright (C) 2013 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.gallery3d.filtershow.state;
-
-import com.android.gallery3d.filtershow.filters.FilterFxRepresentation;
-import com.android.gallery3d.filtershow.filters.FilterRepresentation;
-
-public class State {
-    private String mText;
-    private int mType;
-    private FilterRepresentation mFilterRepresentation;
-
-    public State(State state) {
-        this(state.getText(), state.getType());
-    }
-
-    public State(String text) {
-       this(text, StateView.DEFAULT);
-    }
-
-    public State(String text, int type) {
-        mText = text;
-        mType = type;
-    }
-
-    public boolean equals(State state) {
-        if (mFilterRepresentation.getFilterClass()
-                != state.mFilterRepresentation.getFilterClass()) {
-            return false;
-        }
-        if (mFilterRepresentation instanceof FilterFxRepresentation) {
-            return mFilterRepresentation.equals(state.getFilterRepresentation());
-        }
-        return true;
-    }
-
-    public boolean isDraggable() {
-        return mFilterRepresentation != null;
-    }
-
-    String getText() {
-        return mText;
-    }
-
-    void setText(String text) {
-        mText = text;
-    }
-
-    int getType() {
-        return mType;
-    }
-
-    void setType(int type) {
-        mType = type;
-    }
-
-    public FilterRepresentation getFilterRepresentation() {
-        return mFilterRepresentation;
-    }
-
-    public void setFilterRepresentation(FilterRepresentation filterRepresentation) {
-        mFilterRepresentation = filterRepresentation;
-    }
-}
diff --git a/src/com/android/gallery3d/filtershow/state/StateAdapter.java b/src/com/android/gallery3d/filtershow/state/StateAdapter.java
deleted file mode 100644
index 5225852..0000000
--- a/src/com/android/gallery3d/filtershow/state/StateAdapter.java
+++ /dev/null
@@ -1,115 +0,0 @@
-/*
- * Copyright (C) 2013 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.gallery3d.filtershow.state;
-
-import android.content.Context;
-import android.util.Log;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.ArrayAdapter;
-import com.android.gallery3d.R;
-import com.android.gallery3d.filtershow.FilterShowActivity;
-import com.android.gallery3d.filtershow.editors.ImageOnlyEditor;
-import com.android.gallery3d.filtershow.filters.FilterRepresentation;
-import com.android.gallery3d.filtershow.imageshow.MasterImage;
-
-import java.util.Vector;
-
-public class StateAdapter extends ArrayAdapter<State> {
-
-    private static final String LOGTAG = "StateAdapter";
-    private int mOrientation;
-    private String mOriginalText;
-    private String mResultText;
-
-    public StateAdapter(Context context, int textViewResourceId) {
-        super(context, textViewResourceId);
-        mOriginalText = context.getString(R.string.state_panel_original);
-        mResultText = context.getString(R.string.state_panel_result);
-    }
-
-    @Override
-    public View getView(int position, View convertView, ViewGroup parent) {
-        StateView view = null;
-        if (convertView == null) {
-            convertView = new StateView(getContext());
-        }
-        view = (StateView) convertView;
-        State state = getItem(position);
-        view.setState(state);
-        view.setOrientation(mOrientation);
-        FilterRepresentation currentRep = MasterImage.getImage().getCurrentFilterRepresentation();
-        FilterRepresentation stateRep = state.getFilterRepresentation();
-        if (currentRep != null && stateRep != null
-            && currentRep.getFilterClass() == stateRep.getFilterClass()
-            && currentRep.getEditorId() != ImageOnlyEditor.ID) {
-            view.setSelected(true);
-        } else {
-            view.setSelected(false);
-        }
-        return view;
-    }
-
-    public boolean contains(State state) {
-        for (int i = 0; i < getCount(); i++) {
-            if (state == getItem(i)) {
-                return true;
-            }
-        }
-        return false;
-    }
-
-    public void setOrientation(int orientation) {
-        mOrientation = orientation;
-    }
-
-    public void addOriginal() {
-        add(new State(mOriginalText));
-    }
-
-    public boolean same(Vector<State> states) {
-        // we have the original state in addition
-        if (states.size() + 1 != getCount()) {
-            return false;
-        }
-        for (int i = 1; i < getCount(); i++) {
-            State state = getItem(i);
-            if (!state.equals(states.elementAt(i-1))) {
-                return false;
-            }
-        }
-        return true;
-    }
-
-    public void fill(Vector<State> states) {
-        if (same(states)) {
-            return;
-        }
-        clear();
-        addOriginal();
-        addAll(states);
-        notifyDataSetChanged();
-    }
-
-    @Override
-    public void remove(State state) {
-        super.remove(state);
-        FilterRepresentation filterRepresentation = state.getFilterRepresentation();
-        FilterShowActivity activity = (FilterShowActivity) getContext();
-        activity.removeFilterRepresentation(filterRepresentation);
-    }
-}
diff --git a/src/com/android/gallery3d/filtershow/state/StatePanel.java b/src/com/android/gallery3d/filtershow/state/StatePanel.java
deleted file mode 100644
index df470f2..0000000
--- a/src/com/android/gallery3d/filtershow/state/StatePanel.java
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Copyright (C) 2013 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.gallery3d.filtershow.state;
-
-import android.os.Bundle;
-import android.support.v4.app.Fragment;
-import android.util.Log;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.LinearLayout;
-import com.android.gallery3d.R;
-import com.android.gallery3d.filtershow.imageshow.MasterImage;
-
-public class StatePanel extends Fragment {
-    private static final String LOGTAG = "StatePanel";
-    private StatePanelTrack track;
-    private LinearLayout mMainView;
-    public static final String FRAGMENT_TAG = "StatePanel";
-
-    @Override
-    public View onCreateView(LayoutInflater inflater, ViewGroup container,
-                             Bundle savedInstanceState) {
-        mMainView = (LinearLayout) inflater.inflate(R.layout.filtershow_state_panel_new, null);
-        View panel = mMainView.findViewById(R.id.listStates);
-        track = (StatePanelTrack) panel;
-        track.setAdapter(MasterImage.getImage().getState());
-        return mMainView;
-    }
-}
diff --git a/src/com/android/gallery3d/filtershow/state/StatePanelTrack.java b/src/com/android/gallery3d/filtershow/state/StatePanelTrack.java
deleted file mode 100644
index fff7e7f..0000000
--- a/src/com/android/gallery3d/filtershow/state/StatePanelTrack.java
+++ /dev/null
@@ -1,351 +0,0 @@
-/*
- * Copyright (C) 2013 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.gallery3d.filtershow.state;
-
-import android.animation.LayoutTransition;
-import android.content.Context;
-import android.content.res.TypedArray;
-import android.database.DataSetObserver;
-import android.graphics.Canvas;
-import android.graphics.Point;
-import android.graphics.Rect;
-import android.util.AttributeSet;
-import android.util.Log;
-import android.view.GestureDetector;
-import android.view.MotionEvent;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.Adapter;
-import android.widget.LinearLayout;
-import com.android.gallery3d.R;
-import com.android.gallery3d.filtershow.FilterShowActivity;
-import com.android.gallery3d.filtershow.editors.ImageOnlyEditor;
-import com.android.gallery3d.filtershow.filters.FilterRepresentation;
-import com.android.gallery3d.filtershow.imageshow.MasterImage;
-
-public class StatePanelTrack extends LinearLayout implements PanelTrack {
-
-    private static final String LOGTAG = "StatePanelTrack";
-    private Point mTouchPoint;
-    private StateView mCurrentView;
-    private StateView mCurrentSelectedView;
-    private boolean mExited = false;
-    private boolean mStartedDrag = false;
-    private StateAdapter mAdapter;
-    private DragListener mDragListener = new DragListener(this);
-    private float mDeleteSlope = 0.2f;
-    private GestureDetector mGestureDetector;
-    private int mElemWidth;
-    private int mElemHeight;
-    private int mElemSize;
-    private int mElemEndSize;
-    private int mEndElemWidth;
-    private int mEndElemHeight;
-    private long mTouchTime;
-    private int mMaxTouchDelay = 300; // 300ms delay for touch
-    private static final boolean ALLOWS_DRAG = false;
-    private DataSetObserver mObserver = new DataSetObserver() {
-        @Override
-        public void onChanged() {
-            super.onChanged();
-            fillContent(false);
-        }
-
-        @Override
-        public void onInvalidated() {
-            super.onInvalidated();
-            fillContent(false);
-        }
-    };
-
-    public StatePanelTrack(Context context, AttributeSet attrs) {
-        super(context, attrs);
-        TypedArray a = getContext().obtainStyledAttributes(attrs, R.styleable.StatePanelTrack);
-        mElemSize = a.getDimensionPixelSize(R.styleable.StatePanelTrack_elemSize, 0);
-        mElemEndSize = a.getDimensionPixelSize(R.styleable.StatePanelTrack_elemEndSize, 0);
-        if (getOrientation() == LinearLayout.HORIZONTAL) {
-            mElemWidth = mElemSize;
-            mElemHeight = LayoutParams.MATCH_PARENT;
-            mEndElemWidth = mElemEndSize;
-            mEndElemHeight = LayoutParams.MATCH_PARENT;
-        } else {
-            mElemWidth = LayoutParams.MATCH_PARENT;
-            mElemHeight = mElemSize;
-            mEndElemWidth = LayoutParams.MATCH_PARENT;
-            mEndElemHeight = mElemEndSize;
-        }
-        GestureDetector.SimpleOnGestureListener simpleOnGestureListener
-                = new GestureDetector.SimpleOnGestureListener(){
-            @Override
-            public void onLongPress(MotionEvent e) {
-                longPress(e);
-            }
-            @Override
-            public boolean onDoubleTap(MotionEvent e) {
-                addDuplicate(e);
-                return true;
-            }
-        };
-        mGestureDetector = new GestureDetector(context, simpleOnGestureListener);
-    }
-
-    private void addDuplicate(MotionEvent e) {
-        if (mCurrentSelectedView == null) {
-            return;
-        }
-        int pos = findChild(mCurrentSelectedView);
-        if (pos != -1) {
-            mAdapter.insert(new State(mCurrentSelectedView.getState()), pos);
-            fillContent(true);
-        }
-    }
-
-    private void longPress(MotionEvent e) {
-        View view = findChildAt((int) e.getX(), (int) e.getY());
-        if (view == null) {
-            return;
-        }
-        if (view instanceof StateView) {
-            StateView stateView = (StateView) view;
-            stateView.setDuplicateButton(true);
-        }
-    }
-
-    public void setAdapter(StateAdapter adapter) {
-        mAdapter = adapter;
-        mAdapter.registerDataSetObserver(mObserver);
-        mAdapter.setOrientation(getOrientation());
-        fillContent(false);
-        requestLayout();
-    }
-
-    public StateView findChildWithState(State state) {
-        for (int i = 0; i < getChildCount(); i++) {
-            StateView view = (StateView) getChildAt(i);
-            if (view.getState() == state) {
-                return view;
-            }
-        }
-        return null;
-    }
-
-    public void fillContent(boolean animate) {
-        if (!animate) {
-            this.setLayoutTransition(null);
-        }
-        int n = mAdapter.getCount();
-        for (int i = 0; i < getChildCount(); i++) {
-            StateView child = (StateView) getChildAt(i);
-            child.resetPosition();
-            if (!mAdapter.contains(child.getState())) {
-                removeView(child);
-            }
-        }
-        LayoutParams params = new LayoutParams(mElemWidth, mElemHeight);
-        for (int i = 0; i < n; i++) {
-            State s = mAdapter.getItem(i);
-            if (findChildWithState(s) == null) {
-                View view = mAdapter.getView(i, null, this);
-                addView(view, i, params);
-            }
-        }
-
-        for (int i = 0; i < n; i++) {
-            State state = mAdapter.getItem(i);
-            StateView view = (StateView) getChildAt(i);
-            view.setState(state);
-            if (i == 0) {
-                view.setType(StateView.BEGIN);
-            } else if (i == n - 1) {
-                view.setType(StateView.END);
-            } else {
-                view.setType(StateView.DEFAULT);
-            }
-            view.resetPosition();
-        }
-
-        if (!animate) {
-            this.setLayoutTransition(new LayoutTransition());
-        }
-    }
-
-    public void onTouch(MotionEvent event, StateView view) {
-        if (!view.isDraggable()) {
-            return;
-        }
-        mCurrentView = view;
-        if (mCurrentSelectedView == mCurrentView) {
-            return;
-        }
-        if (mCurrentSelectedView != null) {
-            mCurrentSelectedView.setSelected(false);
-        }
-        // We changed the current view -- let's reset the
-        // gesture detector.
-        MotionEvent cancelEvent = MotionEvent.obtain(event);
-        cancelEvent.setAction(MotionEvent.ACTION_CANCEL);
-        mGestureDetector.onTouchEvent(cancelEvent);
-        mCurrentSelectedView = mCurrentView;
-        // We have to send the event to the gesture detector
-        mGestureDetector.onTouchEvent(event);
-        mTouchTime = System.currentTimeMillis();
-    }
-
-    @Override
-    public boolean onInterceptTouchEvent(MotionEvent event) {
-        if (mCurrentView != null) {
-            return true;
-        }
-        return false;
-    }
-
-    @Override
-    public boolean onTouchEvent(MotionEvent event) {
-        if (mCurrentView == null) {
-            return false;
-        }
-        if (mTouchTime == 0) {
-            mTouchTime = System.currentTimeMillis();
-        }
-        mGestureDetector.onTouchEvent(event);
-        if (mTouchPoint == null) {
-            mTouchPoint = new Point();
-            mTouchPoint.x = (int) event.getX();
-            mTouchPoint.y = (int) event.getY();
-        }
-
-        if (event.getActionMasked() == MotionEvent.ACTION_MOVE) {
-            float translation = event.getY() - mTouchPoint.y;
-            float alpha = 1.0f - (Math.abs(translation) / mCurrentView.getHeight());
-            if (getOrientation() == LinearLayout.VERTICAL) {
-                translation = event.getX() - mTouchPoint.x;
-                alpha = 1.0f - (Math.abs(translation) / mCurrentView.getWidth());
-                mCurrentView.setTranslationX(translation);
-            } else {
-                mCurrentView.setTranslationY(translation);
-            }
-            mCurrentView.setBackgroundAlpha(alpha);
-            if (ALLOWS_DRAG && alpha < 0.7) {
-                setOnDragListener(mDragListener);
-                DragShadowBuilder shadowBuilder = new DragShadowBuilder(mCurrentView);
-                mCurrentView.startDrag(null, shadowBuilder, mCurrentView, 0);
-                mStartedDrag = true;
-            }
-        }
-        if (!mExited && mCurrentView != null
-                && mCurrentView.getBackgroundAlpha() > mDeleteSlope
-                && event.getActionMasked() == MotionEvent.ACTION_UP
-                && System.currentTimeMillis() - mTouchTime < mMaxTouchDelay) {
-            FilterRepresentation representation = mCurrentView.getState().getFilterRepresentation();
-            mCurrentView.setSelected(true);
-            if (representation != MasterImage.getImage().getCurrentFilterRepresentation()) {
-                FilterShowActivity activity = (FilterShowActivity) getContext();
-                activity.showRepresentation(representation);
-                mCurrentView.setSelected(false);
-            }
-        }
-        if (event.getActionMasked() == MotionEvent.ACTION_UP
-                || (!mStartedDrag && event.getActionMasked() == MotionEvent.ACTION_CANCEL)) {
-            checkEndState();
-            if (mCurrentView != null) {
-                FilterRepresentation representation = mCurrentView.getState().getFilterRepresentation();
-                if (representation.getEditorId() == ImageOnlyEditor.ID) {
-                    mCurrentView.setSelected(false);
-                }
-            }
-        }
-        return true;
-    }
-
-    public void checkEndState() {
-        mTouchPoint = null;
-        mTouchTime = 0;
-        if (mExited || mCurrentView.getBackgroundAlpha() < mDeleteSlope) {
-            int origin = findChild(mCurrentView);
-            if (origin != -1) {
-                State current = mAdapter.getItem(origin);
-                FilterRepresentation currentRep = MasterImage.getImage().getCurrentFilterRepresentation();
-                FilterRepresentation removedRep = current.getFilterRepresentation();
-                mAdapter.remove(current);
-                fillContent(true);
-                if (currentRep != null && removedRep != null
-                        && currentRep.getFilterClass() == removedRep.getFilterClass()) {
-                    FilterShowActivity activity = (FilterShowActivity) getContext();
-                    activity.backToMain();
-                    return;
-                }
-            }
-        } else {
-            mCurrentView.setBackgroundAlpha(1.0f);
-            mCurrentView.setTranslationX(0);
-            mCurrentView.setTranslationY(0);
-        }
-        if (mCurrentSelectedView != null) {
-            mCurrentSelectedView.invalidate();
-        }
-        if (mCurrentView != null) {
-            mCurrentView.invalidate();
-        }
-        mCurrentView = null;
-        mExited = false;
-        mStartedDrag = false;
-    }
-
-    public View findChildAt(int x, int y) {
-        Rect frame = new Rect();
-        int scrolledXInt = getScrollX() + x;
-        int scrolledYInt = getScrollY() + y;
-        for (int i = 0; i < getChildCount(); i++) {
-            View child = getChildAt(i);
-            child.getHitRect(frame);
-            if (frame.contains(scrolledXInt, scrolledYInt)) {
-                return child;
-            }
-        }
-        return null;
-    }
-
-    public int findChild(View view) {
-        for (int i = 0; i < getChildCount(); i++) {
-            View child = getChildAt(i);
-            if (child == view) {
-                return i;
-            }
-        }
-        return -1;
-    }
-
-    public StateView getCurrentView() {
-        return mCurrentView;
-    }
-
-    public void setCurrentView(View currentView) {
-        mCurrentView = (StateView) currentView;
-    }
-
-    public void setExited(boolean value) {
-        mExited = value;
-    }
-
-    public Point getTouchPoint() {
-        return mTouchPoint;
-    }
-
-    public Adapter getAdapter() {
-        return mAdapter;
-    }
-}
diff --git a/src/com/android/gallery3d/filtershow/state/StateView.java b/src/com/android/gallery3d/filtershow/state/StateView.java
deleted file mode 100644
index 73d5784..0000000
--- a/src/com/android/gallery3d/filtershow/state/StateView.java
+++ /dev/null
@@ -1,291 +0,0 @@
-/*
- * Copyright (C) 2013 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.gallery3d.filtershow.state;
-
-import android.content.Context;
-import android.content.res.Resources;
-import android.graphics.*;
-import android.util.AttributeSet;
-import android.util.Log;
-import android.view.MotionEvent;
-import android.view.View;
-import android.view.ViewParent;
-import android.widget.LinearLayout;
-import com.android.gallery3d.R;
-import com.android.gallery3d.filtershow.FilterShowActivity;
-import com.android.gallery3d.filtershow.imageshow.MasterImage;
-
-public class StateView extends View {
-
-    private static final String LOGTAG = "StateView";
-    private Path mPath = new Path();
-    private Paint mPaint = new Paint();
-
-    public static int DEFAULT = 0;
-    public static int BEGIN = 1;
-    public static int END = 2;
-
-    public static int UP = 1;
-    public static int DOWN = 2;
-    public static int LEFT = 3;
-    public static int RIGHT = 4;
-
-    private int mType = DEFAULT;
-    private float mAlpha = 1.0f;
-    private String mText = "Default";
-    private float mTextSize = 32;
-    private static int sMargin = 16;
-    private static int sArrowHeight = 16;
-    private static int sArrowWidth = 8;
-    private int mOrientation = LinearLayout.VERTICAL;
-    private int mDirection = DOWN;
-    private boolean mDuplicateButton;
-    private State mState;
-
-    private int mEndsBackgroundColor;
-    private int mEndsTextColor;
-    private int mBackgroundColor;
-    private int mTextColor;
-    private int mSelectedBackgroundColor;
-    private int mSelectedTextColor;
-    private Rect mTextBounds = new Rect();
-
-    public StateView(Context context) {
-        this(context, DEFAULT);
-    }
-
-    public StateView(Context context, int type) {
-        super(context);
-        mType = type;
-        Resources res = getResources();
-        mEndsBackgroundColor = res.getColor(R.color.filtershow_stateview_end_background);
-        mEndsTextColor = res.getColor(R.color.filtershow_stateview_end_text);
-        mBackgroundColor = res.getColor(R.color.filtershow_stateview_background);
-        mTextColor = res.getColor(R.color.filtershow_stateview_text);
-        mSelectedBackgroundColor = res.getColor(R.color.filtershow_stateview_selected_background);
-        mSelectedTextColor = res.getColor(R.color.filtershow_stateview_selected_text);
-        mTextSize = res.getDimensionPixelSize(R.dimen.state_panel_text_size);
-    }
-
-    public String getText() {
-        return mText;
-    }
-
-    public void setText(String text) {
-        mText = text;
-        invalidate();
-    }
-
-    public void setType(int type) {
-        mType = type;
-        invalidate();
-    }
-
-    @Override
-    public void setSelected(boolean value) {
-        super.setSelected(value);
-        if (!value) {
-            mDuplicateButton = false;
-        }
-        invalidate();
-    }
-
-    @Override
-    public boolean onTouchEvent(MotionEvent event) {
-        if (event.getActionMasked() == MotionEvent.ACTION_DOWN) {
-            ViewParent parent = getParent();
-            if (parent instanceof PanelTrack) {
-                ((PanelTrack) getParent()).onTouch(event, this);
-            }
-            if (mType == BEGIN) {
-                MasterImage.getImage().setShowsOriginal(true);
-            }
-        }
-        if (event.getActionMasked() == MotionEvent.ACTION_UP
-                || event.getActionMasked() == MotionEvent.ACTION_CANCEL) {
-            MasterImage.getImage().setShowsOriginal(false);
-        }
-        return true;
-    }
-
-    public void drawText(Canvas canvas) {
-        if (mText == null) {
-            return;
-        }
-        mPaint.reset();
-        if (isSelected()) {
-            mPaint.setColor(mSelectedTextColor);
-        } else {
-            mPaint.setColor(mTextColor);
-        }
-        if (mType == BEGIN) {
-            mPaint.setColor(mEndsTextColor);
-        }
-        mPaint.setTypeface(Typeface.DEFAULT_BOLD);
-        mPaint.setAntiAlias(true);
-        mPaint.setTextSize(mTextSize);
-        mPaint.getTextBounds(mText, 0, mText.length(), mTextBounds);
-        int x = (canvas.getWidth() - mTextBounds.width()) / 2;
-        int y = mTextBounds.height() + (canvas.getHeight() - mTextBounds.height()) / 2;
-        canvas.drawText(mText, x, y, mPaint);
-    }
-
-    public void onDraw(Canvas canvas) {
-        canvas.drawARGB(0, 0, 0, 0);
-        mPaint.reset();
-        mPath.reset();
-
-        float w = canvas.getWidth();
-        float h = canvas.getHeight();
-        float r = sArrowHeight;
-        float d = sArrowWidth;
-
-        if (mOrientation == LinearLayout.HORIZONTAL) {
-            drawHorizontalPath(w, h, r, d);
-        } else {
-            if (mDirection == DOWN) {
-                drawVerticalDownPath(w, h, r, d);
-            } else {
-                drawVerticalPath(w, h, r, d);
-            }
-        }
-
-        if (mType == DEFAULT || mType == END) {
-            if (mDuplicateButton) {
-                mPaint.setARGB(255, 200, 0, 0);
-            } else if (isSelected()) {
-                mPaint.setColor(mSelectedBackgroundColor);
-            } else {
-                mPaint.setColor(mBackgroundColor);
-            }
-        } else {
-            mPaint.setColor(mEndsBackgroundColor);
-        }
-        canvas.drawPath(mPath, mPaint);
-        drawText(canvas);
-    }
-
-    private void drawHorizontalPath(float w, float h, float r, float d) {
-        mPath.moveTo(0, 0);
-        if (mType == END) {
-            mPath.lineTo(w, 0);
-            mPath.lineTo(w, h);
-        } else {
-            mPath.lineTo(w - d, 0);
-            mPath.lineTo(w - d, r);
-            mPath.lineTo(w, r + d);
-            mPath.lineTo(w - d, r + d + r);
-            mPath.lineTo(w - d, h);
-        }
-        mPath.lineTo(0, h);
-        if (mType != BEGIN) {
-            mPath.lineTo(0, r + d + r);
-            mPath.lineTo(d, r + d);
-            mPath.lineTo(0, r);
-        }
-        mPath.close();
-    }
-
-    private void drawVerticalPath(float w, float h, float r, float d) {
-        if (mType == BEGIN) {
-            mPath.moveTo(0, 0);
-            mPath.lineTo(w, 0);
-        } else {
-            mPath.moveTo(0, d);
-            mPath.lineTo(r, d);
-            mPath.lineTo(r + d, 0);
-            mPath.lineTo(r + d + r, d);
-            mPath.lineTo(w, d);
-        }
-        mPath.lineTo(w, h);
-        if (mType != END) {
-            mPath.lineTo(r + d + r, h);
-            mPath.lineTo(r + d, h - d);
-            mPath.lineTo(r, h);
-        }
-        mPath.lineTo(0, h);
-        mPath.close();
-    }
-
-    private void drawVerticalDownPath(float w, float h, float r, float d) {
-        mPath.moveTo(0, 0);
-        if (mType != BEGIN) {
-            mPath.lineTo(r, 0);
-            mPath.lineTo(r + d, d);
-            mPath.lineTo(r + d + r, 0);
-        }
-        mPath.lineTo(w, 0);
-
-        if (mType != END) {
-            mPath.lineTo(w, h - d);
-
-            mPath.lineTo(r + d + r, h - d);
-            mPath.lineTo(r + d, h);
-            mPath.lineTo(r, h - d);
-
-            mPath.lineTo(0, h - d);
-        } else {
-            mPath.lineTo(w, h);
-            mPath.lineTo(0, h);
-        }
-
-        mPath.close();
-    }
-
-    public void setBackgroundAlpha(float alpha) {
-        if (mType == BEGIN) {
-            return;
-        }
-        mAlpha = alpha;
-        setAlpha(alpha);
-        invalidate();
-    }
-
-    public float getBackgroundAlpha() {
-        return mAlpha;
-    }
-
-    public void setOrientation(int orientation) {
-        mOrientation = orientation;
-    }
-
-    public void setDuplicateButton(boolean b) {
-        mDuplicateButton = b;
-        invalidate();
-    }
-
-    public State getState() {
-        return mState;
-    }
-
-    public void setState(State state) {
-        mState = state;
-        mText = mState.getText().toUpperCase();
-        mType = mState.getType();
-        invalidate();
-    }
-
-    public void resetPosition() {
-        setTranslationX(0);
-        setTranslationY(0);
-        setBackgroundAlpha(1.0f);
-    }
-
-    public boolean isDraggable() {
-        return mState.isDraggable();
-    }
-}
diff --git a/src/com/android/gallery3d/filtershow/tools/IconFactory.java b/src/com/android/gallery3d/filtershow/tools/IconFactory.java
deleted file mode 100644
index 9e39f27..0000000
--- a/src/com/android/gallery3d/filtershow/tools/IconFactory.java
+++ /dev/null
@@ -1,108 +0,0 @@
-/*
- * Copyright (C) 2013 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.gallery3d.filtershow.tools;
-
-import android.graphics.Bitmap;
-import android.graphics.Canvas;
-import android.graphics.Paint;
-import android.graphics.Rect;
-import android.graphics.RectF;
-
-/**
- * A factory class for producing bitmaps to use as UI icons.
- */
-public class IconFactory {
-
-    /**
-     * Builds an icon with the dimensions iconWidth:iconHeight. If scale is set
-     * the source image is stretched to fit within the given dimensions;
-     * otherwise, the source image is cropped to the proper aspect ratio.
-     *
-     * @param sourceImage image to create an icon from.
-     * @param iconWidth width of the icon bitmap.
-     * @param iconHeight height of the icon bitmap.
-     * @param scale if true, stretch sourceImage to fit the icon dimensions.
-     * @return an icon bitmap with the dimensions iconWidth:iconHeight.
-     */
-    public static Bitmap createIcon(Bitmap sourceImage, int iconWidth, int iconHeight,
-            boolean scale) {
-        if (sourceImage == null) {
-            throw new IllegalArgumentException("Null argument to buildIcon");
-        }
-
-        int sourceWidth = sourceImage.getWidth();
-        int sourceHeight = sourceImage.getHeight();
-
-        if (sourceWidth == 0 || sourceHeight == 0 || iconWidth == 0 || iconHeight == 0) {
-            throw new IllegalArgumentException("Bitmap with dimension 0 used as input");
-        }
-
-        Bitmap icon = Bitmap.createBitmap(iconWidth, iconHeight,
-                Bitmap.Config.ARGB_8888);
-        drawIcon(icon, sourceImage, scale);
-        return icon;
-    }
-
-    /**
-     * Draws an icon in the destination bitmap. If scale is set the source image
-     * is stretched to fit within the destination dimensions; otherwise, the
-     * source image is cropped to the proper aspect ratio.
-     *
-     * @param dest bitmap into which to draw the icon.
-     * @param sourceImage image to create an icon from.
-     * @param scale if true, stretch sourceImage to fit the destination.
-     */
-    public static void drawIcon(Bitmap dest, Bitmap sourceImage, boolean scale) {
-        if (dest == null || sourceImage == null) {
-            throw new IllegalArgumentException("Null argument to buildIcon");
-        }
-
-        int sourceWidth = sourceImage.getWidth();
-        int sourceHeight = sourceImage.getHeight();
-        int iconWidth = dest.getWidth();
-        int iconHeight = dest.getHeight();
-
-        if (sourceWidth == 0 || sourceHeight == 0 || iconWidth == 0 || iconHeight == 0) {
-            throw new IllegalArgumentException("Bitmap with dimension 0 used as input");
-        }
-
-        Rect destRect = new Rect(0, 0, iconWidth, iconHeight);
-        Canvas canvas = new Canvas(dest);
-
-        Rect srcRect = null;
-        if (scale) {
-            // scale image to fit in icon (stretches if aspect isn't the same)
-            srcRect = new Rect(0, 0, sourceWidth, sourceHeight);
-        } else {
-            // crop image to aspect ratio iconWidth:iconHeight
-            float wScale = sourceWidth / (float) iconWidth;
-            float hScale = sourceHeight / (float) iconHeight;
-            float s = Math.min(hScale, wScale);
-
-            float iw = iconWidth * s;
-            float ih = iconHeight * s;
-
-            float borderW = (sourceWidth - iw) / 2.0f;
-            float borderH = (sourceHeight - ih) / 2.0f;
-            RectF rec = new RectF(borderW, borderH, borderW + iw, borderH + ih);
-            srcRect = new Rect();
-            rec.roundOut(srcRect);
-        }
-
-        canvas.drawBitmap(sourceImage, srcRect, destRect, new Paint(Paint.FILTER_BITMAP_FLAG));
-    }
-}
diff --git a/src/com/android/gallery3d/filtershow/tools/MatrixFit.java b/src/com/android/gallery3d/filtershow/tools/MatrixFit.java
deleted file mode 100644
index 3b81567..0000000
--- a/src/com/android/gallery3d/filtershow/tools/MatrixFit.java
+++ /dev/null
@@ -1,200 +0,0 @@
-/*
- * Copyright (C) 2013 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.gallery3d.filtershow.tools;
-
-import android.util.Log;
-
-public class MatrixFit {
-    // Simple implementation of a matrix fit in N dimensions.
-
-    private static final String LOGTAG = "MatrixFit";
-
-    private double[][] mMatrix;
-    private int mDimension;
-    private boolean mValid = false;
-    private static double sEPS = 1.0f/10000000000.0f;
-
-    public MatrixFit(double[][] from, double[][] to) {
-        mValid = fit(from, to);
-    }
-
-    public int getDimension() {
-        return mDimension;
-    }
-
-    public boolean isValid() {
-        return mValid;
-    }
-
-    public double[][] getMatrix() {
-        return mMatrix;
-    }
-
-    public boolean fit(double[][] from, double[][] to) {
-        if ((from.length != to.length) || (from.length < 1)) {
-            Log.e(LOGTAG, "from and to must be of same size");
-            return false;
-        }
-
-        mDimension = from[0].length;
-        mMatrix = new double[mDimension +1][mDimension + mDimension +1];
-
-        if (from.length < mDimension) {
-            Log.e(LOGTAG, "Too few points => under-determined system");
-            return false;
-        }
-
-        double[][] q = new double[from.length][mDimension];
-        for (int i = 0; i < from.length; i++) {
-            for (int j = 0; j < mDimension; j++) {
-                q[i][j] = from[i][j];
-            }
-        }
-
-        double[][] p = new double[to.length][mDimension];
-        for (int i = 0; i < to.length; i++) {
-            for (int j = 0; j < mDimension; j++) {
-                p[i][j] = to[i][j];
-            }
-        }
-
-        // Make an empty (dim) x (dim + 1) matrix and fill it
-        double[][] c = new double[mDimension+1][mDimension];
-        for (int j = 0; j < mDimension; j++) {
-            for (int k = 0; k < mDimension + 1; k++) {
-                for (int i = 0; i < q.length; i++) {
-                    double qt = 1;
-                    if (k < mDimension) {
-                        qt = q[i][k];
-                    }
-                    c[k][j] += qt * p[i][j];
-                }
-            }
-        }
-
-        // Make an empty (dim+1) x (dim+1) matrix and fill it
-        double[][] Q = new double[mDimension+1][mDimension+1];
-        for (int qi = 0; qi < q.length; qi++) {
-            double[] qt = new double[mDimension + 1];
-            for (int i = 0; i < mDimension; i++) {
-                qt[i] = q[qi][i];
-            }
-            qt[mDimension] = 1;
-            for (int i = 0; i < mDimension + 1; i++) {
-                for (int j = 0; j < mDimension + 1; j++) {
-                    Q[i][j] += qt[i] * qt[j];
-                }
-            }
-        }
-
-        // Use a gaussian elimination to solve the linear system
-        for (int i = 0; i < mDimension + 1; i++) {
-            for (int j = 0; j < mDimension + 1; j++) {
-                mMatrix[i][j] = Q[i][j];
-            }
-            for (int j = 0; j < mDimension; j++) {
-                mMatrix[i][mDimension + 1 + j] = c[i][j];
-            }
-        }
-        if (!gaussianElimination(mMatrix)) {
-            return false;
-        }
-        return true;
-    }
-
-    public double[] apply(double[] point) {
-        if (mDimension != point.length) {
-            return null;
-        }
-        double[] res = new double[mDimension];
-        for (int j = 0; j < mDimension; j++) {
-            for (int i = 0; i < mDimension; i++) {
-                res[j] += point[i] * mMatrix[i][j+ mDimension +1];
-            }
-            res[j] += mMatrix[mDimension][j+ mDimension +1];
-        }
-        return res;
-    }
-
-    public void printEquation() {
-        for (int j = 0; j < mDimension; j++) {
-            String str = "x" + j + "' = ";
-            for (int i = 0; i < mDimension; i++) {
-                str += "x" + i + " * " + mMatrix[i][j+mDimension+1] + " + ";
-            }
-            str += mMatrix[mDimension][j+mDimension+1];
-            Log.v(LOGTAG, str);
-        }
-    }
-
-    private void printMatrix(String name, double[][] matrix) {
-        Log.v(LOGTAG, "name: " + name);
-        for (int i = 0; i < matrix.length; i++) {
-            String str = "";
-            for (int j = 0; j < matrix[0].length; j++) {
-                str += "" + matrix[i][j] + " ";
-            }
-            Log.v(LOGTAG, str);
-        }
-    }
-
-    /*
-     * Transforms the given matrix into a row echelon matrix
-     */
-    private boolean gaussianElimination(double[][] m) {
-        int h = m.length;
-        int w = m[0].length;
-
-        for (int y = 0; y < h; y++) {
-            int maxrow = y;
-            for (int y2 = y + 1; y2 < h; y2++) { // Find max pivot
-                if (Math.abs(m[y2][y]) > Math.abs(m[maxrow][y])) {
-                    maxrow = y2;
-                }
-            }
-            // swap
-            for (int i = 0; i < mDimension; i++) {
-                double t = m[y][i];
-                m[y][i] = m[maxrow][i];
-                m[maxrow][i] = t;
-            }
-
-            if (Math.abs(m[y][y]) <= sEPS) { // Singular Matrix
-                return false;
-            }
-            for (int y2 = y + 1; y2 < h; y2++) { // Eliminate column y
-                double c = m[y2][y] / m[y][y];
-                for (int x = y; x < w; x++) {
-                    m[y2][x] -= m[y][x] * c;
-                }
-            }
-        }
-        for (int y = h -1; y > -1; y--) { // Back substitution
-            double c = m[y][y];
-            for (int y2 = 0; y2 < y; y2++) {
-                for (int x = w - 1; x > y - 1; x--) {
-                    m[y2][x] -= m[y][x] * m[y2][y] / c;
-                }
-            }
-            m[y][y] /= c;
-            for (int x = h; x < w; x++) { // Normalize row y
-                m[y][x] /= c;
-            }
-        }
-        return true;
-    }
-}
diff --git a/src/com/android/gallery3d/filtershow/tools/SaveImage.java b/src/com/android/gallery3d/filtershow/tools/SaveImage.java
deleted file mode 100644
index 83cbd01..0000000
--- a/src/com/android/gallery3d/filtershow/tools/SaveImage.java
+++ /dev/null
@@ -1,632 +0,0 @@
-/*
- * Copyright (C) 2010 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.gallery3d.filtershow.tools;
-
-import android.content.ContentResolver;
-import android.content.ContentValues;
-import android.content.Context;
-import android.content.Intent;
-import android.database.Cursor;
-import android.graphics.Bitmap;
-import android.net.Uri;
-import android.os.Environment;
-import android.provider.MediaStore;
-import android.provider.MediaStore.Images;
-import android.provider.MediaStore.Images.ImageColumns;
-import android.util.Log;
-
-import com.android.gallery3d.common.Utils;
-import com.android.gallery3d.exif.ExifInterface;
-import com.android.gallery3d.filtershow.FilterShowActivity;
-import com.android.gallery3d.filtershow.cache.ImageLoader;
-import com.android.gallery3d.filtershow.filters.FiltersManager;
-import com.android.gallery3d.filtershow.imageshow.MasterImage;
-import com.android.gallery3d.filtershow.pipeline.CachingPipeline;
-import com.android.gallery3d.filtershow.pipeline.ImagePreset;
-import com.android.gallery3d.filtershow.pipeline.ProcessingService;
-import com.android.gallery3d.util.UsageStatistics;
-import com.android.gallery3d.util.XmpUtilHelper;
-
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.FilenameFilter;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.sql.Date;
-import java.text.SimpleDateFormat;
-import java.util.TimeZone;
-
-/**
- * Handles saving edited photo
- */
-public class SaveImage {
-    private static final String LOGTAG = "SaveImage";
-
-    /**
-     * Callback for updates
-     */
-    public interface Callback {
-        void onProgress(int max, int current);
-    }
-
-    public interface ContentResolverQueryCallback {
-        void onCursorResult(Cursor cursor);
-    }
-
-    private static final String TIME_STAMP_NAME = "_yyyyMMdd_HHmmss";
-    private static final String PREFIX_PANO = "PANO";
-    private static final String PREFIX_IMG = "IMG";
-    private static final String POSTFIX_JPG = ".jpg";
-    private static final String AUX_DIR_NAME = ".aux";
-
-    private final Context mContext;
-    private final Uri mSourceUri;
-    private final Callback mCallback;
-    private final File mDestinationFile;
-    private final Uri mSelectedImageUri;
-
-    private int mCurrentProcessingStep = 1;
-
-    public static final int MAX_PROCESSING_STEPS = 6;
-    public static final String DEFAULT_SAVE_DIRECTORY = "EditedOnlinePhotos";
-
-    // In order to support the new edit-save behavior such that user won't see
-    // the edited image together with the original image, we are adding a new
-    // auxiliary directory for the edited image. Basically, the original image
-    // will be hidden in that directory after edit and user will see the edited
-    // image only.
-    // Note that deletion on the edited image will also cause the deletion of
-    // the original image under auxiliary directory.
-    //
-    // There are several situations we need to consider:
-    // 1. User edit local image local01.jpg. A local02.jpg will be created in the
-    // same directory, and original image will be moved to auxiliary directory as
-    // ./.aux/local02.jpg.
-    // If user edit the local02.jpg, local03.jpg will be created in the local
-    // directory and ./.aux/local02.jpg will be renamed to ./.aux/local03.jpg
-    //
-    // 2. User edit remote image remote01.jpg from picassa or other server.
-    // remoteSavedLocal01.jpg will be saved under proper local directory.
-    // In remoteSavedLocal01.jpg, there will be a reference pointing to the
-    // remote01.jpg. There will be no local copy of remote01.jpg.
-    // If user edit remoteSavedLocal01.jpg, then a new remoteSavedLocal02.jpg
-    // will be generated and still pointing to the remote01.jpg
-    //
-    // 3. User delete any local image local.jpg.
-    // Since the filenames are kept consistent in auxiliary directory, every
-    // time a local.jpg get deleted, the files in auxiliary directory whose
-    // names starting with "local." will be deleted.
-    // This pattern will facilitate the multiple images deletion in the auxiliary
-    // directory.
-
-    /**
-     * @param context
-     * @param sourceUri The Uri for the original image, which can be the hidden
-     *  image under the auxiliary directory or the same as selectedImageUri.
-     * @param selectedImageUri The Uri for the image selected by the user.
-     *  In most cases, it is a content Uri for local image or remote image.
-     * @param destination Destinaton File, if this is null, a new file will be
-     *  created under the same directory as selectedImageUri.
-     * @param callback Let the caller know the saving has completed.
-     * @return the newSourceUri
-     */
-    public SaveImage(Context context, Uri sourceUri, Uri selectedImageUri,
-                     File destination, Callback callback)  {
-        mContext = context;
-        mSourceUri = sourceUri;
-        mCallback = callback;
-        if (destination == null) {
-            mDestinationFile = getNewFile(context, selectedImageUri);
-        } else {
-            mDestinationFile = destination;
-        }
-
-        mSelectedImageUri = selectedImageUri;
-    }
-
-    public static File getFinalSaveDirectory(Context context, Uri sourceUri) {
-        File saveDirectory = SaveImage.getSaveDirectory(context, sourceUri);
-        if ((saveDirectory == null) || !saveDirectory.canWrite()) {
-            saveDirectory = new File(Environment.getExternalStorageDirectory(),
-                    SaveImage.DEFAULT_SAVE_DIRECTORY);
-        }
-        // Create the directory if it doesn't exist
-        if (!saveDirectory.exists())
-            saveDirectory.mkdirs();
-        return saveDirectory;
-    }
-
-    public static File getNewFile(Context context, Uri sourceUri) {
-        File saveDirectory = getFinalSaveDirectory(context, sourceUri);
-        String filename = new SimpleDateFormat(TIME_STAMP_NAME).format(new Date(
-                System.currentTimeMillis()));
-        if (hasPanoPrefix(context, sourceUri)) {
-            return new File(saveDirectory, PREFIX_PANO + filename + POSTFIX_JPG);
-        }
-        return new File(saveDirectory, PREFIX_IMG + filename + POSTFIX_JPG);
-    }
-
-    /**
-     * Remove the files in the auxiliary directory whose names are the same as
-     * the source image.
-     * @param contentResolver The application's contentResolver
-     * @param srcContentUri The content Uri for the source image.
-     */
-    public static void deleteAuxFiles(ContentResolver contentResolver,
-            Uri srcContentUri) {
-        final String[] fullPath = new String[1];
-        String[] queryProjection = new String[] { ImageColumns.DATA };
-        querySourceFromContentResolver(contentResolver,
-                srcContentUri, queryProjection,
-                new ContentResolverQueryCallback() {
-                    @Override
-                    public void onCursorResult(Cursor cursor) {
-                        fullPath[0] = cursor.getString(0);
-                    }
-                }
-        );
-        if (fullPath[0] != null) {
-            // Construct the auxiliary directory given the source file's path.
-            // Then select and delete all the files starting with the same name
-            // under the auxiliary directory.
-            File currentFile = new File(fullPath[0]);
-
-            String filename = currentFile.getName();
-            int firstDotPos = filename.indexOf(".");
-            final String filenameNoExt = (firstDotPos == -1) ? filename :
-                filename.substring(0, firstDotPos);
-            File auxDir = getLocalAuxDirectory(currentFile);
-            if (auxDir.exists()) {
-                FilenameFilter filter = new FilenameFilter() {
-                    @Override
-                    public boolean accept(File dir, String name) {
-                        if (name.startsWith(filenameNoExt + ".")) {
-                            return true;
-                        } else {
-                            return false;
-                        }
-                    }
-                };
-
-                // Delete all auxiliary files whose name is matching the
-                // current local image.
-                File[] auxFiles = auxDir.listFiles(filter);
-                for (File file : auxFiles) {
-                    file.delete();
-                }
-            }
-        }
-    }
-
-    public Object getPanoramaXMPData(Uri source, ImagePreset preset) {
-        Object xmp = null;
-        if (preset.isPanoramaSafe()) {
-            InputStream is = null;
-            try {
-                is = mContext.getContentResolver().openInputStream(source);
-                xmp = XmpUtilHelper.extractXMPMeta(is);
-            } catch (FileNotFoundException e) {
-                Log.w(LOGTAG, "Failed to get XMP data from image: ", e);
-            } finally {
-                Utils.closeSilently(is);
-            }
-        }
-        return xmp;
-    }
-
-    public boolean putPanoramaXMPData(File file, Object xmp) {
-        if (xmp != null) {
-            return XmpUtilHelper.writeXMPMeta(file.getAbsolutePath(), xmp);
-        }
-        return false;
-    }
-
-    public ExifInterface getExifData(Uri source) {
-        ExifInterface exif = new ExifInterface();
-        String mimeType = mContext.getContentResolver().getType(mSelectedImageUri);
-        if (mimeType == null) {
-            mimeType = ImageLoader.getMimeType(mSelectedImageUri);
-        }
-        if (mimeType.equals(ImageLoader.JPEG_MIME_TYPE)) {
-            InputStream inStream = null;
-            try {
-                inStream = mContext.getContentResolver().openInputStream(source);
-                exif.readExif(inStream);
-            } catch (FileNotFoundException e) {
-                Log.w(LOGTAG, "Cannot find file: " + source, e);
-            } catch (IOException e) {
-                Log.w(LOGTAG, "Cannot read exif for: " + source, e);
-            } finally {
-                Utils.closeSilently(inStream);
-            }
-        }
-        return exif;
-    }
-
-    public boolean putExifData(File file, ExifInterface exif, Bitmap image,
-            int jpegCompressQuality) {
-        boolean ret = false;
-        OutputStream s = null;
-        try {
-            s = exif.getExifWriterStream(file.getAbsolutePath());
-            image.compress(Bitmap.CompressFormat.JPEG,
-                    (jpegCompressQuality > 0) ? jpegCompressQuality : 1, s);
-            s.flush();
-            s.close();
-            s = null;
-            ret = true;
-        } catch (FileNotFoundException e) {
-            Log.w(LOGTAG, "File not found: " + file.getAbsolutePath(), e);
-        } catch (IOException e) {
-            Log.w(LOGTAG, "Could not write exif: ", e);
-        } finally {
-            Utils.closeSilently(s);
-        }
-        return ret;
-    }
-
-    private Uri resetToOriginalImageIfNeeded(ImagePreset preset, boolean doAuxBackup) {
-        Uri uri = null;
-        if (!preset.hasModifications()) {
-            // This can happen only when preset has no modification but save
-            // button is enabled, it means the file is loaded with filters in
-            // the XMP, then all the filters are removed or restore to default.
-            // In this case, when mSourceUri exists, rename it to the
-            // destination file.
-            File srcFile = getLocalFileFromUri(mContext, mSourceUri);
-            // If the source is not a local file, then skip this renaming and
-            // create a local copy as usual.
-            if (srcFile != null) {
-                srcFile.renameTo(mDestinationFile);
-                uri = SaveImage.linkNewFileToUri(mContext, mSelectedImageUri,
-                        mDestinationFile, System.currentTimeMillis(), doAuxBackup);
-            }
-        }
-        return uri;
-    }
-
-    private void resetProgress() {
-        mCurrentProcessingStep = 0;
-    }
-
-    private void updateProgress() {
-        if (mCallback != null) {
-            mCallback.onProgress(MAX_PROCESSING_STEPS, ++mCurrentProcessingStep);
-        }
-    }
-
-    public Uri processAndSaveImage(ImagePreset preset, boolean doAuxBackup, int quality) {
-
-        Uri uri = resetToOriginalImageIfNeeded(preset, doAuxBackup);
-        if (uri != null) {
-            return null;
-        }
-
-        resetProgress();
-
-        boolean noBitmap = true;
-        int num_tries = 0;
-        int sampleSize = 1;
-
-        // If necessary, move the source file into the auxiliary directory,
-        // newSourceUri is then pointing to the new location.
-        // If no file is moved, newSourceUri will be the same as mSourceUri.
-        Uri newSourceUri = mSourceUri;
-        if (doAuxBackup) {
-            newSourceUri = moveSrcToAuxIfNeeded(mSourceUri, mDestinationFile);
-        }
-
-        // Stopgap fix for low-memory devices.
-        while (noBitmap) {
-            try {
-                updateProgress();
-                // Try to do bitmap operations, downsample if low-memory
-                Bitmap bitmap = ImageLoader.loadOrientedBitmapWithBackouts(mContext, newSourceUri,
-                        sampleSize);
-                if (bitmap == null) {
-                    return null;
-                }
-                updateProgress();
-                CachingPipeline pipeline = new CachingPipeline(FiltersManager.getManager(),
-                        "Saving");
-
-                bitmap = pipeline.renderFinalImage(bitmap, preset);
-                updateProgress();
-
-                Object xmp = getPanoramaXMPData(newSourceUri, preset);
-                ExifInterface exif = getExifData(newSourceUri);
-
-                updateProgress();
-                // Set tags
-                long time = System.currentTimeMillis();
-                exif.addDateTimeStampTag(ExifInterface.TAG_DATE_TIME, time,
-                        TimeZone.getDefault());
-                exif.setTag(exif.buildTag(ExifInterface.TAG_ORIENTATION,
-                        ExifInterface.Orientation.TOP_LEFT));
-                // Remove old thumbnail
-                exif.removeCompressedThumbnail();
-
-                updateProgress();
-
-                // If we succeed in writing the bitmap as a jpeg, return a uri.
-                if (putExifData(mDestinationFile, exif, bitmap, quality)) {
-                    putPanoramaXMPData(mDestinationFile, xmp);
-                    // mDestinationFile will save the newSourceUri info in the XMP.
-                    XmpPresets.writeFilterXMP(mContext, newSourceUri,
-                            mDestinationFile, preset);
-
-                    // After this call, mSelectedImageUri will be actually
-                    // pointing at the new file mDestinationFile.
-                    uri = SaveImage.linkNewFileToUri(mContext, mSelectedImageUri,
-                            mDestinationFile, time, doAuxBackup);
-                }
-                updateProgress();
-
-                noBitmap = false;
-                UsageStatistics.onEvent(UsageStatistics.COMPONENT_EDITOR,
-                        "SaveComplete", null);
-            } catch (OutOfMemoryError e) {
-                // Try 5 times before failing for good.
-                if (++num_tries >= 5) {
-                    throw e;
-                }
-                System.gc();
-                sampleSize *= 2;
-                resetProgress();
-            }
-        }
-        return uri;
-    }
-
-    /**
-     *  Move the source file to auxiliary directory if needed and return the Uri
-     *  pointing to this new source file.
-     * @param srcUri Uri to the source image.
-     * @param dstFile Providing the destination file info to help to build the
-     *  auxiliary directory and new source file's name.
-     * @return the newSourceUri pointing to the new source image.
-     */
-    private Uri moveSrcToAuxIfNeeded(Uri srcUri, File dstFile) {
-        File srcFile = getLocalFileFromUri(mContext, srcUri);
-        if (srcFile == null) {
-            Log.d(LOGTAG, "Source file is not a local file, no update.");
-            return srcUri;
-        }
-
-        // Get the destination directory and create the auxilliary directory
-        // if necessary.
-        File auxDiretory = getLocalAuxDirectory(dstFile);
-        if (!auxDiretory.exists()) {
-            auxDiretory.mkdirs();
-        }
-
-        // Make sure there is a .nomedia file in the auxiliary directory, such
-        // that MediaScanner will not report those files under this directory.
-        File noMedia = new File(auxDiretory, ".nomedia");
-        if (!noMedia.exists()) {
-            try {
-                noMedia.createNewFile();
-            } catch (IOException e) {
-                Log.e(LOGTAG, "Can't create the nomedia");
-                return srcUri;
-            }
-        }
-        // We are using the destination file name such that photos sitting in
-        // the auxiliary directory are matching the parent directory.
-        File newSrcFile = new File(auxDiretory, dstFile.getName());
-
-        if (!newSrcFile.exists()) {
-            srcFile.renameTo(newSrcFile);
-        }
-
-        return Uri.fromFile(newSrcFile);
-
-    }
-
-    private static File getLocalAuxDirectory(File dstFile) {
-        File dstDirectory = dstFile.getParentFile();
-        File auxDiretory = new File(dstDirectory + "/" + AUX_DIR_NAME);
-        return auxDiretory;
-    }
-
-    public static Uri makeAndInsertUri(Context context, Uri sourceUri) {
-        long time = System.currentTimeMillis();
-        String filename = new SimpleDateFormat(TIME_STAMP_NAME).format(new Date(time));
-        File saveDirectory = getFinalSaveDirectory(context, sourceUri);
-        File file = new File(saveDirectory, filename  + ".JPG");
-        return linkNewFileToUri(context, sourceUri, file, time, false);
-    }
-
-    public static void saveImage(ImagePreset preset, final FilterShowActivity filterShowActivity,
-            File destination) {
-        Uri selectedImageUri = filterShowActivity.getSelectedImageUri();
-        Uri sourceImageUri = MasterImage.getImage().getUri();
-
-        Intent processIntent = ProcessingService.getSaveIntent(filterShowActivity, preset,
-                destination, selectedImageUri, sourceImageUri, false, 90);
-
-        filterShowActivity.startService(processIntent);
-
-        if (!filterShowActivity.isSimpleEditAction()) {
-            // terminate for now
-            filterShowActivity.completeSaveImage(selectedImageUri);
-        }
-    }
-
-    public static void querySource(Context context, Uri sourceUri, String[] projection,
-            ContentResolverQueryCallback callback) {
-        ContentResolver contentResolver = context.getContentResolver();
-        querySourceFromContentResolver(contentResolver, sourceUri, projection, callback);
-    }
-
-    private static void querySourceFromContentResolver(
-            ContentResolver contentResolver, Uri sourceUri, String[] projection,
-            ContentResolverQueryCallback callback) {
-        Cursor cursor = null;
-        try {
-            cursor = contentResolver.query(sourceUri, projection, null, null,
-                    null);
-            if ((cursor != null) && cursor.moveToNext()) {
-                callback.onCursorResult(cursor);
-            }
-        } catch (Exception e) {
-            // Ignore error for lacking the data column from the source.
-        } finally {
-            if (cursor != null) {
-                cursor.close();
-            }
-        }
-    }
-
-    private static File getSaveDirectory(Context context, Uri sourceUri) {
-        File file = getLocalFileFromUri(context, sourceUri);
-        if (file != null) {
-            return file.getParentFile();
-        } else {
-            return null;
-        }
-    }
-
-    /**
-     * Construct a File object based on the srcUri.
-     * @return The file object. Return null if srcUri is invalid or not a local
-     * file.
-     */
-    private static File getLocalFileFromUri(Context context, Uri srcUri) {
-        if (srcUri == null) {
-            Log.e(LOGTAG, "srcUri is null.");
-            return null;
-        }
-
-        String scheme = srcUri.getScheme();
-        if (scheme == null) {
-            Log.e(LOGTAG, "scheme is null.");
-            return null;
-        }
-
-        final File[] file = new File[1];
-        // sourceUri can be a file path or a content Uri, it need to be handled
-        // differently.
-        if (scheme.equals(ContentResolver.SCHEME_CONTENT)) {
-            if (srcUri.getAuthority().equals(MediaStore.AUTHORITY)) {
-                querySource(context, srcUri, new String[] {
-                        ImageColumns.DATA
-                },
-                        new ContentResolverQueryCallback() {
-
-                            @Override
-                            public void onCursorResult(Cursor cursor) {
-                                file[0] = new File(cursor.getString(0));
-                            }
-                        });
-            }
-        } else if (scheme.equals(ContentResolver.SCHEME_FILE)) {
-            file[0] = new File(srcUri.getPath());
-        }
-        return file[0];
-    }
-
-    /**
-     * Gets the actual filename for a Uri from Gallery's ContentProvider.
-     */
-    private static String getTrueFilename(Context context, Uri src) {
-        if (context == null || src == null) {
-            return null;
-        }
-        final String[] trueName = new String[1];
-        querySource(context, src, new String[] {
-                ImageColumns.DATA
-        }, new ContentResolverQueryCallback() {
-            @Override
-            public void onCursorResult(Cursor cursor) {
-                trueName[0] = new File(cursor.getString(0)).getName();
-            }
-        });
-        return trueName[0];
-    }
-
-    /**
-     * Checks whether the true filename has the panorama image prefix.
-     */
-    private static boolean hasPanoPrefix(Context context, Uri src) {
-        String name = getTrueFilename(context, src);
-        return name != null && name.startsWith(PREFIX_PANO);
-    }
-
-    /**
-     * If the <code>sourceUri</code> is a local content Uri, update the
-     * <code>sourceUri</code> to point to the <code>file</code>.
-     * At the same time, the old file <code>sourceUri</code> used to point to
-     * will be removed if it is local.
-     * If the <code>sourceUri</code> is not a local content Uri, then the
-     * <code>file</code> will be inserted as a new content Uri.
-     * @return the final Uri referring to the <code>file</code>.
-     */
-    public static Uri linkNewFileToUri(Context context, Uri sourceUri,
-            File file, long time, boolean deleteOriginal) {
-        File oldSelectedFile = getLocalFileFromUri(context, sourceUri);
-        final ContentValues values = new ContentValues();
-
-        time /= 1000;
-        values.put(Images.Media.TITLE, file.getName());
-        values.put(Images.Media.DISPLAY_NAME, file.getName());
-        values.put(Images.Media.MIME_TYPE, "image/jpeg");
-        values.put(Images.Media.DATE_TAKEN, time);
-        values.put(Images.Media.DATE_MODIFIED, time);
-        values.put(Images.Media.DATE_ADDED, time);
-        values.put(Images.Media.ORIENTATION, 0);
-        values.put(Images.Media.DATA, file.getAbsolutePath());
-        values.put(Images.Media.SIZE, file.length());
-
-        final String[] projection = new String[] {
-                ImageColumns.DATE_TAKEN,
-                ImageColumns.LATITUDE, ImageColumns.LONGITUDE,
-        };
-        SaveImage.querySource(context, sourceUri, projection,
-                new SaveImage.ContentResolverQueryCallback() {
-
-                    @Override
-                    public void onCursorResult(Cursor cursor) {
-                        values.put(Images.Media.DATE_TAKEN, cursor.getLong(0));
-
-                        double latitude = cursor.getDouble(1);
-                        double longitude = cursor.getDouble(2);
-                        // TODO: Change || to && after the default location
-                        // issue is fixed.
-                        if ((latitude != 0f) || (longitude != 0f)) {
-                            values.put(Images.Media.LATITUDE, latitude);
-                            values.put(Images.Media.LONGITUDE, longitude);
-                        }
-                    }
-                });
-
-        Uri result = sourceUri;
-        if (oldSelectedFile == null || !deleteOriginal) {
-            result = context.getContentResolver().insert(
-                    Images.Media.EXTERNAL_CONTENT_URI, values);
-        } else {
-            context.getContentResolver().update(sourceUri, values, null, null);
-            if (oldSelectedFile.exists()) {
-                oldSelectedFile.delete();
-            }
-        }
-
-        return result;
-    }
-
-}
diff --git a/src/com/android/gallery3d/filtershow/tools/XmpPresets.java b/src/com/android/gallery3d/filtershow/tools/XmpPresets.java
deleted file mode 100644
index 3995eeb..0000000
--- a/src/com/android/gallery3d/filtershow/tools/XmpPresets.java
+++ /dev/null
@@ -1,133 +0,0 @@
-/*
- * Copyright (C) 2013 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.gallery3d.filtershow.tools;
-
-import android.content.Context;
-import android.net.Uri;
-import android.util.Log;
-
-import com.adobe.xmp.XMPException;
-import com.adobe.xmp.XMPMeta;
-import com.adobe.xmp.XMPMetaFactory;
-import com.android.gallery3d.R;
-import com.android.gallery3d.common.Utils;
-import com.android.gallery3d.filtershow.imageshow.MasterImage;
-import com.android.gallery3d.filtershow.pipeline.ImagePreset;
-import com.android.gallery3d.util.XmpUtilHelper;
-
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.InputStream;
-
-public class XmpPresets {
-    public static final String
-            XMP_GOOGLE_FILTER_NAMESPACE = "http://ns.google.com/photos/1.0/filter/";
-    public static final String XMP_GOOGLE_FILTER_PREFIX = "AFltr";
-    public static final String XMP_SRC_FILE_URI = "SourceFileUri";
-    public static final String XMP_FILTERSTACK = "filterstack";
-    private static final String LOGTAG = "XmpPresets";
-
-    public static class XMresults {
-        public String presetString;
-        public ImagePreset preset;
-        public Uri originalimage;
-    }
-
-    static {
-        try {
-            XMPMetaFactory.getSchemaRegistry().registerNamespace(
-                    XMP_GOOGLE_FILTER_NAMESPACE, XMP_GOOGLE_FILTER_PREFIX);
-        } catch (XMPException e) {
-            Log.e(LOGTAG, "Register XMP name space failed", e);
-        }
-    }
-
-    public static void writeFilterXMP(
-            Context context, Uri srcUri, File dstFile, ImagePreset preset) {
-        InputStream is = null;
-        XMPMeta xmpMeta = null;
-        try {
-            is = context.getContentResolver().openInputStream(srcUri);
-            xmpMeta = XmpUtilHelper.extractXMPMeta(is);
-        } catch (FileNotFoundException e) {
-
-        } finally {
-            Utils.closeSilently(is);
-        }
-
-        if (xmpMeta == null) {
-            xmpMeta = XMPMetaFactory.create();
-        }
-        try {
-            xmpMeta.setProperty(XMP_GOOGLE_FILTER_NAMESPACE,
-                    XMP_SRC_FILE_URI, srcUri.toString());
-            xmpMeta.setProperty(XMP_GOOGLE_FILTER_NAMESPACE,
-                    XMP_FILTERSTACK, preset.getJsonString(context.getString(R.string.saved)));
-        } catch (XMPException e) {
-            Log.v(LOGTAG, "Write XMP meta to file failed:" + dstFile.getAbsolutePath());
-            return;
-        }
-
-        if (!XmpUtilHelper.writeXMPMeta(dstFile.getAbsolutePath(), xmpMeta)) {
-            Log.v(LOGTAG, "Write XMP meta to file failed:" + dstFile.getAbsolutePath());
-        }
-    }
-
-    public static XMresults extractXMPData(
-            Context context, MasterImage mMasterImage, Uri uriToEdit) {
-        XMresults ret = new XMresults();
-
-        InputStream is = null;
-        XMPMeta xmpMeta = null;
-        try {
-            is = context.getContentResolver().openInputStream(uriToEdit);
-            xmpMeta = XmpUtilHelper.extractXMPMeta(is);
-        } catch (FileNotFoundException e) {
-        } finally {
-            Utils.closeSilently(is);
-        }
-
-        if (xmpMeta == null) {
-            return null;
-        }
-
-        try {
-            String strSrcUri = xmpMeta.getPropertyString(XMP_GOOGLE_FILTER_NAMESPACE,
-                    XMP_SRC_FILE_URI);
-
-            if (strSrcUri != null) {
-                String filterString = xmpMeta.getPropertyString(XMP_GOOGLE_FILTER_NAMESPACE,
-                        XMP_FILTERSTACK);
-
-                Uri srcUri = Uri.parse(strSrcUri);
-                ret.originalimage = srcUri;
-
-                ret.preset = new ImagePreset(mMasterImage.getPreset());
-                ret.presetString = filterString;
-                boolean ok = ret.preset.readJsonFromString(filterString);
-                if (!ok) {
-                    return null;
-                }
-                return ret;
-            }
-        } catch (XMPException e) {
-            e.printStackTrace();
-        }
-
-        return null;
-    }
-}
diff --git a/src/com/android/gallery3d/filtershow/ui/ExportDialog.java b/src/com/android/gallery3d/filtershow/ui/ExportDialog.java
deleted file mode 100644
index 4b30e7b..0000000
--- a/src/com/android/gallery3d/filtershow/ui/ExportDialog.java
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * Copyright (C) 2013 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.gallery3d.filtershow.ui;
-
-import android.content.Intent;
-import android.net.Uri;
-import android.os.Bundle;
-import android.support.v4.app.DialogFragment;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.SeekBar;
-import android.widget.TextView;
-
-import com.android.gallery3d.R;
-import com.android.gallery3d.filtershow.FilterShowActivity;
-import com.android.gallery3d.filtershow.imageshow.MasterImage;
-import com.android.gallery3d.filtershow.pipeline.ProcessingService;
-import com.android.gallery3d.filtershow.tools.SaveImage;
-
-import java.io.File;
-
-public class ExportDialog extends DialogFragment implements View.OnClickListener, SeekBar.OnSeekBarChangeListener{
-    SeekBar mSeekBar;
-    TextView mSeekVal;
-    String mSliderLabel;
-
-    @Override
-    public View onCreateView(LayoutInflater inflater, ViewGroup container,
-            Bundle savedInstanceState) {
-        View view = inflater.inflate(R.layout.filtershow_export_dialog, container);
-        mSeekBar = (SeekBar) view.findViewById(R.id.qualitySeekBar);
-        mSeekVal = (TextView) view.findViewById(R.id.qualityTextView);
-        mSliderLabel = getString(R.string.quality) + ": ";
-        mSeekVal.setText(mSliderLabel + mSeekBar.getProgress());
-        mSeekBar.setOnSeekBarChangeListener(this);
-        view.findViewById(R.id.cancel).setOnClickListener(this);
-        view.findViewById(R.id.done).setOnClickListener(this);
-        getDialog().setTitle(R.string.export_flattened);
-        return view;
-    }
-
-    @Override
-    public void onStopTrackingTouch(SeekBar arg0) {
-        // Do nothing
-    }
-
-    @Override
-    public void onStartTrackingTouch(SeekBar arg0) {
-     // Do nothing
-    }
-
-    @Override
-    public void onProgressChanged(SeekBar arg0, int arg1, boolean arg2) {
-        mSeekVal.setText(mSliderLabel + arg1);
-    }
-
-    @Override
-    public void onClick(View v) {
-        switch (v.getId()) {
-            case R.id.cancel:
-                dismiss();
-                break;
-            case R.id.done:
-                FilterShowActivity activity = (FilterShowActivity) getActivity();
-                Uri sourceUri = MasterImage.getImage().getUri();
-                File dest = SaveImage.getNewFile(activity, sourceUri);
-                Intent processIntent = ProcessingService.getSaveIntent(activity, MasterImage
-                        .getImage().getPreset(), dest, activity.getSelectedImageUri(), sourceUri,
-                        true, mSeekBar.getProgress());
-                activity.startService(processIntent);
-                dismiss();
-                break;
-        }
-    }
-}
diff --git a/src/com/android/gallery3d/filtershow/ui/FramedTextButton.java b/src/com/android/gallery3d/filtershow/ui/FramedTextButton.java
deleted file mode 100644
index c1e4109..0000000
--- a/src/com/android/gallery3d/filtershow/ui/FramedTextButton.java
+++ /dev/null
@@ -1,137 +0,0 @@
-/*
- * 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.gallery3d.filtershow.ui;
-
-import android.content.Context;
-import android.content.res.TypedArray;
-import android.graphics.Canvas;
-import android.graphics.Paint;
-import android.graphics.Path;
-import android.graphics.Rect;
-import android.util.AttributeSet;
-import android.widget.ImageButton;
-
-import com.android.gallery3d.R;
-
-public class FramedTextButton extends ImageButton {
-    private static final String LOGTAG = "FramedTextButton";
-    private String mText = null;
-    private static int mTextSize = 24;
-    private static int mTextPadding = 20;
-    private static Paint gPaint = new Paint();
-    private static Path gPath = new Path();
-    private static int mTrianglePadding = 2;
-    private static int mTriangleSize = 30;
-
-    public static void setTextSize(int value) {
-        mTextSize = value;
-    }
-
-    public static void setTextPadding(int value) {
-        mTextPadding = value;
-    }
-
-    public static void setTrianglePadding(int value) {
-        mTrianglePadding = value;
-    }
-
-    public static void setTriangleSize(int value) {
-        mTriangleSize = value;
-    }
-
-    public void setText(String text) {
-        mText = text;
-        invalidate();
-    }
-
-    public void setTextFrom(int itemId) {
-        switch (itemId) {
-            case R.id.curve_menu_rgb: {
-                setText(getContext().getString(R.string.curves_channel_rgb));
-                break;
-            }
-            case R.id.curve_menu_red: {
-                setText(getContext().getString(R.string.curves_channel_red));
-                break;
-            }
-            case R.id.curve_menu_green: {
-                setText(getContext().getString(R.string.curves_channel_green));
-                break;
-            }
-            case R.id.curve_menu_blue: {
-                setText(getContext().getString(R.string.curves_channel_blue));
-                break;
-            }
-        }
-        invalidate();
-    }
-
-    public FramedTextButton(Context context) {
-        this(context, null);
-    }
-
-    public FramedTextButton(Context context, AttributeSet attrs) {
-        super(context, attrs);
-        if (attrs == null) {
-            return;
-        }
-        TypedArray a = getContext().obtainStyledAttributes(
-                attrs, R.styleable.ImageButtonTitle);
-
-        mText = a.getString(R.styleable.ImageButtonTitle_android_text);
-    }
-
-    public String getText(){
-        return mText;
-    }
-
-    @Override
-    public void onDraw(Canvas canvas) {
-        gPaint.setARGB(96, 255, 255, 255);
-        gPaint.setStrokeWidth(2);
-        gPaint.setStyle(Paint.Style.STROKE);
-        int w = getWidth();
-        int h = getHeight();
-        canvas.drawRect(mTextPadding, mTextPadding, w - mTextPadding,
-                h - mTextPadding, gPaint);
-        gPath.reset();
-        gPath.moveTo(w - mTextPadding - mTrianglePadding - mTriangleSize,
-                     h - mTextPadding - mTrianglePadding);
-        gPath.lineTo(w - mTextPadding - mTrianglePadding,
-                     h - mTextPadding - mTrianglePadding - mTriangleSize);
-        gPath.lineTo(w - mTextPadding - mTrianglePadding,
-                     h - mTextPadding - mTrianglePadding);
-        gPath.close();
-        gPaint.setARGB(128, 255, 255, 255);
-        gPaint.setStrokeWidth(1);
-        gPaint.setStyle(Paint.Style.FILL_AND_STROKE);
-        canvas.drawPath(gPath, gPaint);
-        if (mText != null) {
-            gPaint.reset();
-            gPaint.setARGB(255, 255, 255, 255);
-            gPaint.setTextSize(mTextSize);
-            float textWidth = gPaint.measureText(mText);
-            Rect bounds = new Rect();
-            gPaint.getTextBounds(mText, 0, mText.length(), bounds);
-            int x = (int) ((w - textWidth) / 2);
-            int y = (h + bounds.height()) / 2;
-
-            canvas.drawText(mText, x, y, gPaint);
-        }
-    }
-
-}
diff --git a/src/com/android/gallery3d/filtershow/ui/SelectionRenderer.java b/src/com/android/gallery3d/filtershow/ui/SelectionRenderer.java
deleted file mode 100644
index ef40c5e..0000000
--- a/src/com/android/gallery3d/filtershow/ui/SelectionRenderer.java
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Copyright (C) 2013 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.gallery3d.filtershow.ui;
-
-import android.graphics.Canvas;
-import android.graphics.Paint;
-
-public class SelectionRenderer {
-
-    public static void drawSelection(Canvas canvas, int left, int top, int right, int bottom,
-            int stroke, Paint paint) {
-        canvas.drawRect(left, top, right, top + stroke, paint);
-        canvas.drawRect(left, bottom - stroke, right, bottom, paint);
-        canvas.drawRect(left, top, left + stroke, bottom, paint);
-        canvas.drawRect(right - stroke, top, right, bottom, paint);
-    }
-
-    public static void drawSelection(Canvas canvas, int left, int top, int right, int bottom,
-            int stroke, Paint selectPaint, int border, Paint borderPaint) {
-        canvas.drawRect(left, top, right, top + stroke, selectPaint);
-        canvas.drawRect(left, bottom - stroke, right, bottom, selectPaint);
-        canvas.drawRect(left, top, left + stroke, bottom, selectPaint);
-        canvas.drawRect(right - stroke, top, right, bottom, selectPaint);
-        canvas.drawRect(left + stroke, top + stroke, right - stroke,
-                top + stroke + border, borderPaint);
-        canvas.drawRect(left + stroke, bottom - stroke - border, right - stroke,
-                bottom - stroke, borderPaint);
-        canvas.drawRect(left + stroke, top + stroke, left + stroke + border,
-                bottom - stroke, borderPaint);
-        canvas.drawRect(right - stroke - border, top + stroke, right - stroke,
-                bottom - stroke, borderPaint);
-    }
-
-}
diff --git a/src/com/android/gallery3d/gadget/LocalPhotoSource.java b/src/com/android/gallery3d/gadget/LocalPhotoSource.java
deleted file mode 100644
index 4e94e8d..0000000
--- a/src/com/android/gallery3d/gadget/LocalPhotoSource.java
+++ /dev/null
@@ -1,205 +0,0 @@
-/*
- * Copyright (C) 2011 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.gallery3d.gadget;
-
-import android.content.ContentResolver;
-import android.content.Context;
-import android.database.ContentObserver;
-import android.database.Cursor;
-import android.graphics.Bitmap;
-import android.net.Uri;
-import android.os.Environment;
-import android.os.Handler;
-import android.provider.MediaStore.Images.Media;
-
-import com.android.gallery3d.app.GalleryApp;
-import com.android.gallery3d.common.Utils;
-import com.android.gallery3d.data.ContentListener;
-import com.android.gallery3d.data.DataManager;
-import com.android.gallery3d.data.MediaItem;
-import com.android.gallery3d.data.Path;
-import com.android.gallery3d.util.GalleryUtils;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.HashSet;
-import java.util.Random;
-
-public class LocalPhotoSource implements WidgetSource {
-
-    @SuppressWarnings("unused")
-    private static final String TAG = "LocalPhotoSource";
-
-    private static final int MAX_PHOTO_COUNT = 128;
-
-    /* Static fields used to query for the correct set of images */
-    private static final Uri CONTENT_URI = Media.EXTERNAL_CONTENT_URI;
-    private static final String DATE_TAKEN = Media.DATE_TAKEN;
-    private static final String[] PROJECTION = {Media._ID};
-    private static final String[] COUNT_PROJECTION = {"count(*)"};
-    /* We don't want to include the download directory */
-    private static final String SELECTION =
-            String.format("%s != %s", Media.BUCKET_ID, getDownloadBucketId());
-    private static final String ORDER = String.format("%s DESC", DATE_TAKEN);
-
-    private Context mContext;
-    private ArrayList<Long> mPhotos = new ArrayList<Long>();
-    private ContentListener mContentListener;
-    private ContentObserver mContentObserver;
-    private boolean mContentDirty = true;
-    private DataManager mDataManager;
-    private static final Path LOCAL_IMAGE_ROOT = Path.fromString("/local/image/item");
-
-    public LocalPhotoSource(Context context) {
-        mContext = context;
-        mDataManager = ((GalleryApp) context.getApplicationContext()).getDataManager();
-        mContentObserver = new ContentObserver(new Handler()) {
-            @Override
-            public void onChange(boolean selfChange) {
-                mContentDirty = true;
-                if (mContentListener != null) mContentListener.onContentDirty();
-            }
-        };
-        mContext.getContentResolver()
-                .registerContentObserver(CONTENT_URI, true, mContentObserver);
-    }
-
-    @Override
-    public void close() {
-        mContext.getContentResolver().unregisterContentObserver(mContentObserver);
-    }
-
-    @Override
-    public Uri getContentUri(int index) {
-        if (index < mPhotos.size()) {
-            return CONTENT_URI.buildUpon()
-                    .appendPath(String.valueOf(mPhotos.get(index)))
-                    .build();
-        }
-        return null;
-    }
-
-    @Override
-    public Bitmap getImage(int index) {
-        if (index >= mPhotos.size()) return null;
-        long id = mPhotos.get(index);
-        MediaItem image = (MediaItem)
-                mDataManager.getMediaObject(LOCAL_IMAGE_ROOT.getChild(id));
-        if (image == null) return null;
-
-        return WidgetUtils.createWidgetBitmap(image);
-    }
-
-    private int[] getExponentialIndice(int total, int count) {
-        Random random = new Random();
-        if (count > total) count = total;
-        HashSet<Integer> selected = new HashSet<Integer>(count);
-        while (selected.size() < count) {
-            int row = (int)(-Math.log(random.nextDouble()) * total / 2);
-            if (row < total) selected.add(row);
-        }
-        int values[] = new int[count];
-        int index = 0;
-        for (int value : selected) {
-            values[index++] = value;
-        }
-        return values;
-    }
-
-    private int getPhotoCount(ContentResolver resolver) {
-        Cursor cursor = resolver.query(
-                CONTENT_URI, COUNT_PROJECTION, SELECTION, null, null);
-        if (cursor == null) return 0;
-        try {
-            Utils.assertTrue(cursor.moveToNext());
-            return cursor.getInt(0);
-        } finally {
-            cursor.close();
-        }
-    }
-
-    private boolean isContentSound(int totalCount) {
-        if (mPhotos.size() < Math.min(totalCount, MAX_PHOTO_COUNT)) return false;
-        if (mPhotos.size() == 0) return true; // totalCount is also 0
-
-        StringBuilder builder = new StringBuilder();
-        for (Long imageId : mPhotos) {
-            if (builder.length() > 0) builder.append(",");
-            builder.append(imageId);
-        }
-        Cursor cursor = mContext.getContentResolver().query(
-                CONTENT_URI, COUNT_PROJECTION,
-                String.format("%s in (%s)", Media._ID, builder.toString()),
-                null, null);
-        if (cursor == null) return false;
-        try {
-            Utils.assertTrue(cursor.moveToNext());
-            return cursor.getInt(0) == mPhotos.size();
-        } finally {
-            cursor.close();
-        }
-    }
-
-    @Override
-    public void reload() {
-        if (!mContentDirty) return;
-        mContentDirty = false;
-
-        ContentResolver resolver = mContext.getContentResolver();
-        int photoCount = getPhotoCount(resolver);
-        if (isContentSound(photoCount)) return;
-
-        int choosedIds[] = getExponentialIndice(photoCount, MAX_PHOTO_COUNT);
-        Arrays.sort(choosedIds);
-
-        mPhotos.clear();
-        Cursor cursor = mContext.getContentResolver().query(
-                CONTENT_URI, PROJECTION, SELECTION, null, ORDER);
-        if (cursor == null) return;
-        try {
-            for (int index : choosedIds) {
-                if (cursor.moveToPosition(index)) {
-                    mPhotos.add(cursor.getLong(0));
-                }
-            }
-        } finally {
-            cursor.close();
-        }
-    }
-
-    @Override
-    public int size() {
-        reload();
-        return mPhotos.size();
-    }
-
-    /**
-     * Builds the bucket ID for the public external storage Downloads directory
-     * @return the bucket ID
-     */
-    private static int getDownloadBucketId() {
-        String downloadsPath = Environment
-                .getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS)
-                .getAbsolutePath();
-        return GalleryUtils.getBucketId(downloadsPath);
-    }
-
-    @Override
-    public void setContentListener(ContentListener listener) {
-        mContentListener = listener;
-    }
-}
diff --git a/src/com/android/gallery3d/gadget/MediaSetSource.java b/src/com/android/gallery3d/gadget/MediaSetSource.java
deleted file mode 100644
index 458651c..0000000
--- a/src/com/android/gallery3d/gadget/MediaSetSource.java
+++ /dev/null
@@ -1,233 +0,0 @@
-/*
- * Copyright (C) 2011 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.gallery3d.gadget;
-
-import android.graphics.Bitmap;
-import android.net.Uri;
-import android.os.Binder;
-
-import com.android.gallery3d.common.Utils;
-import com.android.gallery3d.data.ContentListener;
-import com.android.gallery3d.data.DataManager;
-import com.android.gallery3d.data.MediaItem;
-import com.android.gallery3d.data.MediaObject;
-import com.android.gallery3d.data.MediaSet;
-import com.android.gallery3d.data.Path;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-
-public class MediaSetSource implements WidgetSource, ContentListener {
-    private static final String TAG = "MediaSetSource";
-
-    private DataManager mDataManager;
-    private Path mAlbumPath;
-
-    private WidgetSource mSource;
-
-    private MediaSet mRootSet;
-    private ContentListener mListener;
-
-    public MediaSetSource(DataManager manager, String albumPath) {
-        MediaSet mediaSet = (MediaSet) manager.getMediaObject(albumPath);
-        if (mediaSet != null) {
-            mSource = new CheckedMediaSetSource(mediaSet);
-            return;
-        }
-
-        // Initialize source to an empty source until the album path can be resolved
-        mDataManager = Utils.checkNotNull(manager);
-        mAlbumPath = Path.fromString(albumPath);
-        mSource = new EmptySource();
-        monitorRootPath();
-    }
-
-    @Override
-    public int size() {
-        return mSource.size();
-    }
-
-    @Override
-    public Bitmap getImage(int index) {
-        return mSource.getImage(index);
-    }
-
-    @Override
-    public Uri getContentUri(int index) {
-        return mSource.getContentUri(index);
-    }
-
-    @Override
-    public synchronized void setContentListener(ContentListener listener) {
-        if (mRootSet != null) {
-            mListener = listener;
-        } else {
-            mSource.setContentListener(listener);
-        }
-    }
-
-    @Override
-    public void reload() {
-        mSource.reload();
-    }
-
-    @Override
-    public void close() {
-        mSource.close();
-    }
-
-    @Override
-    public void onContentDirty() {
-        resolveAlbumPath();
-    }
-
-    private void monitorRootPath() {
-        String rootPath = mDataManager.getTopSetPath(DataManager.INCLUDE_ALL);
-        mRootSet = (MediaSet) mDataManager.getMediaObject(rootPath);
-        mRootSet.addContentListener(this);
-    }
-
-    private synchronized void resolveAlbumPath() {
-        if (mDataManager == null) return;
-        MediaSet mediaSet = (MediaSet) mDataManager.getMediaObject(mAlbumPath);
-        if (mediaSet != null) {
-            // Clear the reference instead of removing the listener
-            // to get around a concurrent modification exception.
-            mRootSet = null;
-
-            mSource = new CheckedMediaSetSource(mediaSet);
-            if (mListener != null) {
-                mListener.onContentDirty();
-                mSource.setContentListener(mListener);
-                mListener = null;
-            }
-            mDataManager = null;
-            mAlbumPath = null;
-        }
-    }
-
-    private static class CheckedMediaSetSource implements WidgetSource, ContentListener {
-        private static final int CACHE_SIZE = 32;
-
-        @SuppressWarnings("unused")
-        private static final String TAG = "CheckedMediaSetSource";
-
-        private MediaSet mSource;
-        private MediaItem mCache[] = new MediaItem[CACHE_SIZE];
-        private int mCacheStart;
-        private int mCacheEnd;
-        private long mSourceVersion = MediaObject.INVALID_DATA_VERSION;
-
-        private ContentListener mContentListener;
-
-        public CheckedMediaSetSource(MediaSet source) {
-            mSource = Utils.checkNotNull(source);
-            mSource.addContentListener(this);
-        }
-
-        @Override
-        public void close() {
-            mSource.removeContentListener(this);
-        }
-
-        private void ensureCacheRange(int index) {
-            if (index >= mCacheStart && index < mCacheEnd) return;
-
-            long token = Binder.clearCallingIdentity();
-            try {
-                mCacheStart = index;
-                ArrayList<MediaItem> items = mSource.getMediaItem(mCacheStart, CACHE_SIZE);
-                mCacheEnd = mCacheStart + items.size();
-                items.toArray(mCache);
-            } finally {
-                Binder.restoreCallingIdentity(token);
-            }
-        }
-
-        @Override
-        public synchronized Uri getContentUri(int index) {
-            ensureCacheRange(index);
-            if (index < mCacheStart || index >= mCacheEnd) return null;
-            return mCache[index - mCacheStart].getContentUri();
-        }
-
-        @Override
-        public synchronized Bitmap getImage(int index) {
-            ensureCacheRange(index);
-            if (index < mCacheStart || index >= mCacheEnd) return null;
-            return WidgetUtils.createWidgetBitmap(mCache[index - mCacheStart]);
-        }
-
-        @Override
-        public void reload() {
-            long version = mSource.reload();
-            if (mSourceVersion != version) {
-                mSourceVersion = version;
-                mCacheStart = 0;
-                mCacheEnd = 0;
-                Arrays.fill(mCache, null);
-            }
-        }
-
-        @Override
-        public void setContentListener(ContentListener listener) {
-            mContentListener = listener;
-        }
-
-        @Override
-        public int size() {
-            long token = Binder.clearCallingIdentity();
-            try {
-                return mSource.getMediaItemCount();
-            } finally {
-                Binder.restoreCallingIdentity(token);
-            }
-        }
-
-        @Override
-        public void onContentDirty() {
-            if (mContentListener != null) mContentListener.onContentDirty();
-        }
-    }
-
-    private static class EmptySource implements WidgetSource {
-
-        @Override
-        public int size() {
-            return 0;
-        }
-
-        @Override
-        public Bitmap getImage(int index) {
-            throw new UnsupportedOperationException();
-        }
-
-        @Override
-        public Uri getContentUri(int index) {
-            throw new UnsupportedOperationException();
-        }
-
-        @Override
-        public void setContentListener(ContentListener listener) {}
-
-        @Override
-        public void reload() {}
-
-        @Override
-        public void close() {}
-    }
-}
diff --git a/src/com/android/gallery3d/gadget/PhotoAppWidgetProvider.java b/src/com/android/gallery3d/gadget/PhotoAppWidgetProvider.java
deleted file mode 100644
index 58466bf..0000000
--- a/src/com/android/gallery3d/gadget/PhotoAppWidgetProvider.java
+++ /dev/null
@@ -1,139 +0,0 @@
-/*
- * Copyright (C) 2010 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.gallery3d.gadget;
-
-import android.annotation.TargetApi;
-import android.app.PendingIntent;
-import android.appwidget.AppWidgetManager;
-import android.appwidget.AppWidgetProvider;
-import android.content.Context;
-import android.content.Intent;
-import android.graphics.Bitmap;
-import android.graphics.BitmapFactory;
-import android.net.Uri;
-import android.util.Log;
-import android.widget.RemoteViews;
-
-import com.android.gallery3d.R;
-import com.android.gallery3d.common.ApiHelper;
-import com.android.gallery3d.gadget.WidgetDatabaseHelper.Entry;
-import com.android.gallery3d.onetimeinitializer.GalleryWidgetMigrator;
-
-public class PhotoAppWidgetProvider extends AppWidgetProvider {
-
-    private static final String TAG = "WidgetProvider";
-
-    static RemoteViews buildWidget(Context context, int id, Entry entry) {
-
-        switch (entry.type) {
-            case WidgetDatabaseHelper.TYPE_ALBUM:
-            case WidgetDatabaseHelper.TYPE_SHUFFLE:
-                return buildStackWidget(context, id, entry);
-            case WidgetDatabaseHelper.TYPE_SINGLE_PHOTO:
-                return buildFrameWidget(context, id, entry);
-        }
-        throw new RuntimeException("invalid type - " + entry.type);
-    }
-
-    @Override
-    public void onUpdate(Context context,
-            AppWidgetManager appWidgetManager, int[] appWidgetIds) {
-
-        if (ApiHelper.HAS_REMOTE_VIEWS_SERVICE) {
-            // migrate gallery widgets from pre-JB releases to JB due to bucket ID change
-            GalleryWidgetMigrator.migrateGalleryWidgets(context);
-        }
-
-        WidgetDatabaseHelper helper = new WidgetDatabaseHelper(context);
-        try {
-            for (int id : appWidgetIds) {
-                Entry entry = helper.getEntry(id);
-                if (entry != null) {
-                    RemoteViews views = buildWidget(context, id, entry);
-                    appWidgetManager.updateAppWidget(id, views);
-                } else {
-                    Log.e(TAG, "cannot load widget: " + id);
-                }
-            }
-        } finally {
-            helper.close();
-        }
-        super.onUpdate(context, appWidgetManager, appWidgetIds);
-    }
-
-    @SuppressWarnings("deprecation")
-    @TargetApi(ApiHelper.VERSION_CODES.HONEYCOMB)
-    private static RemoteViews buildStackWidget(Context context, int widgetId, Entry entry) {
-        RemoteViews views = new RemoteViews(
-                context.getPackageName(), R.layout.appwidget_main);
-
-        Intent intent = new Intent(context, WidgetService.class);
-        intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, widgetId);
-        intent.putExtra(WidgetService.EXTRA_WIDGET_TYPE, entry.type);
-        intent.putExtra(WidgetService.EXTRA_ALBUM_PATH, entry.albumPath);
-        intent.setData(Uri.parse("widget://gallery/" + widgetId));
-
-        // We use the deprecated API for backward compatibility
-        // The new API is available in ICE_CREAM_SANDWICH (15)
-        views.setRemoteAdapter(widgetId, R.id.appwidget_stack_view, intent);
-
-        views.setEmptyView(R.id.appwidget_stack_view, R.id.appwidget_empty_view);
-
-        Intent clickIntent = new Intent(context, WidgetClickHandler.class);
-        PendingIntent pendingIntent = PendingIntent.getActivity(
-                context, 0, clickIntent, PendingIntent.FLAG_UPDATE_CURRENT);
-        views.setPendingIntentTemplate(R.id.appwidget_stack_view, pendingIntent);
-
-        return views;
-    }
-
-    static RemoteViews buildFrameWidget(Context context, int appWidgetId, Entry entry) {
-        RemoteViews views = new RemoteViews(
-                context.getPackageName(), R.layout.photo_frame);
-        try {
-            byte[] data = entry.imageData;
-            Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0, data.length);
-            views.setImageViewBitmap(R.id.photo, bitmap);
-        } catch (Throwable t) {
-            Log.w(TAG, "cannot load widget image: " + appWidgetId, t);
-        }
-
-        if (entry.imageUri != null) {
-            try {
-                Uri uri = Uri.parse(entry.imageUri);
-                Intent clickIntent = new Intent(context, WidgetClickHandler.class)
-                        .setData(uri);
-                PendingIntent pendingClickIntent = PendingIntent.getActivity(context, 0,
-                        clickIntent, PendingIntent.FLAG_CANCEL_CURRENT);
-                views.setOnClickPendingIntent(R.id.photo, pendingClickIntent);
-            } catch (Throwable t) {
-                Log.w(TAG, "cannot load widget uri: " + appWidgetId, t);
-            }
-        }
-        return views;
-    }
-
-    @Override
-    public void onDeleted(Context context, int[] appWidgetIds) {
-        // Clean deleted photos out of our database
-        WidgetDatabaseHelper helper = new WidgetDatabaseHelper(context);
-        for (int appWidgetId : appWidgetIds) {
-            helper.deleteEntry(appWidgetId);
-        }
-        helper.close();
-    }
-}
diff --git a/src/com/android/gallery3d/gadget/WidgetClickHandler.java b/src/com/android/gallery3d/gadget/WidgetClickHandler.java
deleted file mode 100644
index 37ee1a6..0000000
--- a/src/com/android/gallery3d/gadget/WidgetClickHandler.java
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * Copyright (C) 2009 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.gallery3d.gadget;
-
-import android.annotation.TargetApi;
-import android.app.Activity;
-import android.content.Intent;
-import android.content.res.AssetFileDescriptor;
-import android.net.Uri;
-import android.os.Build;
-import android.os.Bundle;
-import android.util.Log;
-import android.widget.Toast;
-
-import com.android.gallery3d.R;
-import com.android.gallery3d.app.Gallery;
-import com.android.gallery3d.app.PhotoPage;
-import com.android.gallery3d.common.ApiHelper;
-
-public class WidgetClickHandler extends Activity {
-    private static final String TAG = "PhotoAppWidgetClickHandler";
-
-    private boolean isValidDataUri(Uri dataUri) {
-        if (dataUri == null) return false;
-        try {
-            AssetFileDescriptor f = getContentResolver()
-                    .openAssetFileDescriptor(dataUri, "r");
-            f.close();
-            return true;
-        } catch (Throwable e) {
-            Log.w(TAG, "cannot open uri: " + dataUri, e);
-            return false;
-        }
-    }
-
-    @Override
-    @TargetApi(ApiHelper.VERSION_CODES.HONEYCOMB)
-    protected void onCreate(Bundle savedState) {
-        super.onCreate(savedState);
-        // The behavior is changed in JB, refer to b/6384492 for more details
-        boolean tediousBack = Build.VERSION.SDK_INT >= ApiHelper.VERSION_CODES.JELLY_BEAN;
-        Uri uri = getIntent().getData();
-        Intent intent;
-        if (isValidDataUri(uri)) {
-            intent = new Intent(Intent.ACTION_VIEW, uri);
-            if (tediousBack) {
-                intent.putExtra(PhotoPage.KEY_TREAT_BACK_AS_UP, true);
-            }
-        } else {
-            Toast.makeText(this,
-                    R.string.no_such_item, Toast.LENGTH_LONG).show();
-            intent = new Intent(this, Gallery.class);
-        }
-        if (tediousBack) {
-            intent.setFlags(
-                    Intent.FLAG_ACTIVITY_NEW_TASK |
-                    Intent.FLAG_ACTIVITY_CLEAR_TASK |
-                    Intent.FLAG_ACTIVITY_TASK_ON_HOME);
-        }
-        startActivity(intent);
-        finish();
-    }
-}
diff --git a/src/com/android/gallery3d/gadget/WidgetConfigure.java b/src/com/android/gallery3d/gadget/WidgetConfigure.java
deleted file mode 100644
index 2a4c6cf..0000000
--- a/src/com/android/gallery3d/gadget/WidgetConfigure.java
+++ /dev/null
@@ -1,209 +0,0 @@
-/*
- * Copyright (C) 2011 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.gallery3d.gadget;
-
-import android.app.Activity;
-import android.appwidget.AppWidgetManager;
-import android.content.Intent;
-import android.content.res.Resources;
-import android.graphics.Bitmap;
-import android.net.Uri;
-import android.os.Bundle;
-import android.util.Log;
-import android.widget.RemoteViews;
-
-import com.android.gallery3d.R;
-import com.android.gallery3d.app.AlbumPicker;
-import com.android.gallery3d.app.DialogPicker;
-import com.android.gallery3d.app.GalleryApp;
-import com.android.gallery3d.common.ApiHelper;
-import com.android.gallery3d.data.DataManager;
-import com.android.gallery3d.data.LocalAlbum;
-import com.android.gallery3d.data.MediaSet;
-import com.android.gallery3d.data.Path;
-import com.android.gallery3d.filtershow.crop.CropActivity;
-import com.android.gallery3d.filtershow.crop.CropExtras;
-
-public class WidgetConfigure extends Activity {
-    @SuppressWarnings("unused")
-    private static final String TAG = "WidgetConfigure";
-
-    public static final String KEY_WIDGET_TYPE = "widget-type";
-    private static final String KEY_PICKED_ITEM = "picked-item";
-
-    private static final int REQUEST_WIDGET_TYPE = 1;
-    private static final int REQUEST_CHOOSE_ALBUM = 2;
-    private static final int REQUEST_CROP_IMAGE = 3;
-    private static final int REQUEST_GET_PHOTO = 4;
-
-    public static final int RESULT_ERROR = RESULT_FIRST_USER;
-
-    // Scale up the widget size since we only specified the minimized
-    // size of the gadget. The real size could be larger.
-    // Note: There is also a limit on the size of data that can be
-    // passed in Binder's transaction.
-    private static float WIDGET_SCALE_FACTOR = 1.5f;
-    private static int MAX_WIDGET_SIDE = 360;
-
-    private int mAppWidgetId = -1;
-    private Uri mPickedItem;
-
-    @Override
-    protected void onCreate(Bundle savedState) {
-        super.onCreate(savedState);
-        mAppWidgetId = getIntent().getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, -1);
-
-        if (mAppWidgetId == -1) {
-            setResult(Activity.RESULT_CANCELED);
-            finish();
-            return;
-        }
-
-        if (savedState == null) {
-            if (ApiHelper.HAS_REMOTE_VIEWS_SERVICE) {
-                Intent intent = new Intent(this, WidgetTypeChooser.class);
-                startActivityForResult(intent, REQUEST_WIDGET_TYPE);
-            } else { // Choose the photo type widget
-                setWidgetType(new Intent()
-                        .putExtra(KEY_WIDGET_TYPE, R.id.widget_type_photo));
-            }
-        } else {
-            mPickedItem = savedState.getParcelable(KEY_PICKED_ITEM);
-        }
-    }
-
-    protected void onSaveInstanceStates(Bundle outState) {
-        super.onSaveInstanceState(outState);
-        outState.putParcelable(KEY_PICKED_ITEM, mPickedItem);
-    }
-
-    private void updateWidgetAndFinish(WidgetDatabaseHelper.Entry entry) {
-        AppWidgetManager manager = AppWidgetManager.getInstance(this);
-        RemoteViews views = PhotoAppWidgetProvider.buildWidget(this, mAppWidgetId, entry);
-        manager.updateAppWidget(mAppWidgetId, views);
-        setResult(RESULT_OK, new Intent().putExtra(
-                AppWidgetManager.EXTRA_APPWIDGET_ID, mAppWidgetId));
-        finish();
-    }
-
-    @Override
-    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
-        if (resultCode != RESULT_OK) {
-            setResult(resultCode, new Intent().putExtra(
-                    AppWidgetManager.EXTRA_APPWIDGET_ID, mAppWidgetId));
-            finish();
-            return;
-        }
-
-        if (requestCode == REQUEST_WIDGET_TYPE) {
-            setWidgetType(data);
-        } else if (requestCode == REQUEST_CHOOSE_ALBUM) {
-            setChoosenAlbum(data);
-        } else if (requestCode == REQUEST_GET_PHOTO) {
-            setChoosenPhoto(data);
-        } else if (requestCode == REQUEST_CROP_IMAGE) {
-            setPhotoWidget(data);
-        } else {
-            throw new AssertionError("unknown request: " + requestCode);
-        }
-    }
-
-    private void setPhotoWidget(Intent data) {
-        // Store the cropped photo in our database
-        Bitmap bitmap = (Bitmap) data.getParcelableExtra("data");
-        WidgetDatabaseHelper helper = new WidgetDatabaseHelper(this);
-        try {
-            helper.setPhoto(mAppWidgetId, mPickedItem, bitmap);
-            updateWidgetAndFinish(helper.getEntry(mAppWidgetId));
-        } finally {
-            helper.close();
-        }
-    }
-
-    private void setChoosenPhoto(Intent data) {
-        Resources res = getResources();
-
-        float width = res.getDimension(R.dimen.appwidget_width);
-        float height = res.getDimension(R.dimen.appwidget_height);
-
-        // We try to crop a larger image (by scale factor), but there is still
-        // a bound on the binder limit.
-        float scale = Math.min(WIDGET_SCALE_FACTOR,
-                MAX_WIDGET_SIDE / Math.max(width, height));
-
-        int widgetWidth = Math.round(width * scale);
-        int widgetHeight = Math.round(height * scale);
-
-        mPickedItem = data.getData();
-        Intent request = new Intent(CropActivity.CROP_ACTION, mPickedItem)
-                .putExtra(CropExtras.KEY_OUTPUT_X, widgetWidth)
-                .putExtra(CropExtras.KEY_OUTPUT_Y, widgetHeight)
-                .putExtra(CropExtras.KEY_ASPECT_X, widgetWidth)
-                .putExtra(CropExtras.KEY_ASPECT_Y, widgetHeight)
-                .putExtra(CropExtras.KEY_SCALE_UP_IF_NEEDED, true)
-                .putExtra(CropExtras.KEY_SCALE, true)
-                .putExtra(CropExtras.KEY_RETURN_DATA, true);
-        startActivityForResult(request, REQUEST_CROP_IMAGE);
-    }
-
-    private void setChoosenAlbum(Intent data) {
-        String albumPath = data.getStringExtra(AlbumPicker.KEY_ALBUM_PATH);
-        WidgetDatabaseHelper helper = new WidgetDatabaseHelper(this);
-        try {
-            String relativePath = null;
-            GalleryApp galleryApp = (GalleryApp) getApplicationContext();
-            DataManager manager = galleryApp.getDataManager();
-            Path path = Path.fromString(albumPath);
-            MediaSet mediaSet = (MediaSet) manager.getMediaObject(path);
-            if (mediaSet instanceof LocalAlbum) {
-                int bucketId = Integer.parseInt(path.getSuffix());
-                // If the chosen album is a local album, find relative path
-                // Otherwise, leave the relative path field empty
-                relativePath = LocalAlbum.getRelativePath(bucketId);
-                Log.i(TAG, "Setting widget, album path: " + albumPath
-                        + ", relative path: " + relativePath);
-            }
-            helper.setWidget(mAppWidgetId,
-                    WidgetDatabaseHelper.TYPE_ALBUM, albumPath, relativePath);
-            updateWidgetAndFinish(helper.getEntry(mAppWidgetId));
-        } finally {
-            helper.close();
-        }
-    }
-
-    private void setWidgetType(Intent data) {
-        int widgetType = data.getIntExtra(KEY_WIDGET_TYPE, R.id.widget_type_shuffle);
-        if (widgetType == R.id.widget_type_album) {
-            Intent intent = new Intent(this, AlbumPicker.class);
-            startActivityForResult(intent, REQUEST_CHOOSE_ALBUM);
-        } else if (widgetType == R.id.widget_type_shuffle) {
-            WidgetDatabaseHelper helper = new WidgetDatabaseHelper(this);
-            try {
-                helper.setWidget(mAppWidgetId, WidgetDatabaseHelper.TYPE_SHUFFLE, null, null);
-                updateWidgetAndFinish(helper.getEntry(mAppWidgetId));
-            } finally {
-                helper.close();
-            }
-        } else {
-            // Explicitly send the intent to the DialogPhotoPicker
-            Intent request = new Intent(this, DialogPicker.class)
-                    .setAction(Intent.ACTION_GET_CONTENT)
-                    .setType("image/*");
-            startActivityForResult(request, REQUEST_GET_PHOTO);
-        }
-    }
-}
diff --git a/src/com/android/gallery3d/gadget/WidgetDatabaseHelper.java b/src/com/android/gallery3d/gadget/WidgetDatabaseHelper.java
deleted file mode 100644
index c014584..0000000
--- a/src/com/android/gallery3d/gadget/WidgetDatabaseHelper.java
+++ /dev/null
@@ -1,309 +0,0 @@
-/*
- * Copyright (C) 2010 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.gallery3d.gadget;
-
-import android.content.ContentValues;
-import android.content.Context;
-import android.database.Cursor;
-import android.database.sqlite.SQLiteDatabase;
-import android.database.sqlite.SQLiteException;
-import android.database.sqlite.SQLiteOpenHelper;
-import android.graphics.Bitmap;
-import android.net.Uri;
-import android.util.Log;
-
-import com.android.gallery3d.common.Utils;
-
-import java.io.ByteArrayOutputStream;
-import java.util.ArrayList;
-import java.util.List;
-
-public class WidgetDatabaseHelper extends SQLiteOpenHelper {
-    private static final String TAG = "PhotoDatabaseHelper";
-    private static final String DATABASE_NAME = "launcher.db";
-
-    // Increment the database version to 5. In version 5, we
-    // add a column in widgets table to record relative paths.
-    private static final int DATABASE_VERSION = 5;
-
-    private static final String TABLE_WIDGETS = "widgets";
-
-    private static final String FIELD_APPWIDGET_ID = "appWidgetId";
-    private static final String FIELD_IMAGE_URI = "imageUri";
-    private static final String FIELD_PHOTO_BLOB = "photoBlob";
-    private static final String FIELD_WIDGET_TYPE = "widgetType";
-    private static final String FIELD_ALBUM_PATH = "albumPath";
-    private static final String FIELD_RELATIVE_PATH = "relativePath";
-
-    public static final int TYPE_SINGLE_PHOTO = 0;
-    public static final int TYPE_SHUFFLE = 1;
-    public static final int TYPE_ALBUM = 2;
-
-    private static final String[] PROJECTION = {
-            FIELD_WIDGET_TYPE, FIELD_IMAGE_URI, FIELD_PHOTO_BLOB, FIELD_ALBUM_PATH,
-            FIELD_APPWIDGET_ID, FIELD_RELATIVE_PATH};
-    private static final int INDEX_WIDGET_TYPE = 0;
-    private static final int INDEX_IMAGE_URI = 1;
-    private static final int INDEX_PHOTO_BLOB = 2;
-    private static final int INDEX_ALBUM_PATH = 3;
-    private static final int INDEX_APPWIDGET_ID = 4;
-    private static final int INDEX_RELATIVE_PATH = 5;
-    private static final String WHERE_APPWIDGET_ID = FIELD_APPWIDGET_ID + " = ?";
-    private static final String WHERE_WIDGET_TYPE = FIELD_WIDGET_TYPE + " = ?";
-
-    public static class Entry {
-        public int widgetId;
-        public int type;
-        public String imageUri;
-        public byte imageData[];
-        public String albumPath;
-        public String relativePath;
-
-        private Entry() {}
-
-        private Entry(int id, Cursor cursor) {
-            widgetId = id;
-            type = cursor.getInt(INDEX_WIDGET_TYPE);
-            if (type == TYPE_SINGLE_PHOTO) {
-                imageUri = cursor.getString(INDEX_IMAGE_URI);
-                imageData = cursor.getBlob(INDEX_PHOTO_BLOB);
-            } else if (type == TYPE_ALBUM) {
-                albumPath = cursor.getString(INDEX_ALBUM_PATH);
-                relativePath = cursor.getString(INDEX_RELATIVE_PATH);
-            }
-        }
-
-        private Entry(Cursor cursor) {
-            this(cursor.getInt(INDEX_APPWIDGET_ID), cursor);
-        }
-    }
-
-    public WidgetDatabaseHelper(Context context) {
-        super(context, DATABASE_NAME, null, DATABASE_VERSION);
-    }
-
-    @Override
-    public void onCreate(SQLiteDatabase db) {
-        db.execSQL("CREATE TABLE " + TABLE_WIDGETS + " ("
-                + FIELD_APPWIDGET_ID + " INTEGER PRIMARY KEY, "
-                + FIELD_WIDGET_TYPE + " INTEGER DEFAULT 0, "
-                + FIELD_IMAGE_URI + " TEXT, "
-                + FIELD_ALBUM_PATH + " TEXT, "
-                + FIELD_PHOTO_BLOB + " BLOB, "
-                + FIELD_RELATIVE_PATH + " TEXT)");
-    }
-
-    private void saveData(SQLiteDatabase db, int oldVersion, ArrayList<Entry> data) {
-        if (oldVersion <= 2) {
-            Cursor cursor = db.query("photos",
-                    new String[] {FIELD_APPWIDGET_ID, FIELD_PHOTO_BLOB},
-                    null, null, null, null, null);
-            if (cursor == null) return;
-            try {
-                while (cursor.moveToNext()) {
-                    Entry entry = new Entry();
-                    entry.type = TYPE_SINGLE_PHOTO;
-                    entry.widgetId = cursor.getInt(0);
-                    entry.imageData = cursor.getBlob(1);
-                    data.add(entry);
-                }
-            } finally {
-                cursor.close();
-            }
-        } else if (oldVersion == 3) {
-            Cursor cursor = db.query("photos",
-                    new String[] {FIELD_APPWIDGET_ID, FIELD_PHOTO_BLOB, FIELD_IMAGE_URI},
-                    null, null, null, null, null);
-            if (cursor == null) return;
-            try {
-                while (cursor.moveToNext()) {
-                    Entry entry = new Entry();
-                    entry.type = TYPE_SINGLE_PHOTO;
-                    entry.widgetId = cursor.getInt(0);
-                    entry.imageData = cursor.getBlob(1);
-                    entry.imageUri = cursor.getString(2);
-                    data.add(entry);
-                }
-            } finally {
-                cursor.close();
-            }
-        }
-    }
-
-    private void restoreData(SQLiteDatabase db, ArrayList<Entry> data) {
-        db.beginTransaction();
-        try {
-            for (Entry entry : data) {
-                ContentValues values = new ContentValues();
-                values.put(FIELD_APPWIDGET_ID, entry.widgetId);
-                values.put(FIELD_WIDGET_TYPE, entry.type);
-                values.put(FIELD_IMAGE_URI, entry.imageUri);
-                values.put(FIELD_PHOTO_BLOB, entry.imageData);
-                values.put(FIELD_ALBUM_PATH, entry.albumPath);
-                db.insert(TABLE_WIDGETS, null, values);
-            }
-            db.setTransactionSuccessful();
-        } finally {
-            db.endTransaction();
-        }
-    }
-
-    @Override
-    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
-        if (oldVersion < 4) {
-            // Table "photos" is renamed to "widget" in version 4
-            ArrayList<Entry> data = new ArrayList<Entry>();
-            saveData(db, oldVersion, data);
-
-            Log.w(TAG, "destroying all old data.");
-            db.execSQL("DROP TABLE IF EXISTS photos");
-            db.execSQL("DROP TABLE IF EXISTS " + TABLE_WIDGETS);
-            onCreate(db);
-
-            restoreData(db, data);
-        }
-        // Add a column for relative path
-        if (oldVersion < DATABASE_VERSION) {
-            try {
-                db.execSQL("ALTER TABLE widgets ADD COLUMN relativePath TEXT");
-            } catch (Throwable t) {
-                Log.e(TAG, "Failed to add the column for relative path.");
-                return;
-            }
-        }
-    }
-
-    /**
-     * Store the given bitmap in this database for the given appWidgetId.
-     */
-    public boolean setPhoto(int appWidgetId, Uri imageUri, Bitmap bitmap) {
-        try {
-            // Try go guesstimate how much space the icon will take when
-            // serialized to avoid unnecessary allocations/copies during
-            // the write.
-            int size = bitmap.getWidth() * bitmap.getHeight() * 4;
-            ByteArrayOutputStream out = new ByteArrayOutputStream(size);
-            bitmap.compress(Bitmap.CompressFormat.PNG, 100, out);
-            out.close();
-
-            ContentValues values = new ContentValues();
-            values.put(FIELD_APPWIDGET_ID, appWidgetId);
-            values.put(FIELD_WIDGET_TYPE, TYPE_SINGLE_PHOTO);
-            values.put(FIELD_IMAGE_URI, imageUri.toString());
-            values.put(FIELD_PHOTO_BLOB, out.toByteArray());
-
-            SQLiteDatabase db = getWritableDatabase();
-            db.replaceOrThrow(TABLE_WIDGETS, null, values);
-            return true;
-        } catch (Throwable e) {
-            Log.e(TAG, "set widget photo fail", e);
-            return false;
-        }
-    }
-
-    public boolean setWidget(int id, int type, String albumPath, String relativePath) {
-        try {
-            ContentValues values = new ContentValues();
-            values.put(FIELD_APPWIDGET_ID, id);
-            values.put(FIELD_WIDGET_TYPE, type);
-            values.put(FIELD_ALBUM_PATH, Utils.ensureNotNull(albumPath));
-            values.put(FIELD_RELATIVE_PATH, relativePath);
-            getWritableDatabase().replaceOrThrow(TABLE_WIDGETS, null, values);
-            return true;
-        } catch (Throwable e) {
-            Log.e(TAG, "set widget fail", e);
-            return false;
-        }
-    }
-
-    public Entry getEntry(int appWidgetId) {
-        Cursor cursor = null;
-        try {
-            SQLiteDatabase db = getReadableDatabase();
-            cursor = db.query(TABLE_WIDGETS, PROJECTION,
-                    WHERE_APPWIDGET_ID, new String[] {String.valueOf(appWidgetId)},
-                    null, null, null);
-            if (cursor == null || !cursor.moveToNext()) {
-                Log.e(TAG, "query fail: empty cursor: " + cursor + " appWidgetId: "
-                        + appWidgetId);
-                return null;
-            }
-            return new Entry(appWidgetId, cursor);
-        } catch (Throwable e) {
-            Log.e(TAG, "Could not load photo from database", e);
-            return null;
-        } finally {
-            Utils.closeSilently(cursor);
-        }
-    }
-
-    public List<Entry> getEntries(int type) {
-        Cursor cursor = null;
-        try {
-            SQLiteDatabase db = getReadableDatabase();
-            cursor = db.query(TABLE_WIDGETS, PROJECTION,
-                    WHERE_WIDGET_TYPE, new String[] {String.valueOf(type)},
-                    null, null, null);
-            if (cursor == null) {
-                Log.e(TAG, "query fail: null cursor: " + cursor);
-                return null;
-            }
-            ArrayList<Entry> result = new ArrayList<Entry>(cursor.getCount());
-            while (cursor.moveToNext()) {
-                result.add(new Entry(cursor));
-            }
-            return result;
-        } catch (Throwable e) {
-            Log.e(TAG, "Could not load widget from database", e);
-            return null;
-        } finally {
-            Utils.closeSilently(cursor);
-        }
-    }
-
-    /**
-     * Updates the entry in the widget database.
-     */
-    public void updateEntry(Entry entry) {
-        deleteEntry(entry.widgetId);
-        try {
-            ContentValues values = new ContentValues();
-            values.put(FIELD_APPWIDGET_ID, entry.widgetId);
-            values.put(FIELD_WIDGET_TYPE, entry.type);
-            values.put(FIELD_ALBUM_PATH, entry.albumPath);
-            values.put(FIELD_IMAGE_URI, entry.imageUri);
-            values.put(FIELD_PHOTO_BLOB, entry.imageData);
-            values.put(FIELD_RELATIVE_PATH, entry.relativePath);
-            getWritableDatabase().insert(TABLE_WIDGETS, null, values);
-        } catch (Throwable e) {
-            Log.e(TAG, "set widget fail", e);
-        }
-    }
-
-    /**
-     * Remove any bitmap associated with the given appWidgetId.
-     */
-    public void deleteEntry(int appWidgetId) {
-        try {
-            SQLiteDatabase db = getWritableDatabase();
-            db.delete(TABLE_WIDGETS, WHERE_APPWIDGET_ID,
-                    new String[] {String.valueOf(appWidgetId)});
-        } catch (SQLiteException e) {
-            Log.e(TAG, "Could not delete photo from database", e);
-        }
-    }
-}
diff --git a/src/com/android/gallery3d/gadget/WidgetService.java b/src/com/android/gallery3d/gadget/WidgetService.java
deleted file mode 100644
index 94dd164..0000000
--- a/src/com/android/gallery3d/gadget/WidgetService.java
+++ /dev/null
@@ -1,143 +0,0 @@
-/*
- * Copyright (C) 2010 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.gallery3d.gadget;
-
-import android.annotation.TargetApi;
-import android.appwidget.AppWidgetManager;
-import android.content.Intent;
-import android.graphics.Bitmap;
-import android.net.Uri;
-import android.widget.RemoteViews;
-import android.widget.RemoteViewsService;
-
-import com.android.gallery3d.R;
-import com.android.gallery3d.app.GalleryApp;
-import com.android.gallery3d.common.ApiHelper;
-import com.android.gallery3d.data.ContentListener;
-
-@TargetApi(ApiHelper.VERSION_CODES.HONEYCOMB)
-public class WidgetService extends RemoteViewsService {
-
-    @SuppressWarnings("unused")
-    private static final String TAG = "GalleryAppWidgetService";
-
-    public static final String EXTRA_WIDGET_TYPE = "widget-type";
-    public static final String EXTRA_ALBUM_PATH = "album-path";
-
-    @Override
-    public RemoteViewsFactory onGetViewFactory(Intent intent) {
-        int id = intent.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID,
-                AppWidgetManager.INVALID_APPWIDGET_ID);
-        int type = intent.getIntExtra(EXTRA_WIDGET_TYPE, 0);
-        String albumPath = intent.getStringExtra(EXTRA_ALBUM_PATH);
-
-        return new PhotoRVFactory((GalleryApp) getApplicationContext(),
-                id, type, albumPath);
-    }
-
-    private static class PhotoRVFactory implements
-            RemoteViewsService.RemoteViewsFactory, ContentListener {
-
-        private final int mAppWidgetId;
-        private final int mType;
-        private final String mAlbumPath;
-        private final GalleryApp mApp;
-
-        private WidgetSource mSource;
-
-        public PhotoRVFactory(GalleryApp app, int id, int type, String albumPath) {
-            mApp = app;
-            mAppWidgetId = id;
-            mType = type;
-            mAlbumPath = albumPath;
-        }
-
-        @Override
-        public void onCreate() {
-            if (mType == WidgetDatabaseHelper.TYPE_ALBUM) {
-                mSource = new MediaSetSource(mApp.getDataManager(), mAlbumPath);
-            } else {
-                mSource = new LocalPhotoSource(mApp.getAndroidContext());
-            }
-            mSource.setContentListener(this);
-            AppWidgetManager.getInstance(mApp.getAndroidContext())
-                    .notifyAppWidgetViewDataChanged(
-                    mAppWidgetId, R.id.appwidget_stack_view);
-        }
-
-        @Override
-        public void onDestroy() {
-            mSource.close();
-            mSource = null;
-        }
-
-        @Override
-        public int getCount() {
-            return mSource.size();
-        }
-
-        @Override
-        public long getItemId(int position) {
-            return position;
-        }
-
-        @Override
-        public int getViewTypeCount() {
-            return 1;
-        }
-
-        @Override
-        public boolean hasStableIds() {
-            return true;
-        }
-
-        @Override
-        public RemoteViews getLoadingView() {
-            RemoteViews rv = new RemoteViews(
-                    mApp.getAndroidContext().getPackageName(),
-                    R.layout.appwidget_loading_item);
-            rv.setProgressBar(R.id.appwidget_loading_item, 0, 0, true);
-            return rv;
-        }
-
-        @Override
-        public RemoteViews getViewAt(int position) {
-            Bitmap bitmap = mSource.getImage(position);
-            if (bitmap == null) return getLoadingView();
-            RemoteViews views = new RemoteViews(
-                    mApp.getAndroidContext().getPackageName(),
-                    R.layout.appwidget_photo_item);
-            views.setImageViewBitmap(R.id.appwidget_photo_item, bitmap);
-            views.setOnClickFillInIntent(R.id.appwidget_photo_item, new Intent()
-                    .setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
-                    .setData(mSource.getContentUri(position)));
-            return views;
-        }
-
-        @Override
-        public void onDataSetChanged() {
-            mSource.reload();
-        }
-
-        @Override
-        public void onContentDirty() {
-            AppWidgetManager.getInstance(mApp.getAndroidContext())
-                    .notifyAppWidgetViewDataChanged(
-                    mAppWidgetId, R.id.appwidget_stack_view);
-        }
-    }
-}
diff --git a/src/com/android/gallery3d/gadget/WidgetSource.java b/src/com/android/gallery3d/gadget/WidgetSource.java
deleted file mode 100644
index 92874c7..0000000
--- a/src/com/android/gallery3d/gadget/WidgetSource.java
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright (C) 2011 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.gallery3d.gadget;
-
-import android.graphics.Bitmap;
-import android.net.Uri;
-
-import com.android.gallery3d.data.ContentListener;
-
-public interface WidgetSource {
-    public int size();
-    public Bitmap getImage(int index);
-    public Uri getContentUri(int index);
-    public void setContentListener(ContentListener listener);
-    public void reload();
-    public void close();
-}
diff --git a/src/com/android/gallery3d/gadget/WidgetTypeChooser.java b/src/com/android/gallery3d/gadget/WidgetTypeChooser.java
deleted file mode 100644
index 1694f1c..0000000
--- a/src/com/android/gallery3d/gadget/WidgetTypeChooser.java
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Copyright (C) 2011 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.gallery3d.gadget;
-
-import android.app.Activity;
-import android.content.Intent;
-import android.os.Bundle;
-import android.view.View;
-import android.view.View.OnClickListener;
-import android.widget.Button;
-import android.widget.RadioGroup;
-import android.widget.RadioGroup.OnCheckedChangeListener;
-
-import com.android.gallery3d.R;
-
-public class WidgetTypeChooser extends Activity {
-
-    private OnCheckedChangeListener mListener = new OnCheckedChangeListener() {
-        @Override
-        public void onCheckedChanged(RadioGroup group, int checkedId) {
-            Intent data = new Intent()
-                    .putExtra(WidgetConfigure.KEY_WIDGET_TYPE, checkedId);
-            setResult(RESULT_OK, data);
-            finish();
-        }
-    };
-
-    @Override
-    public void onCreate(Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-        setTitle(R.string.widget_type);
-        setContentView(R.layout.choose_widget_type);
-        RadioGroup rg = (RadioGroup) findViewById(R.id.widget_type);
-        rg.setOnCheckedChangeListener(mListener);
-
-        Button cancel = (Button) findViewById(R.id.cancel);
-        cancel.setOnClickListener(new OnClickListener() {
-            @Override
-            public void onClick(View v) {
-                setResult(RESULT_CANCELED);
-                finish();
-            }
-        });
-    }
-}
diff --git a/src/com/android/gallery3d/gadget/WidgetUtils.java b/src/com/android/gallery3d/gadget/WidgetUtils.java
deleted file mode 100644
index c20c186..0000000
--- a/src/com/android/gallery3d/gadget/WidgetUtils.java
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * Copyright (C) 2011 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.gallery3d.gadget;
-
-import android.content.Context;
-import android.content.res.Resources;
-import android.graphics.Bitmap;
-import android.graphics.Bitmap.Config;
-import android.graphics.Canvas;
-import android.graphics.Paint;
-import android.util.Log;
-
-import com.android.gallery3d.R;
-import com.android.gallery3d.data.MediaItem;
-import com.android.gallery3d.util.ThreadPool;
-
-public class WidgetUtils {
-
-    private static final String TAG = "WidgetUtils";
-
-    private static int sStackPhotoWidth = 220;
-    private static int sStackPhotoHeight = 170;
-
-    private WidgetUtils() {
-    }
-
-    public static void initialize(Context context) {
-        Resources r = context.getResources();
-        sStackPhotoWidth = r.getDimensionPixelSize(R.dimen.stack_photo_width);
-        sStackPhotoHeight = r.getDimensionPixelSize(R.dimen.stack_photo_height);
-    }
-
-    public static Bitmap createWidgetBitmap(MediaItem image) {
-        Bitmap bitmap = image.requestImage(MediaItem.TYPE_THUMBNAIL)
-               .run(ThreadPool.JOB_CONTEXT_STUB);
-        if (bitmap == null) {
-            Log.w(TAG, "fail to get image of " + image.toString());
-            return null;
-        }
-        return createWidgetBitmap(bitmap, image.getRotation());
-    }
-
-    public static Bitmap createWidgetBitmap(Bitmap bitmap, int rotation) {
-        int w = bitmap.getWidth();
-        int h = bitmap.getHeight();
-
-        float scale;
-        if (((rotation / 90) & 1) == 0) {
-            scale = Math.max((float) sStackPhotoWidth / w,
-                    (float) sStackPhotoHeight / h);
-        } else {
-            scale = Math.max((float) sStackPhotoWidth / h,
-                    (float) sStackPhotoHeight / w);
-        }
-
-        Bitmap target = Bitmap.createBitmap(
-                sStackPhotoWidth, sStackPhotoHeight, Config.ARGB_8888);
-        Canvas canvas = new Canvas(target);
-        canvas.translate(sStackPhotoWidth / 2, sStackPhotoHeight / 2);
-        canvas.rotate(rotation);
-        canvas.scale(scale, scale);
-        Paint paint = new Paint(Paint.FILTER_BITMAP_FLAG | Paint.DITHER_FLAG);
-        canvas.drawBitmap(bitmap, -w / 2, -h / 2, paint);
-        return target;
-    }
-}
diff --git a/src/com/android/gallery3d/glrenderer/BasicTexture.java b/src/com/android/gallery3d/glrenderer/BasicTexture.java
deleted file mode 100644
index 2e77b90..0000000
--- a/src/com/android/gallery3d/glrenderer/BasicTexture.java
+++ /dev/null
@@ -1,212 +0,0 @@
-/*
- * Copyright (C) 2010 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.gallery3d.glrenderer;
-
-import android.util.Log;
-
-import com.android.gallery3d.common.Utils;
-
-import java.util.WeakHashMap;
-
-// BasicTexture is a Texture corresponds to a real GL texture.
-// The state of a BasicTexture indicates whether its data is loaded to GL memory.
-// If a BasicTexture is loaded into GL memory, it has a GL texture id.
-public abstract class BasicTexture implements Texture {
-
-    @SuppressWarnings("unused")
-    private static final String TAG = "BasicTexture";
-    protected static final int UNSPECIFIED = -1;
-
-    protected static final int STATE_UNLOADED = 0;
-    protected static final int STATE_LOADED = 1;
-    protected static final int STATE_ERROR = -1;
-
-    // Log a warning if a texture is larger along a dimension
-    private static final int MAX_TEXTURE_SIZE = 4096;
-
-    protected int mId = -1;
-    protected int mState;
-
-    protected int mWidth = UNSPECIFIED;
-    protected int mHeight = UNSPECIFIED;
-
-    protected int mTextureWidth;
-    protected int mTextureHeight;
-
-    private boolean mHasBorder;
-
-    protected GLCanvas mCanvasRef = null;
-    private static WeakHashMap<BasicTexture, Object> sAllTextures
-            = new WeakHashMap<BasicTexture, Object>();
-    private static ThreadLocal sInFinalizer = new ThreadLocal();
-
-    protected BasicTexture(GLCanvas canvas, int id, int state) {
-        setAssociatedCanvas(canvas);
-        mId = id;
-        mState = state;
-        synchronized (sAllTextures) {
-            sAllTextures.put(this, null);
-        }
-    }
-
-    protected BasicTexture() {
-        this(null, 0, STATE_UNLOADED);
-    }
-
-    protected void setAssociatedCanvas(GLCanvas canvas) {
-        mCanvasRef = canvas;
-    }
-
-    /**
-     * Sets the content size of this texture. In OpenGL, the actual texture
-     * size must be of power of 2, the size of the content may be smaller.
-     */
-    public void setSize(int width, int height) {
-        mWidth = width;
-        mHeight = height;
-        mTextureWidth = width > 0 ? Utils.nextPowerOf2(width) : 0;
-        mTextureHeight = height > 0 ? Utils.nextPowerOf2(height) : 0;
-        if (mTextureWidth > MAX_TEXTURE_SIZE || mTextureHeight > MAX_TEXTURE_SIZE) {
-            Log.w(TAG, String.format("texture is too large: %d x %d",
-                    mTextureWidth, mTextureHeight), new Exception());
-        }
-    }
-
-    public boolean isFlippedVertically() {
-      return false;
-    }
-
-    public int getId() {
-        return mId;
-    }
-
-    @Override
-    public int getWidth() {
-        return mWidth;
-    }
-
-    @Override
-    public int getHeight() {
-        return mHeight;
-    }
-
-    // Returns the width rounded to the next power of 2.
-    public int getTextureWidth() {
-        return mTextureWidth;
-    }
-
-    // Returns the height rounded to the next power of 2.
-    public int getTextureHeight() {
-        return mTextureHeight;
-    }
-
-    // Returns true if the texture has one pixel transparent border around the
-    // actual content. This is used to avoid jigged edges.
-    //
-    // The jigged edges appear because we use GL_CLAMP_TO_EDGE for texture wrap
-    // mode (GL_CLAMP is not available in OpenGL ES), so a pixel partially
-    // covered by the texture will use the color of the edge texel. If we add
-    // the transparent border, the color of the edge texel will be mixed with
-    // appropriate amount of transparent.
-    //
-    // Currently our background is black, so we can draw the thumbnails without
-    // enabling blending.
-    public boolean hasBorder() {
-        return mHasBorder;
-    }
-
-    protected void setBorder(boolean hasBorder) {
-        mHasBorder = hasBorder;
-    }
-
-    @Override
-    public void draw(GLCanvas canvas, int x, int y) {
-        canvas.drawTexture(this, x, y, getWidth(), getHeight());
-    }
-
-    @Override
-    public void draw(GLCanvas canvas, int x, int y, int w, int h) {
-        canvas.drawTexture(this, x, y, w, h);
-    }
-
-    // onBind is called before GLCanvas binds this texture.
-    // It should make sure the data is uploaded to GL memory.
-    abstract protected boolean onBind(GLCanvas canvas);
-
-    // Returns the GL texture target for this texture (e.g. GL_TEXTURE_2D).
-    abstract protected int getTarget();
-
-    public boolean isLoaded() {
-        return mState == STATE_LOADED;
-    }
-
-    // recycle() is called when the texture will never be used again,
-    // so it can free all resources.
-    public void recycle() {
-        freeResource();
-    }
-
-    // yield() is called when the texture will not be used temporarily,
-    // so it can free some resources.
-    // The default implementation unloads the texture from GL memory, so
-    // the subclass should make sure it can reload the texture to GL memory
-    // later, or it will have to override this method.
-    public void yield() {
-        freeResource();
-    }
-
-    private void freeResource() {
-        GLCanvas canvas = mCanvasRef;
-        if (canvas != null && mId != -1) {
-            canvas.unloadTexture(this);
-            mId = -1; // Don't free it again.
-        }
-        mState = STATE_UNLOADED;
-        setAssociatedCanvas(null);
-    }
-
-    @Override
-    protected void finalize() {
-        sInFinalizer.set(BasicTexture.class);
-        recycle();
-        sInFinalizer.set(null);
-    }
-
-    // This is for deciding if we can call Bitmap's recycle().
-    // We cannot call Bitmap's recycle() in finalizer because at that point
-    // the finalizer of Bitmap may already be called so recycle() will crash.
-    public static boolean inFinalizer() {
-        return sInFinalizer.get() != null;
-    }
-
-    public static void yieldAllTextures() {
-        synchronized (sAllTextures) {
-            for (BasicTexture t : sAllTextures.keySet()) {
-                t.yield();
-            }
-        }
-    }
-
-    public static void invalidateAllTextures() {
-        synchronized (sAllTextures) {
-            for (BasicTexture t : sAllTextures.keySet()) {
-                t.mState = STATE_UNLOADED;
-                t.setAssociatedCanvas(null);
-            }
-        }
-    }
-}
diff --git a/src/com/android/gallery3d/glrenderer/BitmapTexture.java b/src/com/android/gallery3d/glrenderer/BitmapTexture.java
deleted file mode 100644
index 100b0b3..0000000
--- a/src/com/android/gallery3d/glrenderer/BitmapTexture.java
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Copyright (C) 2010 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.gallery3d.glrenderer;
-
-import android.graphics.Bitmap;
-
-import junit.framework.Assert;
-
-// BitmapTexture is a texture whose content is specified by a fixed Bitmap.
-//
-// The texture does not own the Bitmap. The user should make sure the Bitmap
-// is valid during the texture's lifetime. When the texture is recycled, it
-// does not free the Bitmap.
-public class BitmapTexture extends UploadedTexture {
-    protected Bitmap mContentBitmap;
-
-    public BitmapTexture(Bitmap bitmap) {
-        this(bitmap, false);
-    }
-
-    public BitmapTexture(Bitmap bitmap, boolean hasBorder) {
-        super(hasBorder);
-        Assert.assertTrue(bitmap != null && !bitmap.isRecycled());
-        mContentBitmap = bitmap;
-    }
-
-    @Override
-    protected void onFreeBitmap(Bitmap bitmap) {
-        // Do nothing.
-    }
-
-    @Override
-    protected Bitmap onGetBitmap() {
-        return mContentBitmap;
-    }
-
-    public Bitmap getBitmap() {
-        return mContentBitmap;
-    }
-}
diff --git a/src/com/android/gallery3d/glrenderer/CanvasTexture.java b/src/com/android/gallery3d/glrenderer/CanvasTexture.java
deleted file mode 100644
index bff9d4b..0000000
--- a/src/com/android/gallery3d/glrenderer/CanvasTexture.java
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Copyright (C) 2010 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.gallery3d.glrenderer;
-
-import android.graphics.Bitmap;
-import android.graphics.Bitmap.Config;
-import android.graphics.Canvas;
-
-// CanvasTexture is a texture whose content is the drawing on a Canvas.
-// The subclasses should override onDraw() to draw on the bitmap.
-// By default CanvasTexture is not opaque.
-abstract class CanvasTexture extends UploadedTexture {
-    protected Canvas mCanvas;
-    private final Config mConfig;
-
-    public CanvasTexture(int width, int height) {
-        mConfig = Config.ARGB_8888;
-        setSize(width, height);
-        setOpaque(false);
-    }
-
-    @Override
-    protected Bitmap onGetBitmap() {
-        Bitmap bitmap = Bitmap.createBitmap(mWidth, mHeight, mConfig);
-        mCanvas = new Canvas(bitmap);
-        onDraw(mCanvas, bitmap);
-        return bitmap;
-    }
-
-    @Override
-    protected void onFreeBitmap(Bitmap bitmap) {
-        if (!inFinalizer()) {
-            bitmap.recycle();
-        }
-    }
-
-    abstract protected void onDraw(Canvas canvas, Bitmap backing);
-}
diff --git a/src/com/android/gallery3d/glrenderer/ColorTexture.java b/src/com/android/gallery3d/glrenderer/ColorTexture.java
deleted file mode 100644
index 904c78e..0000000
--- a/src/com/android/gallery3d/glrenderer/ColorTexture.java
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * Copyright (C) 2010 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.gallery3d.glrenderer;
-
-import com.android.gallery3d.common.Utils;
-
-// ColorTexture is a texture which fills the rectangle with the specified color.
-public class ColorTexture implements Texture {
-
-    private final int mColor;
-    private int mWidth;
-    private int mHeight;
-
-    public ColorTexture(int color) {
-        mColor = color;
-        mWidth = 1;
-        mHeight = 1;
-    }
-
-    @Override
-    public void draw(GLCanvas canvas, int x, int y) {
-        draw(canvas, x, y, mWidth, mHeight);
-    }
-
-    @Override
-    public void draw(GLCanvas canvas, int x, int y, int w, int h) {
-        canvas.fillRect(x, y, w, h, mColor);
-    }
-
-    @Override
-    public boolean isOpaque() {
-        return Utils.isOpaque(mColor);
-    }
-
-    public void setSize(int width, int height) {
-        mWidth = width;
-        mHeight = height;
-    }
-
-    @Override
-    public int getWidth() {
-        return mWidth;
-    }
-
-    @Override
-    public int getHeight() {
-        return mHeight;
-    }
-}
diff --git a/src/com/android/gallery3d/glrenderer/ExtTexture.java b/src/com/android/gallery3d/glrenderer/ExtTexture.java
deleted file mode 100644
index af76300..0000000
--- a/src/com/android/gallery3d/glrenderer/ExtTexture.java
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * 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.gallery3d.glrenderer;
-
-// ExtTexture is a texture whose content comes from a external texture.
-// Before drawing, setSize() should be called.
-public class ExtTexture extends BasicTexture {
-
-    private int mTarget;
-
-    public ExtTexture(GLCanvas canvas, int target) {
-        GLId glId = canvas.getGLId();
-        mId = glId.generateTexture();
-        mTarget = target;
-    }
-
-    private void uploadToCanvas(GLCanvas canvas) {
-        canvas.setTextureParameters(this);
-        setAssociatedCanvas(canvas);
-        mState = STATE_LOADED;
-    }
-
-    @Override
-    protected boolean onBind(GLCanvas canvas) {
-        if (!isLoaded()) {
-            uploadToCanvas(canvas);
-        }
-
-        return true;
-    }
-
-    @Override
-    public int getTarget() {
-        return mTarget;
-    }
-
-    @Override
-    public boolean isOpaque() {
-        return true;
-    }
-
-    @Override
-    public void yield() {
-        // we cannot free the texture because we have no backup.
-    }
-}
diff --git a/src/com/android/gallery3d/glrenderer/FadeInTexture.java b/src/com/android/gallery3d/glrenderer/FadeInTexture.java
deleted file mode 100644
index 838d465..0000000
--- a/src/com/android/gallery3d/glrenderer/FadeInTexture.java
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Copyright (C) 2011 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.gallery3d.glrenderer;
-
-
-// FadeInTexture is a texture which begins with a color, then gradually animates
-// into a given texture.
-public class FadeInTexture extends FadeTexture implements Texture {
-    @SuppressWarnings("unused")
-    private static final String TAG = "FadeInTexture";
-
-    private final int mColor;
-    private final TiledTexture mTexture;
-
-    public FadeInTexture(int color, TiledTexture texture) {
-        super(texture.getWidth(), texture.getHeight(), texture.isOpaque());
-        mColor = color;
-        mTexture = texture;
-    }
-
-    @Override
-    public void draw(GLCanvas canvas, int x, int y, int w, int h) {
-        if (isAnimating()) {
-            mTexture.drawMixed(canvas, mColor, getRatio(), x, y, w, h);
-        } else {
-            mTexture.draw(canvas, x, y, w, h);
-        }
-    }
-}
diff --git a/src/com/android/gallery3d/glrenderer/FadeOutTexture.java b/src/com/android/gallery3d/glrenderer/FadeOutTexture.java
deleted file mode 100644
index b05f3b6..0000000
--- a/src/com/android/gallery3d/glrenderer/FadeOutTexture.java
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Copyright (C) 2011 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.gallery3d.glrenderer;
-
-
-// FadeOutTexture is a texture which begins with a given texture, then gradually animates
-// into fading out totally.
-public class FadeOutTexture extends FadeTexture {
-    @SuppressWarnings("unused")
-    private static final String TAG = "FadeOutTexture";
-
-    private final BasicTexture mTexture;
-
-    public FadeOutTexture(BasicTexture texture) {
-        super(texture.getWidth(), texture.getHeight(), texture.isOpaque());
-        mTexture = texture;
-    }
-
-    @Override
-    public void draw(GLCanvas canvas, int x, int y, int w, int h) {
-        if (isAnimating()) {
-            canvas.save(GLCanvas.SAVE_FLAG_ALPHA);
-            canvas.setAlpha(getRatio());
-            mTexture.draw(canvas, x, y, w, h);
-            canvas.restore();
-        }
-    }
-}
diff --git a/src/com/android/gallery3d/glrenderer/FadeTexture.java b/src/com/android/gallery3d/glrenderer/FadeTexture.java
deleted file mode 100644
index 002c90f..0000000
--- a/src/com/android/gallery3d/glrenderer/FadeTexture.java
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * Copyright (C) 2011 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.gallery3d.glrenderer;
-
-import com.android.gallery3d.common.Utils;
-import com.android.gallery3d.ui.AnimationTime;
-
-// FadeTexture is a texture which fades the given texture along the time.
-public abstract class FadeTexture implements Texture {
-    @SuppressWarnings("unused")
-    private static final String TAG = "FadeTexture";
-
-    // The duration of the fading animation in milliseconds
-    public static final int DURATION = 180;
-
-    private final long mStartTime;
-    private final int mWidth;
-    private final int mHeight;
-    private final boolean mIsOpaque;
-    private boolean mIsAnimating;
-
-    public FadeTexture(int width, int height, boolean opaque) {
-        mWidth = width;
-        mHeight = height;
-        mIsOpaque = opaque;
-        mStartTime = now();
-        mIsAnimating = true;
-    }
-
-    @Override
-    public void draw(GLCanvas canvas, int x, int y) {
-        draw(canvas, x, y, mWidth, mHeight);
-    }
-
-    @Override
-    public boolean isOpaque() {
-        return mIsOpaque;
-    }
-
-    @Override
-    public int getWidth() {
-        return mWidth;
-    }
-
-    @Override
-    public int getHeight() {
-        return mHeight;
-    }
-
-    public boolean isAnimating() {
-        if (mIsAnimating) {
-            if (now() - mStartTime >= DURATION) {
-                mIsAnimating = false;
-            }
-        }
-        return mIsAnimating;
-    }
-
-    protected float getRatio() {
-        float r = (float)(now() - mStartTime) / DURATION;
-        return Utils.clamp(1.0f - r, 0.0f, 1.0f);
-    }
-
-    private long now() {
-        return AnimationTime.get();
-    }
-}
diff --git a/src/com/android/gallery3d/glrenderer/GLCanvas.java b/src/com/android/gallery3d/glrenderer/GLCanvas.java
deleted file mode 100644
index 305e905..0000000
--- a/src/com/android/gallery3d/glrenderer/GLCanvas.java
+++ /dev/null
@@ -1,217 +0,0 @@
-/*
- * Copyright (C) 2010 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.gallery3d.glrenderer;
-
-import android.graphics.Bitmap;
-import android.graphics.Rect;
-import android.graphics.RectF;
-
-import javax.microedition.khronos.opengles.GL11;
-
-//
-// GLCanvas gives a convenient interface to draw using OpenGL.
-//
-// When a rectangle is specified in this interface, it means the region
-// [x, x+width) * [y, y+height)
-//
-public interface GLCanvas {
-
-    public GLId getGLId();
-
-    // Tells GLCanvas the size of the underlying GL surface. This should be
-    // called before first drawing and when the size of GL surface is changed.
-    // This is called by GLRoot and should not be called by the clients
-    // who only want to draw on the GLCanvas. Both width and height must be
-    // nonnegative.
-    public abstract void setSize(int width, int height);
-
-    // Clear the drawing buffers. This should only be used by GLRoot.
-    public abstract void clearBuffer();
-
-    public abstract void clearBuffer(float[] argb);
-
-    // Sets and gets the current alpha, alpha must be in [0, 1].
-    public abstract void setAlpha(float alpha);
-
-    public abstract float getAlpha();
-
-    // (current alpha) = (current alpha) * alpha
-    public abstract void multiplyAlpha(float alpha);
-
-    // Change the current transform matrix.
-    public abstract void translate(float x, float y, float z);
-
-    public abstract void translate(float x, float y);
-
-    public abstract void scale(float sx, float sy, float sz);
-
-    public abstract void rotate(float angle, float x, float y, float z);
-
-    public abstract void multiplyMatrix(float[] mMatrix, int offset);
-
-    // Pushes the configuration state (matrix, and alpha) onto
-    // a private stack.
-    public abstract void save();
-
-    // Same as save(), but only save those specified in saveFlags.
-    public abstract void save(int saveFlags);
-
-    public static final int SAVE_FLAG_ALL = 0xFFFFFFFF;
-    public static final int SAVE_FLAG_ALPHA = 0x01;
-    public static final int SAVE_FLAG_MATRIX = 0x02;
-
-    // Pops from the top of the stack as current configuration state (matrix,
-    // alpha, and clip). This call balances a previous call to save(), and is
-    // used to remove all modifications to the configuration state since the
-    // last save call.
-    public abstract void restore();
-
-    // Draws a line using the specified paint from (x1, y1) to (x2, y2).
-    // (Both end points are included).
-    public abstract void drawLine(float x1, float y1, float x2, float y2, GLPaint paint);
-
-    // Draws a rectangle using the specified paint from (x1, y1) to (x2, y2).
-    // (Both end points are included).
-    public abstract void drawRect(float x1, float y1, float x2, float y2, GLPaint paint);
-
-    // Fills the specified rectangle with the specified color.
-    public abstract void fillRect(float x, float y, float width, float height, int color);
-
-    // Draws a texture to the specified rectangle.
-    public abstract void drawTexture(
-            BasicTexture texture, int x, int y, int width, int height);
-
-    public abstract void drawMesh(BasicTexture tex, int x, int y, int xyBuffer,
-            int uvBuffer, int indexBuffer, int indexCount);
-
-    // Draws the source rectangle part of the texture to the target rectangle.
-    public abstract void drawTexture(BasicTexture texture, RectF source, RectF target);
-
-    // Draw a texture with a specified texture transform.
-    public abstract void drawTexture(BasicTexture texture, float[] mTextureTransform,
-                int x, int y, int w, int h);
-
-    // Draw two textures to the specified rectangle. The actual texture used is
-    // from * (1 - ratio) + to * ratio
-    // The two textures must have the same size.
-    public abstract void drawMixed(BasicTexture from, int toColor,
-            float ratio, int x, int y, int w, int h);
-
-    // Draw a region of a texture and a specified color to the specified
-    // rectangle. The actual color used is from * (1 - ratio) + to * ratio.
-    // The region of the texture is defined by parameter "src". The target
-    // rectangle is specified by parameter "target".
-    public abstract void drawMixed(BasicTexture from, int toColor,
-            float ratio, RectF src, RectF target);
-
-    // Unloads the specified texture from the canvas. The resource allocated
-    // to draw the texture will be released. The specified texture will return
-    // to the unloaded state. This function should be called only from
-    // BasicTexture or its descendant
-    public abstract boolean unloadTexture(BasicTexture texture);
-
-    // Delete the specified buffer object, similar to unloadTexture.
-    public abstract void deleteBuffer(int bufferId);
-
-    // Delete the textures and buffers in GL side. This function should only be
-    // called in the GL thread.
-    public abstract void deleteRecycledResources();
-
-    // Dump statistics information and clear the counters. For debug only.
-    public abstract void dumpStatisticsAndClear();
-
-    public abstract void beginRenderTarget(RawTexture texture);
-
-    public abstract void endRenderTarget();
-
-    /**
-     * Sets texture parameters to use GL_CLAMP_TO_EDGE for both
-     * GL_TEXTURE_WRAP_S and GL_TEXTURE_WRAP_T. Sets texture parameters to be
-     * GL_LINEAR for GL_TEXTURE_MIN_FILTER and GL_TEXTURE_MAG_FILTER.
-     * bindTexture() must be called prior to this.
-     *
-     * @param texture The texture to set parameters on.
-     */
-    public abstract void setTextureParameters(BasicTexture texture);
-
-    /**
-     * Initializes the texture to a size by calling texImage2D on it.
-     *
-     * @param texture The texture to initialize the size.
-     * @param format The texture format (e.g. GL_RGBA)
-     * @param type The texture type (e.g. GL_UNSIGNED_BYTE)
-     */
-    public abstract void initializeTextureSize(BasicTexture texture, int format, int type);
-
-    /**
-     * Initializes the texture to a size by calling texImage2D on it.
-     *
-     * @param texture The texture to initialize the size.
-     * @param bitmap The bitmap to initialize the bitmap with.
-     */
-    public abstract void initializeTexture(BasicTexture texture, Bitmap bitmap);
-
-    /**
-     * Calls glTexSubImage2D to upload a bitmap to the texture.
-     *
-     * @param texture The target texture to write to.
-     * @param xOffset Specifies a texel offset in the x direction within the
-     *            texture array.
-     * @param yOffset Specifies a texel offset in the y direction within the
-     *            texture array.
-     * @param format The texture format (e.g. GL_RGBA)
-     * @param type The texture type (e.g. GL_UNSIGNED_BYTE)
-     */
-    public abstract void texSubImage2D(BasicTexture texture, int xOffset, int yOffset,
-            Bitmap bitmap,
-            int format, int type);
-
-    /**
-     * Generates buffers and uploads the buffer data.
-     *
-     * @param buffer The buffer to upload
-     * @return The buffer ID that was generated.
-     */
-    public abstract int uploadBuffer(java.nio.FloatBuffer buffer);
-
-    /**
-     * Generates buffers and uploads the element array buffer data.
-     *
-     * @param buffer The buffer to upload
-     * @return The buffer ID that was generated.
-     */
-    public abstract int uploadBuffer(java.nio.ByteBuffer buffer);
-
-    /**
-     * After LightCycle makes GL calls, this method is called to restore the GL
-     * configuration to the one expected by GLCanvas.
-     */
-    public abstract void recoverFromLightCycle();
-
-    /**
-     * Gets the bounds given by x, y, width, and height as well as the internal
-     * matrix state. There is no special handling for non-90-degree rotations.
-     * It only considers the lower-left and upper-right corners as the bounds.
-     *
-     * @param bounds The output bounds to write to.
-     * @param x The left side of the input rectangle.
-     * @param y The bottom of the input rectangle.
-     * @param width The width of the input rectangle.
-     * @param height The height of the input rectangle.
-     */
-    public abstract void getBounds(Rect bounds, int x, int y, int width, int height);
-}
diff --git a/src/com/android/gallery3d/glrenderer/GLES11Canvas.java b/src/com/android/gallery3d/glrenderer/GLES11Canvas.java
deleted file mode 100644
index 7013c3d..0000000
--- a/src/com/android/gallery3d/glrenderer/GLES11Canvas.java
+++ /dev/null
@@ -1,997 +0,0 @@
-/*
- * Copyright (C) 2010 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.gallery3d.glrenderer;
-
-import android.graphics.Bitmap;
-import android.graphics.Rect;
-import android.graphics.RectF;
-import android.opengl.GLU;
-import android.opengl.GLUtils;
-import android.opengl.Matrix;
-import android.util.Log;
-
-import com.android.gallery3d.common.Utils;
-import com.android.gallery3d.util.IntArray;
-
-import junit.framework.Assert;
-
-import java.nio.Buffer;
-import java.nio.ByteBuffer;
-import java.nio.ByteOrder;
-import java.nio.FloatBuffer;
-import java.util.ArrayList;
-
-import javax.microedition.khronos.opengles.GL10;
-import javax.microedition.khronos.opengles.GL11;
-import javax.microedition.khronos.opengles.GL11Ext;
-import javax.microedition.khronos.opengles.GL11ExtensionPack;
-
-public class GLES11Canvas implements GLCanvas {
-    @SuppressWarnings("unused")
-    private static final String TAG = "GLCanvasImp";
-
-    private static final float OPAQUE_ALPHA = 0.95f;
-
-    private static final int OFFSET_FILL_RECT = 0;
-    private static final int OFFSET_DRAW_LINE = 4;
-    private static final int OFFSET_DRAW_RECT = 6;
-    private static final float[] BOX_COORDINATES = {
-            0, 0, 1, 0, 0, 1, 1, 1,  // used for filling a rectangle
-            0, 0, 1, 1,              // used for drawing a line
-            0, 0, 0, 1, 1, 1, 1, 0}; // used for drawing the outline of a rectangle
-
-    private GL11 mGL;
-
-    private final float mMatrixValues[] = new float[16];
-    private final float mTextureMatrixValues[] = new float[16];
-
-    // The results of mapPoints are stored in this buffer, and the order is
-    // x1, y1, x2, y2.
-    private final float mMapPointsBuffer[] = new float[4];
-
-    private final float mTextureColor[] = new float[4];
-
-    private int mBoxCoords;
-
-    private GLState mGLState;
-    private final ArrayList<RawTexture> mTargetStack = new ArrayList<RawTexture>();
-
-    private float mAlpha;
-    private final ArrayList<ConfigState> mRestoreStack = new ArrayList<ConfigState>();
-    private ConfigState mRecycledRestoreAction;
-
-    private final RectF mDrawTextureSourceRect = new RectF();
-    private final RectF mDrawTextureTargetRect = new RectF();
-    private final float[] mTempMatrix = new float[32];
-    private final IntArray mUnboundTextures = new IntArray();
-    private final IntArray mDeleteBuffers = new IntArray();
-    private int mScreenWidth;
-    private int mScreenHeight;
-    private boolean mBlendEnabled = true;
-    private int mFrameBuffer[] = new int[1];
-    private static float[] sCropRect = new float[4];
-
-    private RawTexture mTargetTexture;
-
-    // Drawing statistics
-    int mCountDrawLine;
-    int mCountFillRect;
-    int mCountDrawMesh;
-    int mCountTextureRect;
-    int mCountTextureOES;
-
-    private static GLId mGLId = new GLES11IdImpl();
-
-    public GLES11Canvas(GL11 gl) {
-        mGL = gl;
-        mGLState = new GLState(gl);
-        // First create an nio buffer, then create a VBO from it.
-        int size = BOX_COORDINATES.length * Float.SIZE / Byte.SIZE;
-        FloatBuffer xyBuffer = allocateDirectNativeOrderBuffer(size).asFloatBuffer();
-        xyBuffer.put(BOX_COORDINATES, 0, BOX_COORDINATES.length).position(0);
-
-        int[] name = new int[1];
-        mGLId.glGenBuffers(1, name, 0);
-        mBoxCoords = name[0];
-
-        gl.glBindBuffer(GL11.GL_ARRAY_BUFFER, mBoxCoords);
-        gl.glBufferData(GL11.GL_ARRAY_BUFFER, xyBuffer.capacity() * (Float.SIZE / Byte.SIZE),
-                xyBuffer, GL11.GL_STATIC_DRAW);
-
-        gl.glVertexPointer(2, GL11.GL_FLOAT, 0, 0);
-        gl.glTexCoordPointer(2, GL11.GL_FLOAT, 0, 0);
-
-        // Enable the texture coordinate array for Texture 1
-        gl.glClientActiveTexture(GL11.GL_TEXTURE1);
-        gl.glTexCoordPointer(2, GL11.GL_FLOAT, 0, 0);
-        gl.glClientActiveTexture(GL11.GL_TEXTURE0);
-        gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
-
-        // mMatrixValues and mAlpha will be initialized in setSize()
-    }
-
-    @Override
-    public void setSize(int width, int height) {
-        Assert.assertTrue(width >= 0 && height >= 0);
-
-        if (mTargetTexture == null) {
-            mScreenWidth = width;
-            mScreenHeight = height;
-        }
-        mAlpha = 1.0f;
-
-        GL11 gl = mGL;
-        gl.glViewport(0, 0, width, height);
-        gl.glMatrixMode(GL11.GL_PROJECTION);
-        gl.glLoadIdentity();
-        GLU.gluOrtho2D(gl, 0, width, 0, height);
-
-        gl.glMatrixMode(GL11.GL_MODELVIEW);
-        gl.glLoadIdentity();
-
-        float matrix[] = mMatrixValues;
-        Matrix.setIdentityM(matrix, 0);
-        // to match the graphic coordinate system in android, we flip it vertically.
-        if (mTargetTexture == null) {
-            Matrix.translateM(matrix, 0, 0, height, 0);
-            Matrix.scaleM(matrix, 0, 1, -1, 1);
-        }
-    }
-
-    @Override
-    public void setAlpha(float alpha) {
-        Assert.assertTrue(alpha >= 0 && alpha <= 1);
-        mAlpha = alpha;
-    }
-
-    @Override
-    public float getAlpha() {
-        return mAlpha;
-    }
-
-    @Override
-    public void multiplyAlpha(float alpha) {
-        Assert.assertTrue(alpha >= 0 && alpha <= 1);
-        mAlpha *= alpha;
-    }
-
-    private static ByteBuffer allocateDirectNativeOrderBuffer(int size) {
-        return ByteBuffer.allocateDirect(size).order(ByteOrder.nativeOrder());
-    }
-
-    @Override
-    public void drawRect(float x, float y, float width, float height, GLPaint paint) {
-        GL11 gl = mGL;
-
-        mGLState.setColorMode(paint.getColor(), mAlpha);
-        mGLState.setLineWidth(paint.getLineWidth());
-
-        saveTransform();
-        translate(x, y);
-        scale(width, height, 1);
-
-        gl.glLoadMatrixf(mMatrixValues, 0);
-        gl.glDrawArrays(GL11.GL_LINE_LOOP, OFFSET_DRAW_RECT, 4);
-
-        restoreTransform();
-        mCountDrawLine++;
-    }
-
-    @Override
-    public void drawLine(float x1, float y1, float x2, float y2, GLPaint paint) {
-        GL11 gl = mGL;
-
-        mGLState.setColorMode(paint.getColor(), mAlpha);
-        mGLState.setLineWidth(paint.getLineWidth());
-
-        saveTransform();
-        translate(x1, y1);
-        scale(x2 - x1, y2 - y1, 1);
-
-        gl.glLoadMatrixf(mMatrixValues, 0);
-        gl.glDrawArrays(GL11.GL_LINE_STRIP, OFFSET_DRAW_LINE, 2);
-
-        restoreTransform();
-        mCountDrawLine++;
-    }
-
-    @Override
-    public void fillRect(float x, float y, float width, float height, int color) {
-        mGLState.setColorMode(color, mAlpha);
-        GL11 gl = mGL;
-
-        saveTransform();
-        translate(x, y);
-        scale(width, height, 1);
-
-        gl.glLoadMatrixf(mMatrixValues, 0);
-        gl.glDrawArrays(GL11.GL_TRIANGLE_STRIP, OFFSET_FILL_RECT, 4);
-
-        restoreTransform();
-        mCountFillRect++;
-    }
-
-    @Override
-    public void translate(float x, float y, float z) {
-        Matrix.translateM(mMatrixValues, 0, x, y, z);
-    }
-
-    // This is a faster version of translate(x, y, z) because
-    // (1) we knows z = 0, (2) we inline the Matrix.translateM call,
-    // (3) we unroll the loop
-    @Override
-    public void translate(float x, float y) {
-        float[] m = mMatrixValues;
-        m[12] += m[0] * x + m[4] * y;
-        m[13] += m[1] * x + m[5] * y;
-        m[14] += m[2] * x + m[6] * y;
-        m[15] += m[3] * x + m[7] * y;
-    }
-
-    @Override
-    public void scale(float sx, float sy, float sz) {
-        Matrix.scaleM(mMatrixValues, 0, sx, sy, sz);
-    }
-
-    @Override
-    public void rotate(float angle, float x, float y, float z) {
-        if (angle == 0) return;
-        float[] temp = mTempMatrix;
-        Matrix.setRotateM(temp, 0, angle, x, y, z);
-        Matrix.multiplyMM(temp, 16, mMatrixValues, 0, temp, 0);
-        System.arraycopy(temp, 16, mMatrixValues, 0, 16);
-    }
-
-    @Override
-    public void multiplyMatrix(float matrix[], int offset) {
-        float[] temp = mTempMatrix;
-        Matrix.multiplyMM(temp, 0, mMatrixValues, 0, matrix, offset);
-        System.arraycopy(temp, 0, mMatrixValues, 0, 16);
-    }
-
-    private void textureRect(float x, float y, float width, float height) {
-        GL11 gl = mGL;
-
-        saveTransform();
-        translate(x, y);
-        scale(width, height, 1);
-
-        gl.glLoadMatrixf(mMatrixValues, 0);
-        gl.glDrawArrays(GL11.GL_TRIANGLE_STRIP, OFFSET_FILL_RECT, 4);
-
-        restoreTransform();
-        mCountTextureRect++;
-    }
-
-    @Override
-    public void drawMesh(BasicTexture tex, int x, int y, int xyBuffer,
-            int uvBuffer, int indexBuffer, int indexCount) {
-        float alpha = mAlpha;
-        if (!bindTexture(tex)) return;
-
-        mGLState.setBlendEnabled(mBlendEnabled
-                && (!tex.isOpaque() || alpha < OPAQUE_ALPHA));
-        mGLState.setTextureAlpha(alpha);
-
-        // Reset the texture matrix. We will set our own texture coordinates
-        // below.
-        setTextureCoords(0, 0, 1, 1);
-
-        saveTransform();
-        translate(x, y);
-
-        mGL.glLoadMatrixf(mMatrixValues, 0);
-
-        mGL.glBindBuffer(GL11.GL_ARRAY_BUFFER, xyBuffer);
-        mGL.glVertexPointer(2, GL11.GL_FLOAT, 0, 0);
-
-        mGL.glBindBuffer(GL11.GL_ARRAY_BUFFER, uvBuffer);
-        mGL.glTexCoordPointer(2, GL11.GL_FLOAT, 0, 0);
-
-        mGL.glBindBuffer(GL11.GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
-        mGL.glDrawElements(GL11.GL_TRIANGLE_STRIP,
-                indexCount, GL11.GL_UNSIGNED_BYTE, 0);
-
-        mGL.glBindBuffer(GL11.GL_ARRAY_BUFFER, mBoxCoords);
-        mGL.glVertexPointer(2, GL11.GL_FLOAT, 0, 0);
-        mGL.glTexCoordPointer(2, GL11.GL_FLOAT, 0, 0);
-
-        restoreTransform();
-        mCountDrawMesh++;
-    }
-
-    // Transforms two points by the given matrix m. The result
-    // {x1', y1', x2', y2'} are stored in mMapPointsBuffer and also returned.
-    private float[] mapPoints(float m[], int x1, int y1, int x2, int y2) {
-        float[] r = mMapPointsBuffer;
-
-        // Multiply m and (x1 y1 0 1) to produce (x3 y3 z3 w3). z3 is unused.
-        float x3 = m[0] * x1 + m[4] * y1 + m[12];
-        float y3 = m[1] * x1 + m[5] * y1 + m[13];
-        float w3 = m[3] * x1 + m[7] * y1 + m[15];
-        r[0] = x3 / w3;
-        r[1] = y3 / w3;
-
-        // Same for x2 y2.
-        float x4 = m[0] * x2 + m[4] * y2 + m[12];
-        float y4 = m[1] * x2 + m[5] * y2 + m[13];
-        float w4 = m[3] * x2 + m[7] * y2 + m[15];
-        r[2] = x4 / w4;
-        r[3] = y4 / w4;
-
-        return r;
-    }
-
-    private void drawBoundTexture(
-            BasicTexture texture, int x, int y, int width, int height) {
-        // Test whether it has been rotated or flipped, if so, glDrawTexiOES
-        // won't work
-        if (isMatrixRotatedOrFlipped(mMatrixValues)) {
-            if (texture.hasBorder()) {
-                setTextureCoords(
-                        1.0f / texture.getTextureWidth(),
-                        1.0f / texture.getTextureHeight(),
-                        (texture.getWidth() - 1.0f) / texture.getTextureWidth(),
-                        (texture.getHeight() - 1.0f) / texture.getTextureHeight());
-            } else {
-                setTextureCoords(0, 0,
-                        (float) texture.getWidth() / texture.getTextureWidth(),
-                        (float) texture.getHeight() / texture.getTextureHeight());
-            }
-            textureRect(x, y, width, height);
-        } else {
-            // draw the rect from bottom-left to top-right
-            float points[] = mapPoints(
-                    mMatrixValues, x, y + height, x + width, y);
-            x = (int) (points[0] + 0.5f);
-            y = (int) (points[1] + 0.5f);
-            width = (int) (points[2] + 0.5f) - x;
-            height = (int) (points[3] + 0.5f) - y;
-            if (width > 0 && height > 0) {
-                ((GL11Ext) mGL).glDrawTexiOES(x, y, 0, width, height);
-                mCountTextureOES++;
-            }
-        }
-    }
-
-    @Override
-    public void drawTexture(
-            BasicTexture texture, int x, int y, int width, int height) {
-        drawTexture(texture, x, y, width, height, mAlpha);
-    }
-
-    private void drawTexture(BasicTexture texture,
-            int x, int y, int width, int height, float alpha) {
-        if (width <= 0 || height <= 0) return;
-
-        mGLState.setBlendEnabled(mBlendEnabled
-                && (!texture.isOpaque() || alpha < OPAQUE_ALPHA));
-        if (!bindTexture(texture)) return;
-        mGLState.setTextureAlpha(alpha);
-        drawBoundTexture(texture, x, y, width, height);
-    }
-
-    @Override
-    public void drawTexture(BasicTexture texture, RectF source, RectF target) {
-        if (target.width() <= 0 || target.height() <= 0) return;
-
-        // Copy the input to avoid changing it.
-        mDrawTextureSourceRect.set(source);
-        mDrawTextureTargetRect.set(target);
-        source = mDrawTextureSourceRect;
-        target = mDrawTextureTargetRect;
-
-        mGLState.setBlendEnabled(mBlendEnabled
-                && (!texture.isOpaque() || mAlpha < OPAQUE_ALPHA));
-        if (!bindTexture(texture)) return;
-        convertCoordinate(source, target, texture);
-        setTextureCoords(source);
-        mGLState.setTextureAlpha(mAlpha);
-        textureRect(target.left, target.top, target.width(), target.height());
-    }
-
-    @Override
-    public void drawTexture(BasicTexture texture, float[] mTextureTransform,
-            int x, int y, int w, int h) {
-        mGLState.setBlendEnabled(mBlendEnabled
-                && (!texture.isOpaque() || mAlpha < OPAQUE_ALPHA));
-        if (!bindTexture(texture)) return;
-        setTextureCoords(mTextureTransform);
-        mGLState.setTextureAlpha(mAlpha);
-        textureRect(x, y, w, h);
-    }
-
-    // This function changes the source coordinate to the texture coordinates.
-    // It also clips the source and target coordinates if it is beyond the
-    // bound of the texture.
-    private static void convertCoordinate(RectF source, RectF target,
-            BasicTexture texture) {
-
-        int width = texture.getWidth();
-        int height = texture.getHeight();
-        int texWidth = texture.getTextureWidth();
-        int texHeight = texture.getTextureHeight();
-        // Convert to texture coordinates
-        source.left /= texWidth;
-        source.right /= texWidth;
-        source.top /= texHeight;
-        source.bottom /= texHeight;
-
-        // Clip if the rendering range is beyond the bound of the texture.
-        float xBound = (float) width / texWidth;
-        if (source.right > xBound) {
-            target.right = target.left + target.width() *
-                    (xBound - source.left) / source.width();
-            source.right = xBound;
-        }
-        float yBound = (float) height / texHeight;
-        if (source.bottom > yBound) {
-            target.bottom = target.top + target.height() *
-                    (yBound - source.top) / source.height();
-            source.bottom = yBound;
-        }
-    }
-
-    @Override
-    public void drawMixed(BasicTexture from,
-            int toColor, float ratio, int x, int y, int w, int h) {
-        drawMixed(from, toColor, ratio, x, y, w, h, mAlpha);
-    }
-
-    private boolean bindTexture(BasicTexture texture) {
-        if (!texture.onBind(this)) return false;
-        int target = texture.getTarget();
-        mGLState.setTextureTarget(target);
-        mGL.glBindTexture(target, texture.getId());
-        return true;
-    }
-
-    private void setTextureColor(float r, float g, float b, float alpha) {
-        float[] color = mTextureColor;
-        color[0] = r;
-        color[1] = g;
-        color[2] = b;
-        color[3] = alpha;
-    }
-
-    private void setMixedColor(int toColor, float ratio, float alpha) {
-        //
-        // The formula we want:
-        //     alpha * ((1 - ratio) * from + ratio * to)
-        //
-        // The formula that GL supports is in the form of:
-        //     combo * from + (1 - combo) * to * scale
-        //
-        // So, we have combo = alpha * (1 - ratio)
-        //     and     scale = alpha * ratio / (1 - combo)
-        //
-        float combo = alpha * (1 - ratio);
-        float scale = alpha * ratio / (1 - combo);
-
-        // Specify the interpolation factor via the alpha component of
-        // GL_TEXTURE_ENV_COLORs.
-        // RGB component are get from toColor and will used as SRC1
-        float colorScale = scale * (toColor >>> 24) / (0xff * 0xff);
-        setTextureColor(((toColor >>> 16) & 0xff) * colorScale,
-                ((toColor >>> 8) & 0xff) * colorScale,
-                (toColor & 0xff) * colorScale, combo);
-        GL11 gl = mGL;
-        gl.glTexEnvfv(GL11.GL_TEXTURE_ENV, GL11.GL_TEXTURE_ENV_COLOR, mTextureColor, 0);
-
-        gl.glTexEnvf(GL11.GL_TEXTURE_ENV, GL11.GL_COMBINE_RGB, GL11.GL_INTERPOLATE);
-        gl.glTexEnvf(GL11.GL_TEXTURE_ENV, GL11.GL_COMBINE_ALPHA, GL11.GL_INTERPOLATE);
-        gl.glTexEnvf(GL11.GL_TEXTURE_ENV, GL11.GL_SRC1_RGB, GL11.GL_CONSTANT);
-        gl.glTexEnvf(GL11.GL_TEXTURE_ENV, GL11.GL_OPERAND1_RGB, GL11.GL_SRC_COLOR);
-        gl.glTexEnvf(GL11.GL_TEXTURE_ENV, GL11.GL_SRC1_ALPHA, GL11.GL_CONSTANT);
-        gl.glTexEnvf(GL11.GL_TEXTURE_ENV, GL11.GL_OPERAND1_ALPHA, GL11.GL_SRC_ALPHA);
-
-        // Wire up the interpolation factor for RGB.
-        gl.glTexEnvf(GL11.GL_TEXTURE_ENV, GL11.GL_SRC2_RGB, GL11.GL_CONSTANT);
-        gl.glTexEnvf(GL11.GL_TEXTURE_ENV, GL11.GL_OPERAND2_RGB, GL11.GL_SRC_ALPHA);
-
-        // Wire up the interpolation factor for alpha.
-        gl.glTexEnvf(GL11.GL_TEXTURE_ENV, GL11.GL_SRC2_ALPHA, GL11.GL_CONSTANT);
-        gl.glTexEnvf(GL11.GL_TEXTURE_ENV, GL11.GL_OPERAND2_ALPHA, GL11.GL_SRC_ALPHA);
-
-    }
-
-    @Override
-    public void drawMixed(BasicTexture from, int toColor, float ratio,
-            RectF source, RectF target) {
-        if (target.width() <= 0 || target.height() <= 0) return;
-
-        if (ratio <= 0.01f) {
-            drawTexture(from, source, target);
-            return;
-        } else if (ratio >= 1) {
-            fillRect(target.left, target.top, target.width(), target.height(), toColor);
-            return;
-        }
-
-        float alpha = mAlpha;
-
-        // Copy the input to avoid changing it.
-        mDrawTextureSourceRect.set(source);
-        mDrawTextureTargetRect.set(target);
-        source = mDrawTextureSourceRect;
-        target = mDrawTextureTargetRect;
-
-        mGLState.setBlendEnabled(mBlendEnabled && (!from.isOpaque()
-                || !Utils.isOpaque(toColor) || alpha < OPAQUE_ALPHA));
-
-        if (!bindTexture(from)) return;
-
-        // Interpolate the RGB and alpha values between both textures.
-        mGLState.setTexEnvMode(GL11.GL_COMBINE);
-        setMixedColor(toColor, ratio, alpha);
-        convertCoordinate(source, target, from);
-        setTextureCoords(source);
-        textureRect(target.left, target.top, target.width(), target.height());
-        mGLState.setTexEnvMode(GL11.GL_REPLACE);
-    }
-
-    private void drawMixed(BasicTexture from, int toColor,
-            float ratio, int x, int y, int width, int height, float alpha) {
-        // change from 0 to 0.01f to prevent getting divided by zero below
-        if (ratio <= 0.01f) {
-            drawTexture(from, x, y, width, height, alpha);
-            return;
-        } else if (ratio >= 1) {
-            fillRect(x, y, width, height, toColor);
-            return;
-        }
-
-        mGLState.setBlendEnabled(mBlendEnabled && (!from.isOpaque()
-                || !Utils.isOpaque(toColor) || alpha < OPAQUE_ALPHA));
-
-        final GL11 gl = mGL;
-        if (!bindTexture(from)) return;
-
-        // Interpolate the RGB and alpha values between both textures.
-        mGLState.setTexEnvMode(GL11.GL_COMBINE);
-        setMixedColor(toColor, ratio, alpha);
-
-        drawBoundTexture(from, x, y, width, height);
-        mGLState.setTexEnvMode(GL11.GL_REPLACE);
-    }
-
-    // TODO: the code only work for 2D should get fixed for 3D or removed
-    private static final int MSKEW_X = 4;
-    private static final int MSKEW_Y = 1;
-    private static final int MSCALE_X = 0;
-    private static final int MSCALE_Y = 5;
-
-    private static boolean isMatrixRotatedOrFlipped(float matrix[]) {
-        final float eps = 1e-5f;
-        return Math.abs(matrix[MSKEW_X]) > eps
-                || Math.abs(matrix[MSKEW_Y]) > eps
-                || matrix[MSCALE_X] < -eps
-                || matrix[MSCALE_Y] > eps;
-    }
-
-    private static class GLState {
-
-        private final GL11 mGL;
-
-        private int mTexEnvMode = GL11.GL_REPLACE;
-        private float mTextureAlpha = 1.0f;
-        private int mTextureTarget = GL11.GL_TEXTURE_2D;
-        private boolean mBlendEnabled = true;
-        private float mLineWidth = 1.0f;
-        private boolean mLineSmooth = false;
-
-        public GLState(GL11 gl) {
-            mGL = gl;
-
-            // Disable unused state
-            gl.glDisable(GL11.GL_LIGHTING);
-
-            // Enable used features
-            gl.glEnable(GL11.GL_DITHER);
-
-            gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
-            gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
-            gl.glEnable(GL11.GL_TEXTURE_2D);
-
-            gl.glTexEnvf(GL11.GL_TEXTURE_ENV,
-                    GL11.GL_TEXTURE_ENV_MODE, GL11.GL_REPLACE);
-
-            // Set the background color
-            gl.glClearColor(0f, 0f, 0f, 0f);
-
-            gl.glEnable(GL11.GL_BLEND);
-            gl.glBlendFunc(GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA);
-
-            // We use 565 or 8888 format, so set the alignment to 2 bytes/pixel.
-            gl.glPixelStorei(GL11.GL_UNPACK_ALIGNMENT, 2);
-        }
-
-        public void setTexEnvMode(int mode) {
-            if (mTexEnvMode == mode) return;
-            mTexEnvMode = mode;
-            mGL.glTexEnvf(GL11.GL_TEXTURE_ENV, GL11.GL_TEXTURE_ENV_MODE, mode);
-        }
-
-        public void setLineWidth(float width) {
-            if (mLineWidth == width) return;
-            mLineWidth = width;
-            mGL.glLineWidth(width);
-        }
-
-        public void setTextureAlpha(float alpha) {
-            if (mTextureAlpha == alpha) return;
-            mTextureAlpha = alpha;
-            if (alpha >= OPAQUE_ALPHA) {
-                // The alpha is need for those texture without alpha channel
-                mGL.glColor4f(1, 1, 1, 1);
-                setTexEnvMode(GL11.GL_REPLACE);
-            } else {
-                mGL.glColor4f(alpha, alpha, alpha, alpha);
-                setTexEnvMode(GL11.GL_MODULATE);
-            }
-        }
-
-        public void setColorMode(int color, float alpha) {
-            setBlendEnabled(!Utils.isOpaque(color) || alpha < OPAQUE_ALPHA);
-
-            // Set mTextureAlpha to an invalid value, so that it will reset
-            // again in setTextureAlpha(float) later.
-            mTextureAlpha = -1.0f;
-
-            setTextureTarget(0);
-
-            float prealpha = (color >>> 24) * alpha * 65535f / 255f / 255f;
-            mGL.glColor4x(
-                    Math.round(((color >> 16) & 0xFF) * prealpha),
-                    Math.round(((color >> 8) & 0xFF) * prealpha),
-                    Math.round((color & 0xFF) * prealpha),
-                    Math.round(255 * prealpha));
-        }
-
-        // target is a value like GL_TEXTURE_2D. If target = 0, texturing is disabled.
-        public void setTextureTarget(int target) {
-            if (mTextureTarget == target) return;
-            if (mTextureTarget != 0) {
-                mGL.glDisable(mTextureTarget);
-            }
-            mTextureTarget = target;
-            if (mTextureTarget != 0) {
-                mGL.glEnable(mTextureTarget);
-            }
-        }
-
-        public void setBlendEnabled(boolean enabled) {
-            if (mBlendEnabled == enabled) return;
-            mBlendEnabled = enabled;
-            if (enabled) {
-                mGL.glEnable(GL11.GL_BLEND);
-            } else {
-                mGL.glDisable(GL11.GL_BLEND);
-            }
-        }
-    }
-
-    @Override
-    public void clearBuffer(float[] argb) {
-        if(argb != null && argb.length == 4) {
-            mGL.glClearColor(argb[1], argb[2], argb[3], argb[0]);
-        } else {
-            mGL.glClearColor(0, 0, 0, 1);
-        }
-        mGL.glClear(GL10.GL_COLOR_BUFFER_BIT);
-    }
-
-    @Override
-    public void clearBuffer() {
-        clearBuffer(null);
-    }
-
-    private void setTextureCoords(RectF source) {
-        setTextureCoords(source.left, source.top, source.right, source.bottom);
-    }
-
-    private void setTextureCoords(float left, float top,
-            float right, float bottom) {
-        mGL.glMatrixMode(GL11.GL_TEXTURE);
-        mTextureMatrixValues[0] = right - left;
-        mTextureMatrixValues[5] = bottom - top;
-        mTextureMatrixValues[10] = 1;
-        mTextureMatrixValues[12] = left;
-        mTextureMatrixValues[13] = top;
-        mTextureMatrixValues[15] = 1;
-        mGL.glLoadMatrixf(mTextureMatrixValues, 0);
-        mGL.glMatrixMode(GL11.GL_MODELVIEW);
-    }
-
-    private void setTextureCoords(float[] mTextureTransform) {
-        mGL.glMatrixMode(GL11.GL_TEXTURE);
-        mGL.glLoadMatrixf(mTextureTransform, 0);
-        mGL.glMatrixMode(GL11.GL_MODELVIEW);
-    }
-
-    // unloadTexture and deleteBuffer can be called from the finalizer thread,
-    // so we synchronized on the mUnboundTextures object.
-    @Override
-    public boolean unloadTexture(BasicTexture t) {
-        synchronized (mUnboundTextures) {
-            if (!t.isLoaded()) return false;
-            mUnboundTextures.add(t.mId);
-            return true;
-        }
-    }
-
-    @Override
-    public void deleteBuffer(int bufferId) {
-        synchronized (mUnboundTextures) {
-            mDeleteBuffers.add(bufferId);
-        }
-    }
-
-    @Override
-    public void deleteRecycledResources() {
-        synchronized (mUnboundTextures) {
-            IntArray ids = mUnboundTextures;
-            if (ids.size() > 0) {
-                mGLId.glDeleteTextures(mGL, ids.size(), ids.getInternalArray(), 0);
-                ids.clear();
-            }
-
-            ids = mDeleteBuffers;
-            if (ids.size() > 0) {
-                mGLId.glDeleteBuffers(mGL, ids.size(), ids.getInternalArray(), 0);
-                ids.clear();
-            }
-        }
-    }
-
-    @Override
-    public void save() {
-        save(SAVE_FLAG_ALL);
-    }
-
-    @Override
-    public void save(int saveFlags) {
-        ConfigState config = obtainRestoreConfig();
-
-        if ((saveFlags & SAVE_FLAG_ALPHA) != 0) {
-            config.mAlpha = mAlpha;
-        } else {
-            config.mAlpha = -1;
-        }
-
-        if ((saveFlags & SAVE_FLAG_MATRIX) != 0) {
-            System.arraycopy(mMatrixValues, 0, config.mMatrix, 0, 16);
-        } else {
-            config.mMatrix[0] = Float.NEGATIVE_INFINITY;
-        }
-
-        mRestoreStack.add(config);
-    }
-
-    @Override
-    public void restore() {
-        if (mRestoreStack.isEmpty()) throw new IllegalStateException();
-        ConfigState config = mRestoreStack.remove(mRestoreStack.size() - 1);
-        config.restore(this);
-        freeRestoreConfig(config);
-    }
-
-    private void freeRestoreConfig(ConfigState action) {
-        action.mNextFree = mRecycledRestoreAction;
-        mRecycledRestoreAction = action;
-    }
-
-    private ConfigState obtainRestoreConfig() {
-        if (mRecycledRestoreAction != null) {
-            ConfigState result = mRecycledRestoreAction;
-            mRecycledRestoreAction = result.mNextFree;
-            return result;
-        }
-        return new ConfigState();
-    }
-
-    private static class ConfigState {
-        float mAlpha;
-        float mMatrix[] = new float[16];
-        ConfigState mNextFree;
-
-        public void restore(GLES11Canvas canvas) {
-            if (mAlpha >= 0) canvas.setAlpha(mAlpha);
-            if (mMatrix[0] != Float.NEGATIVE_INFINITY) {
-                System.arraycopy(mMatrix, 0, canvas.mMatrixValues, 0, 16);
-            }
-        }
-    }
-
-    @Override
-    public void dumpStatisticsAndClear() {
-        String line = String.format(
-                "MESH:%d, TEX_OES:%d, TEX_RECT:%d, FILL_RECT:%d, LINE:%d",
-                mCountDrawMesh, mCountTextureRect, mCountTextureOES,
-                mCountFillRect, mCountDrawLine);
-        mCountDrawMesh = 0;
-        mCountTextureRect = 0;
-        mCountTextureOES = 0;
-        mCountFillRect = 0;
-        mCountDrawLine = 0;
-        Log.d(TAG, line);
-    }
-
-    private void saveTransform() {
-        System.arraycopy(mMatrixValues, 0, mTempMatrix, 0, 16);
-    }
-
-    private void restoreTransform() {
-        System.arraycopy(mTempMatrix, 0, mMatrixValues, 0, 16);
-    }
-
-    private void setRenderTarget(RawTexture texture) {
-        GL11ExtensionPack gl11ep = (GL11ExtensionPack) mGL;
-
-        if (mTargetTexture == null && texture != null) {
-            mGLId.glGenBuffers(1, mFrameBuffer, 0);
-            gl11ep.glBindFramebufferOES(
-                    GL11ExtensionPack.GL_FRAMEBUFFER_OES, mFrameBuffer[0]);
-        }
-        if (mTargetTexture != null && texture  == null) {
-            gl11ep.glBindFramebufferOES(GL11ExtensionPack.GL_FRAMEBUFFER_OES, 0);
-            gl11ep.glDeleteFramebuffersOES(1, mFrameBuffer, 0);
-        }
-
-        mTargetTexture = texture;
-        if (texture == null) {
-            setSize(mScreenWidth, mScreenHeight);
-        } else {
-            setSize(texture.getWidth(), texture.getHeight());
-
-            if (!texture.isLoaded()) texture.prepare(this);
-
-            gl11ep.glFramebufferTexture2DOES(
-                    GL11ExtensionPack.GL_FRAMEBUFFER_OES,
-                    GL11ExtensionPack.GL_COLOR_ATTACHMENT0_OES,
-                    GL11.GL_TEXTURE_2D, texture.getId(), 0);
-
-            checkFramebufferStatus(gl11ep);
-        }
-    }
-
-    @Override
-    public void endRenderTarget() {
-        RawTexture texture = mTargetStack.remove(mTargetStack.size() - 1);
-        setRenderTarget(texture);
-        restore(); // restore matrix and alpha
-    }
-
-    @Override
-    public void beginRenderTarget(RawTexture texture) {
-        save(); // save matrix and alpha
-        mTargetStack.add(mTargetTexture);
-        setRenderTarget(texture);
-    }
-
-    private static void checkFramebufferStatus(GL11ExtensionPack gl11ep) {
-        int status = gl11ep.glCheckFramebufferStatusOES(GL11ExtensionPack.GL_FRAMEBUFFER_OES);
-        if (status != GL11ExtensionPack.GL_FRAMEBUFFER_COMPLETE_OES) {
-            String msg = "";
-            switch (status) {
-                case GL11ExtensionPack.GL_FRAMEBUFFER_INCOMPLETE_FORMATS_OES:
-                    msg = "FRAMEBUFFER_FORMATS";
-                    break;
-                case GL11ExtensionPack.GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_OES:
-                    msg = "FRAMEBUFFER_ATTACHMENT";
-                    break;
-                case GL11ExtensionPack.GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_OES:
-                    msg = "FRAMEBUFFER_MISSING_ATTACHMENT";
-                    break;
-                case GL11ExtensionPack.GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_OES:
-                    msg = "FRAMEBUFFER_DRAW_BUFFER";
-                    break;
-                case GL11ExtensionPack.GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_OES:
-                    msg = "FRAMEBUFFER_READ_BUFFER";
-                    break;
-                case GL11ExtensionPack.GL_FRAMEBUFFER_UNSUPPORTED_OES:
-                    msg = "FRAMEBUFFER_UNSUPPORTED";
-                    break;
-                case GL11ExtensionPack.GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_OES:
-                    msg = "FRAMEBUFFER_INCOMPLETE_DIMENSIONS";
-                    break;
-            }
-            throw new RuntimeException(msg + ":" + Integer.toHexString(status));
-        }
-    }
-
-    @Override
-    public void setTextureParameters(BasicTexture texture) {
-        int width = texture.getWidth();
-        int height = texture.getHeight();
-        // Define a vertically flipped crop rectangle for OES_draw_texture.
-        // The four values in sCropRect are: left, bottom, width, and
-        // height. Negative value of width or height means flip.
-        sCropRect[0] = 0;
-        sCropRect[1] = height;
-        sCropRect[2] = width;
-        sCropRect[3] = -height;
-
-        // Set texture parameters.
-        int target = texture.getTarget();
-        mGL.glBindTexture(target, texture.getId());
-        mGL.glTexParameterfv(target, GL11Ext.GL_TEXTURE_CROP_RECT_OES, sCropRect, 0);
-        mGL.glTexParameteri(target, GL11.GL_TEXTURE_WRAP_S, GL11.GL_CLAMP_TO_EDGE);
-        mGL.glTexParameteri(target, GL11.GL_TEXTURE_WRAP_T, GL11.GL_CLAMP_TO_EDGE);
-        mGL.glTexParameterf(target, GL11.GL_TEXTURE_MIN_FILTER, GL11.GL_LINEAR);
-        mGL.glTexParameterf(target, GL11.GL_TEXTURE_MAG_FILTER, GL11.GL_LINEAR);
-    }
-
-    @Override
-    public void initializeTextureSize(BasicTexture texture, int format, int type) {
-        int target = texture.getTarget();
-        mGL.glBindTexture(target, texture.getId());
-        int width = texture.getTextureWidth();
-        int height = texture.getTextureHeight();
-        mGL.glTexImage2D(target, 0, format, width, height, 0, format, type, null);
-    }
-
-    @Override
-    public void initializeTexture(BasicTexture texture, Bitmap bitmap) {
-        int target = texture.getTarget();
-        mGL.glBindTexture(target, texture.getId());
-        GLUtils.texImage2D(target, 0, bitmap, 0);
-    }
-
-    @Override
-    public void texSubImage2D(BasicTexture texture, int xOffset, int yOffset, Bitmap bitmap,
-            int format, int type) {
-        int target = texture.getTarget();
-        mGL.glBindTexture(target, texture.getId());
-        GLUtils.texSubImage2D(target, 0, xOffset, yOffset, bitmap, format, type);
-    }
-
-    @Override
-    public int uploadBuffer(FloatBuffer buf) {
-        return uploadBuffer(buf, Float.SIZE / Byte.SIZE);
-    }
-
-    @Override
-    public int uploadBuffer(ByteBuffer buf) {
-        return uploadBuffer(buf, 1);
-    }
-
-    private int uploadBuffer(Buffer buf, int elementSize) {
-        int[] bufferIds = new int[1];
-        mGLId.glGenBuffers(bufferIds.length, bufferIds, 0);
-        int bufferId = bufferIds[0];
-        mGL.glBindBuffer(GL11.GL_ARRAY_BUFFER, bufferId);
-        mGL.glBufferData(GL11.GL_ARRAY_BUFFER, buf.capacity() * elementSize, buf,
-                GL11.GL_STATIC_DRAW);
-        return bufferId;
-    }
-
-    @Override
-    public void recoverFromLightCycle() {
-        // This is only required for GLES20
-    }
-
-    @Override
-    public void getBounds(Rect bounds, int x, int y, int width, int height) {
-        // This is only required for GLES20
-    }
-
-    @Override
-    public GLId getGLId() {
-        return mGLId;
-    }
-}
diff --git a/src/com/android/gallery3d/glrenderer/GLES11IdImpl.java b/src/com/android/gallery3d/glrenderer/GLES11IdImpl.java
deleted file mode 100644
index e479373..0000000
--- a/src/com/android/gallery3d/glrenderer/GLES11IdImpl.java
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * 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.gallery3d.glrenderer;
-
-import javax.microedition.khronos.opengles.GL11;
-import javax.microedition.khronos.opengles.GL11ExtensionPack;
-
-/**
- * Open GL ES 1.1 implementation for generating and destroying texture IDs and
- * buffer IDs
- */
-public class GLES11IdImpl implements GLId {
-    private static int sNextId = 1;
-    // Mutex for sNextId
-    private static Object sLock = new Object();
-
-    @Override
-    public int generateTexture() {
-        synchronized (sLock) {
-            return sNextId++;
-        }
-    }
-
-    @Override
-    public void glGenBuffers(int n, int[] buffers, int offset) {
-        synchronized (sLock) {
-            while (n-- > 0) {
-                buffers[offset + n] = sNextId++;
-            }
-        }
-    }
-
-    @Override
-    public void glDeleteTextures(GL11 gl, int n, int[] textures, int offset) {
-        synchronized (sLock) {
-            gl.glDeleteTextures(n, textures, offset);
-        }
-    }
-
-    @Override
-    public void glDeleteBuffers(GL11 gl, int n, int[] buffers, int offset) {
-        synchronized (sLock) {
-            gl.glDeleteBuffers(n, buffers, offset);
-        }
-    }
-
-    @Override
-    public void glDeleteFramebuffers(GL11ExtensionPack gl11ep, int n, int[] buffers, int offset) {
-        synchronized (sLock) {
-            gl11ep.glDeleteFramebuffersOES(n, buffers, offset);
-        }
-    }
-
-
-}
diff --git a/src/com/android/gallery3d/glrenderer/GLES20Canvas.java b/src/com/android/gallery3d/glrenderer/GLES20Canvas.java
deleted file mode 100644
index 4ead131..0000000
--- a/src/com/android/gallery3d/glrenderer/GLES20Canvas.java
+++ /dev/null
@@ -1,1009 +0,0 @@
-/*
- * 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.gallery3d.glrenderer;
-
-import android.graphics.Bitmap;
-import android.graphics.Rect;
-import android.graphics.RectF;
-import android.opengl.GLES20;
-import android.opengl.GLUtils;
-import android.opengl.Matrix;
-import android.util.Log;
-
-import com.android.gallery3d.util.IntArray;
-
-import java.nio.Buffer;
-import java.nio.ByteBuffer;
-import java.nio.ByteOrder;
-import java.nio.FloatBuffer;
-import java.util.ArrayList;
-import java.util.Arrays;
-
-public class GLES20Canvas implements GLCanvas {
-    // ************** Constants **********************
-    private static final String TAG = GLES20Canvas.class.getSimpleName();
-    private static final int FLOAT_SIZE = Float.SIZE / Byte.SIZE;
-    private static final float OPAQUE_ALPHA = 0.95f;
-
-    private static final int COORDS_PER_VERTEX = 2;
-    private static final int VERTEX_STRIDE = COORDS_PER_VERTEX * FLOAT_SIZE;
-
-    private static final int COUNT_FILL_VERTEX = 4;
-    private static final int COUNT_LINE_VERTEX = 2;
-    private static final int COUNT_RECT_VERTEX = 4;
-    private static final int OFFSET_FILL_RECT = 0;
-    private static final int OFFSET_DRAW_LINE = OFFSET_FILL_RECT + COUNT_FILL_VERTEX;
-    private static final int OFFSET_DRAW_RECT = OFFSET_DRAW_LINE + COUNT_LINE_VERTEX;
-
-    private static final float[] BOX_COORDINATES = {
-            0, 0, // Fill rectangle
-            1, 0,
-            0, 1,
-            1, 1,
-            0, 0, // Draw line
-            1, 1,
-            0, 0, // Draw rectangle outline
-            0, 1,
-            1, 1,
-            1, 0,
-    };
-
-    private static final float[] BOUNDS_COORDINATES = {
-        0, 0, 0, 1,
-        1, 1, 0, 1,
-    };
-
-    private static final String POSITION_ATTRIBUTE = "aPosition";
-    private static final String COLOR_UNIFORM = "uColor";
-    private static final String MATRIX_UNIFORM = "uMatrix";
-    private static final String TEXTURE_MATRIX_UNIFORM = "uTextureMatrix";
-    private static final String TEXTURE_SAMPLER_UNIFORM = "uTextureSampler";
-    private static final String ALPHA_UNIFORM = "uAlpha";
-    private static final String TEXTURE_COORD_ATTRIBUTE = "aTextureCoordinate";
-
-    private static final String DRAW_VERTEX_SHADER = ""
-            + "uniform mat4 " + MATRIX_UNIFORM + ";\n"
-            + "attribute vec2 " + POSITION_ATTRIBUTE + ";\n"
-            + "void main() {\n"
-            + "  vec4 pos = vec4(" + POSITION_ATTRIBUTE + ", 0.0, 1.0);\n"
-            + "  gl_Position = " + MATRIX_UNIFORM + " * pos;\n"
-            + "}\n";
-
-    private static final String DRAW_FRAGMENT_SHADER = ""
-            + "precision mediump float;\n"
-            + "uniform vec4 " + COLOR_UNIFORM + ";\n"
-            + "void main() {\n"
-            + "  gl_FragColor = " + COLOR_UNIFORM + ";\n"
-            + "}\n";
-
-    private static final String TEXTURE_VERTEX_SHADER = ""
-            + "uniform mat4 " + MATRIX_UNIFORM + ";\n"
-            + "uniform mat4 " + TEXTURE_MATRIX_UNIFORM + ";\n"
-            + "attribute vec2 " + POSITION_ATTRIBUTE + ";\n"
-            + "varying vec2 vTextureCoord;\n"
-            + "void main() {\n"
-            + "  vec4 pos = vec4(" + POSITION_ATTRIBUTE + ", 0.0, 1.0);\n"
-            + "  gl_Position = " + MATRIX_UNIFORM + " * pos;\n"
-            + "  vTextureCoord = (" + TEXTURE_MATRIX_UNIFORM + " * pos).xy;\n"
-            + "}\n";
-
-    private static final String MESH_VERTEX_SHADER = ""
-            + "uniform mat4 " + MATRIX_UNIFORM + ";\n"
-            + "attribute vec2 " + POSITION_ATTRIBUTE + ";\n"
-            + "attribute vec2 " + TEXTURE_COORD_ATTRIBUTE + ";\n"
-            + "varying vec2 vTextureCoord;\n"
-            + "void main() {\n"
-            + "  vec4 pos = vec4(" + POSITION_ATTRIBUTE + ", 0.0, 1.0);\n"
-            + "  gl_Position = " + MATRIX_UNIFORM + " * pos;\n"
-            + "  vTextureCoord = " + TEXTURE_COORD_ATTRIBUTE + ";\n"
-            + "}\n";
-
-    private static final String TEXTURE_FRAGMENT_SHADER = ""
-            + "precision mediump float;\n"
-            + "varying vec2 vTextureCoord;\n"
-            + "uniform float " + ALPHA_UNIFORM + ";\n"
-            + "uniform sampler2D " + TEXTURE_SAMPLER_UNIFORM + ";\n"
-            + "void main() {\n"
-            + "  gl_FragColor = texture2D(" + TEXTURE_SAMPLER_UNIFORM + ", vTextureCoord);\n"
-            + "  gl_FragColor *= " + ALPHA_UNIFORM + ";\n"
-            + "}\n";
-
-    private static final String OES_TEXTURE_FRAGMENT_SHADER = ""
-            + "#extension GL_OES_EGL_image_external : require\n"
-            + "precision mediump float;\n"
-            + "varying vec2 vTextureCoord;\n"
-            + "uniform float " + ALPHA_UNIFORM + ";\n"
-            + "uniform samplerExternalOES " + TEXTURE_SAMPLER_UNIFORM + ";\n"
-            + "void main() {\n"
-            + "  gl_FragColor = texture2D(" + TEXTURE_SAMPLER_UNIFORM + ", vTextureCoord);\n"
-            + "  gl_FragColor *= " + ALPHA_UNIFORM + ";\n"
-            + "}\n";
-
-    private static final int INITIAL_RESTORE_STATE_SIZE = 8;
-    private static final int MATRIX_SIZE = 16;
-
-    // Keep track of restore state
-    private float[] mMatrices = new float[INITIAL_RESTORE_STATE_SIZE * MATRIX_SIZE];
-    private float[] mAlphas = new float[INITIAL_RESTORE_STATE_SIZE];
-    private IntArray mSaveFlags = new IntArray();
-
-    private int mCurrentAlphaIndex = 0;
-    private int mCurrentMatrixIndex = 0;
-
-    // Viewport size
-    private int mWidth;
-    private int mHeight;
-
-    // Projection matrix
-    private float[] mProjectionMatrix = new float[MATRIX_SIZE];
-
-    // Screen size for when we aren't bound to a texture
-    private int mScreenWidth;
-    private int mScreenHeight;
-
-    // GL programs
-    private int mDrawProgram;
-    private int mTextureProgram;
-    private int mOesTextureProgram;
-    private int mMeshProgram;
-
-    // GL buffer containing BOX_COORDINATES
-    private int mBoxCoordinates;
-
-    // Handle indices -- common
-    private static final int INDEX_POSITION = 0;
-    private static final int INDEX_MATRIX = 1;
-
-    // Handle indices -- draw
-    private static final int INDEX_COLOR = 2;
-
-    // Handle indices -- texture
-    private static final int INDEX_TEXTURE_MATRIX = 2;
-    private static final int INDEX_TEXTURE_SAMPLER = 3;
-    private static final int INDEX_ALPHA = 4;
-
-    // Handle indices -- mesh
-    private static final int INDEX_TEXTURE_COORD = 2;
-
-    private abstract static class ShaderParameter {
-        public int handle;
-        protected final String mName;
-
-        public ShaderParameter(String name) {
-            mName = name;
-        }
-
-        public abstract void loadHandle(int program);
-    }
-
-    private static class UniformShaderParameter extends ShaderParameter {
-        public UniformShaderParameter(String name) {
-            super(name);
-        }
-
-        @Override
-        public void loadHandle(int program) {
-            handle = GLES20.glGetUniformLocation(program, mName);
-            checkError();
-        }
-    }
-
-    private static class AttributeShaderParameter extends ShaderParameter {
-        public AttributeShaderParameter(String name) {
-            super(name);
-        }
-
-        @Override
-        public void loadHandle(int program) {
-            handle = GLES20.glGetAttribLocation(program, mName);
-            checkError();
-        }
-    }
-
-    ShaderParameter[] mDrawParameters = {
-            new AttributeShaderParameter(POSITION_ATTRIBUTE), // INDEX_POSITION
-            new UniformShaderParameter(MATRIX_UNIFORM), // INDEX_MATRIX
-            new UniformShaderParameter(COLOR_UNIFORM), // INDEX_COLOR
-    };
-    ShaderParameter[] mTextureParameters = {
-            new AttributeShaderParameter(POSITION_ATTRIBUTE), // INDEX_POSITION
-            new UniformShaderParameter(MATRIX_UNIFORM), // INDEX_MATRIX
-            new UniformShaderParameter(TEXTURE_MATRIX_UNIFORM), // INDEX_TEXTURE_MATRIX
-            new UniformShaderParameter(TEXTURE_SAMPLER_UNIFORM), // INDEX_TEXTURE_SAMPLER
-            new UniformShaderParameter(ALPHA_UNIFORM), // INDEX_ALPHA
-    };
-    ShaderParameter[] mOesTextureParameters = {
-            new AttributeShaderParameter(POSITION_ATTRIBUTE), // INDEX_POSITION
-            new UniformShaderParameter(MATRIX_UNIFORM), // INDEX_MATRIX
-            new UniformShaderParameter(TEXTURE_MATRIX_UNIFORM), // INDEX_TEXTURE_MATRIX
-            new UniformShaderParameter(TEXTURE_SAMPLER_UNIFORM), // INDEX_TEXTURE_SAMPLER
-            new UniformShaderParameter(ALPHA_UNIFORM), // INDEX_ALPHA
-    };
-    ShaderParameter[] mMeshParameters = {
-            new AttributeShaderParameter(POSITION_ATTRIBUTE), // INDEX_POSITION
-            new UniformShaderParameter(MATRIX_UNIFORM), // INDEX_MATRIX
-            new AttributeShaderParameter(TEXTURE_COORD_ATTRIBUTE), // INDEX_TEXTURE_COORD
-            new UniformShaderParameter(TEXTURE_SAMPLER_UNIFORM), // INDEX_TEXTURE_SAMPLER
-            new UniformShaderParameter(ALPHA_UNIFORM), // INDEX_ALPHA
-    };
-
-    private final IntArray mUnboundTextures = new IntArray();
-    private final IntArray mDeleteBuffers = new IntArray();
-
-    // Keep track of statistics for debugging
-    private int mCountDrawMesh = 0;
-    private int mCountTextureRect = 0;
-    private int mCountFillRect = 0;
-    private int mCountDrawLine = 0;
-
-    // Buffer for framebuffer IDs -- we keep track so we can switch the attached
-    // texture.
-    private int[] mFrameBuffer = new int[1];
-
-    // Bound textures.
-    private ArrayList<RawTexture> mTargetTextures = new ArrayList<RawTexture>();
-
-    // Temporary variables used within calculations
-    private final float[] mTempMatrix = new float[32];
-    private final float[] mTempColor = new float[4];
-    private final RectF mTempSourceRect = new RectF();
-    private final RectF mTempTargetRect = new RectF();
-    private final float[] mTempTextureMatrix = new float[MATRIX_SIZE];
-    private final int[] mTempIntArray = new int[1];
-
-    private static final GLId mGLId = new GLES20IdImpl();
-
-    public GLES20Canvas() {
-        Matrix.setIdentityM(mTempTextureMatrix, 0);
-        Matrix.setIdentityM(mMatrices, mCurrentMatrixIndex);
-        mAlphas[mCurrentAlphaIndex] = 1f;
-        mTargetTextures.add(null);
-
-        FloatBuffer boxBuffer = createBuffer(BOX_COORDINATES);
-        mBoxCoordinates = uploadBuffer(boxBuffer);
-
-        int drawVertexShader = loadShader(GLES20.GL_VERTEX_SHADER, DRAW_VERTEX_SHADER);
-        int textureVertexShader = loadShader(GLES20.GL_VERTEX_SHADER, TEXTURE_VERTEX_SHADER);
-        int meshVertexShader = loadShader(GLES20.GL_VERTEX_SHADER, MESH_VERTEX_SHADER);
-        int drawFragmentShader = loadShader(GLES20.GL_FRAGMENT_SHADER, DRAW_FRAGMENT_SHADER);
-        int textureFragmentShader = loadShader(GLES20.GL_FRAGMENT_SHADER, TEXTURE_FRAGMENT_SHADER);
-        int oesTextureFragmentShader = loadShader(GLES20.GL_FRAGMENT_SHADER,
-                OES_TEXTURE_FRAGMENT_SHADER);
-
-        mDrawProgram = assembleProgram(drawVertexShader, drawFragmentShader, mDrawParameters);
-        mTextureProgram = assembleProgram(textureVertexShader, textureFragmentShader,
-                mTextureParameters);
-        mOesTextureProgram = assembleProgram(textureVertexShader, oesTextureFragmentShader,
-                mOesTextureParameters);
-        mMeshProgram = assembleProgram(meshVertexShader, textureFragmentShader, mMeshParameters);
-        GLES20.glBlendFunc(GLES20.GL_ONE, GLES20.GL_ONE_MINUS_SRC_ALPHA);
-        checkError();
-    }
-
-    private static FloatBuffer createBuffer(float[] values) {
-        // First create an nio buffer, then create a VBO from it.
-        int size = values.length * FLOAT_SIZE;
-        FloatBuffer buffer = ByteBuffer.allocateDirect(size).order(ByteOrder.nativeOrder())
-                .asFloatBuffer();
-        buffer.put(values, 0, values.length).position(0);
-        return buffer;
-    }
-
-    private int assembleProgram(int vertexShader, int fragmentShader, ShaderParameter[] params) {
-        int program = GLES20.glCreateProgram();
-        checkError();
-        if (program == 0) {
-            throw new RuntimeException("Cannot create GL program: " + GLES20.glGetError());
-        }
-        GLES20.glAttachShader(program, vertexShader);
-        checkError();
-        GLES20.glAttachShader(program, fragmentShader);
-        checkError();
-        GLES20.glLinkProgram(program);
-        checkError();
-        int[] mLinkStatus = mTempIntArray;
-        GLES20.glGetProgramiv(program, GLES20.GL_LINK_STATUS, mLinkStatus, 0);
-        if (mLinkStatus[0] != GLES20.GL_TRUE) {
-            Log.e(TAG, "Could not link program: ");
-            Log.e(TAG, GLES20.glGetProgramInfoLog(program));
-            GLES20.glDeleteProgram(program);
-            program = 0;
-        }
-        for (int i = 0; i < params.length; i++) {
-            params[i].loadHandle(program);
-        }
-        return program;
-    }
-
-    private static int loadShader(int type, String shaderCode) {
-        // create a vertex shader type (GLES20.GL_VERTEX_SHADER)
-        // or a fragment shader type (GLES20.GL_FRAGMENT_SHADER)
-        int shader = GLES20.glCreateShader(type);
-
-        // add the source code to the shader and compile it
-        GLES20.glShaderSource(shader, shaderCode);
-        checkError();
-        GLES20.glCompileShader(shader);
-        checkError();
-
-        return shader;
-    }
-
-    @Override
-    public void setSize(int width, int height) {
-        mWidth = width;
-        mHeight = height;
-        GLES20.glViewport(0, 0, mWidth, mHeight);
-        checkError();
-        Matrix.setIdentityM(mMatrices, mCurrentMatrixIndex);
-        Matrix.orthoM(mProjectionMatrix, 0, 0, width, 0, height, -1, 1);
-        if (getTargetTexture() == null) {
-            mScreenWidth = width;
-            mScreenHeight = height;
-            Matrix.translateM(mMatrices, mCurrentMatrixIndex, 0, height, 0);
-            Matrix.scaleM(mMatrices, mCurrentMatrixIndex, 1, -1, 1);
-        }
-    }
-
-    @Override
-    public void clearBuffer() {
-        GLES20.glClearColor(0f, 0f, 0f, 1f);
-        checkError();
-        GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
-        checkError();
-    }
-
-    @Override
-    public void clearBuffer(float[] argb) {
-        GLES20.glClearColor(argb[1], argb[2], argb[3], argb[0]);
-        checkError();
-        GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
-        checkError();
-    }
-
-    @Override
-    public float getAlpha() {
-        return mAlphas[mCurrentAlphaIndex];
-    }
-
-    @Override
-    public void setAlpha(float alpha) {
-        mAlphas[mCurrentAlphaIndex] = alpha;
-    }
-
-    @Override
-    public void multiplyAlpha(float alpha) {
-        setAlpha(getAlpha() * alpha);
-    }
-
-    @Override
-    public void translate(float x, float y, float z) {
-        Matrix.translateM(mMatrices, mCurrentMatrixIndex, x, y, z);
-    }
-
-    // This is a faster version of translate(x, y, z) because
-    // (1) we knows z = 0, (2) we inline the Matrix.translateM call,
-    // (3) we unroll the loop
-    @Override
-    public void translate(float x, float y) {
-        int index = mCurrentMatrixIndex;
-        float[] m = mMatrices;
-        m[index + 12] += m[index + 0] * x + m[index + 4] * y;
-        m[index + 13] += m[index + 1] * x + m[index + 5] * y;
-        m[index + 14] += m[index + 2] * x + m[index + 6] * y;
-        m[index + 15] += m[index + 3] * x + m[index + 7] * y;
-    }
-
-    @Override
-    public void scale(float sx, float sy, float sz) {
-        Matrix.scaleM(mMatrices, mCurrentMatrixIndex, sx, sy, sz);
-    }
-
-    @Override
-    public void rotate(float angle, float x, float y, float z) {
-        if (angle == 0f) {
-            return;
-        }
-        float[] temp = mTempMatrix;
-        Matrix.setRotateM(temp, 0, angle, x, y, z);
-        float[] matrix = mMatrices;
-        int index = mCurrentMatrixIndex;
-        Matrix.multiplyMM(temp, MATRIX_SIZE, matrix, index, temp, 0);
-        System.arraycopy(temp, MATRIX_SIZE, matrix, index, MATRIX_SIZE);
-    }
-
-    @Override
-    public void multiplyMatrix(float[] matrix, int offset) {
-        float[] temp = mTempMatrix;
-        float[] currentMatrix = mMatrices;
-        int index = mCurrentMatrixIndex;
-        Matrix.multiplyMM(temp, 0, currentMatrix, index, matrix, offset);
-        System.arraycopy(temp, 0, currentMatrix, index, 16);
-    }
-
-    @Override
-    public void save() {
-        save(SAVE_FLAG_ALL);
-    }
-
-    @Override
-    public void save(int saveFlags) {
-        boolean saveAlpha = (saveFlags & SAVE_FLAG_ALPHA) == SAVE_FLAG_ALPHA;
-        if (saveAlpha) {
-            float currentAlpha = getAlpha();
-            mCurrentAlphaIndex++;
-            if (mAlphas.length <= mCurrentAlphaIndex) {
-                mAlphas = Arrays.copyOf(mAlphas, mAlphas.length * 2);
-            }
-            mAlphas[mCurrentAlphaIndex] = currentAlpha;
-        }
-        boolean saveMatrix = (saveFlags & SAVE_FLAG_MATRIX) == SAVE_FLAG_MATRIX;
-        if (saveMatrix) {
-            int currentIndex = mCurrentMatrixIndex;
-            mCurrentMatrixIndex += MATRIX_SIZE;
-            if (mMatrices.length <= mCurrentMatrixIndex) {
-                mMatrices = Arrays.copyOf(mMatrices, mMatrices.length * 2);
-            }
-            System.arraycopy(mMatrices, currentIndex, mMatrices, mCurrentMatrixIndex, MATRIX_SIZE);
-        }
-        mSaveFlags.add(saveFlags);
-    }
-
-    @Override
-    public void restore() {
-        int restoreFlags = mSaveFlags.removeLast();
-        boolean restoreAlpha = (restoreFlags & SAVE_FLAG_ALPHA) == SAVE_FLAG_ALPHA;
-        if (restoreAlpha) {
-            mCurrentAlphaIndex--;
-        }
-        boolean restoreMatrix = (restoreFlags & SAVE_FLAG_MATRIX) == SAVE_FLAG_MATRIX;
-        if (restoreMatrix) {
-            mCurrentMatrixIndex -= MATRIX_SIZE;
-        }
-    }
-
-    @Override
-    public void drawLine(float x1, float y1, float x2, float y2, GLPaint paint) {
-        draw(GLES20.GL_LINE_STRIP, OFFSET_DRAW_LINE, COUNT_LINE_VERTEX, x1, y1, x2 - x1, y2 - y1,
-                paint);
-        mCountDrawLine++;
-    }
-
-    @Override
-    public void drawRect(float x, float y, float width, float height, GLPaint paint) {
-        draw(GLES20.GL_LINE_LOOP, OFFSET_DRAW_RECT, COUNT_RECT_VERTEX, x, y, width, height, paint);
-        mCountDrawLine++;
-    }
-
-    private void draw(int type, int offset, int count, float x, float y, float width, float height,
-            GLPaint paint) {
-        draw(type, offset, count, x, y, width, height, paint.getColor(), paint.getLineWidth());
-    }
-
-    private void draw(int type, int offset, int count, float x, float y, float width, float height,
-            int color, float lineWidth) {
-        prepareDraw(offset, color, lineWidth);
-        draw(mDrawParameters, type, count, x, y, width, height);
-    }
-
-    private void prepareDraw(int offset, int color, float lineWidth) {
-        GLES20.glUseProgram(mDrawProgram);
-        checkError();
-        if (lineWidth > 0) {
-            GLES20.glLineWidth(lineWidth);
-            checkError();
-        }
-        float[] colorArray = getColor(color);
-        boolean blendingEnabled = (colorArray[3] < 1f);
-        enableBlending(blendingEnabled);
-        if (blendingEnabled) {
-            GLES20.glBlendColor(colorArray[0], colorArray[1], colorArray[2], colorArray[3]);
-            checkError();
-        }
-
-        GLES20.glUniform4fv(mDrawParameters[INDEX_COLOR].handle, 1, colorArray, 0);
-        setPosition(mDrawParameters, offset);
-        checkError();
-    }
-
-    private float[] getColor(int color) {
-        float alpha = ((color >>> 24) & 0xFF) / 255f * getAlpha();
-        float red = ((color >>> 16) & 0xFF) / 255f * alpha;
-        float green = ((color >>> 8) & 0xFF) / 255f * alpha;
-        float blue = (color & 0xFF) / 255f * alpha;
-        mTempColor[0] = red;
-        mTempColor[1] = green;
-        mTempColor[2] = blue;
-        mTempColor[3] = alpha;
-        return mTempColor;
-    }
-
-    private void enableBlending(boolean enableBlending) {
-        if (enableBlending) {
-            GLES20.glEnable(GLES20.GL_BLEND);
-            checkError();
-        } else {
-            GLES20.glDisable(GLES20.GL_BLEND);
-            checkError();
-        }
-    }
-
-    private void setPosition(ShaderParameter[] params, int offset) {
-        GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, mBoxCoordinates);
-        checkError();
-        GLES20.glVertexAttribPointer(params[INDEX_POSITION].handle, COORDS_PER_VERTEX,
-                GLES20.GL_FLOAT, false, VERTEX_STRIDE, offset * VERTEX_STRIDE);
-        checkError();
-        GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, 0);
-        checkError();
-    }
-
-    private void draw(ShaderParameter[] params, int type, int count, float x, float y, float width,
-            float height) {
-        setMatrix(params, x, y, width, height);
-        int positionHandle = params[INDEX_POSITION].handle;
-        GLES20.glEnableVertexAttribArray(positionHandle);
-        checkError();
-        GLES20.glDrawArrays(type, 0, count);
-        checkError();
-        GLES20.glDisableVertexAttribArray(positionHandle);
-        checkError();
-    }
-
-    private void setMatrix(ShaderParameter[] params, float x, float y, float width, float height) {
-        Matrix.translateM(mTempMatrix, 0, mMatrices, mCurrentMatrixIndex, x, y, 0f);
-        Matrix.scaleM(mTempMatrix, 0, width, height, 1f);
-        Matrix.multiplyMM(mTempMatrix, MATRIX_SIZE, mProjectionMatrix, 0, mTempMatrix, 0);
-        GLES20.glUniformMatrix4fv(params[INDEX_MATRIX].handle, 1, false, mTempMatrix, MATRIX_SIZE);
-        checkError();
-    }
-
-    @Override
-    public void fillRect(float x, float y, float width, float height, int color) {
-        draw(GLES20.GL_TRIANGLE_STRIP, OFFSET_FILL_RECT, COUNT_FILL_VERTEX, x, y, width, height,
-                color, 0f);
-        mCountFillRect++;
-    }
-
-    @Override
-    public void drawTexture(BasicTexture texture, int x, int y, int width, int height) {
-        if (width <= 0 || height <= 0) {
-            return;
-        }
-        copyTextureCoordinates(texture, mTempSourceRect);
-        mTempTargetRect.set(x, y, x + width, y + height);
-        convertCoordinate(mTempSourceRect, mTempTargetRect, texture);
-        drawTextureRect(texture, mTempSourceRect, mTempTargetRect);
-    }
-
-    private static void copyTextureCoordinates(BasicTexture texture, RectF outRect) {
-        int left = 0;
-        int top = 0;
-        int right = texture.getWidth();
-        int bottom = texture.getHeight();
-        if (texture.hasBorder()) {
-            left = 1;
-            top = 1;
-            right -= 1;
-            bottom -= 1;
-        }
-        outRect.set(left, top, right, bottom);
-    }
-
-    @Override
-    public void drawTexture(BasicTexture texture, RectF source, RectF target) {
-        if (target.width() <= 0 || target.height() <= 0) {
-            return;
-        }
-        mTempSourceRect.set(source);
-        mTempTargetRect.set(target);
-
-        convertCoordinate(mTempSourceRect, mTempTargetRect, texture);
-        drawTextureRect(texture, mTempSourceRect, mTempTargetRect);
-    }
-
-    @Override
-    public void drawTexture(BasicTexture texture, float[] textureTransform, int x, int y, int w,
-            int h) {
-        if (w <= 0 || h <= 0) {
-            return;
-        }
-        mTempTargetRect.set(x, y, x + w, y + h);
-        drawTextureRect(texture, textureTransform, mTempTargetRect);
-    }
-
-    private void drawTextureRect(BasicTexture texture, RectF source, RectF target) {
-        setTextureMatrix(source);
-        drawTextureRect(texture, mTempTextureMatrix, target);
-    }
-
-    private void setTextureMatrix(RectF source) {
-        mTempTextureMatrix[0] = source.width();
-        mTempTextureMatrix[5] = source.height();
-        mTempTextureMatrix[12] = source.left;
-        mTempTextureMatrix[13] = source.top;
-    }
-
-    // This function changes the source coordinate to the texture coordinates.
-    // It also clips the source and target coordinates if it is beyond the
-    // bound of the texture.
-    private static void convertCoordinate(RectF source, RectF target, BasicTexture texture) {
-        int width = texture.getWidth();
-        int height = texture.getHeight();
-        int texWidth = texture.getTextureWidth();
-        int texHeight = texture.getTextureHeight();
-        // Convert to texture coordinates
-        source.left /= texWidth;
-        source.right /= texWidth;
-        source.top /= texHeight;
-        source.bottom /= texHeight;
-
-        // Clip if the rendering range is beyond the bound of the texture.
-        float xBound = (float) width / texWidth;
-        if (source.right > xBound) {
-            target.right = target.left + target.width() * (xBound - source.left) / source.width();
-            source.right = xBound;
-        }
-        float yBound = (float) height / texHeight;
-        if (source.bottom > yBound) {
-            target.bottom = target.top + target.height() * (yBound - source.top) / source.height();
-            source.bottom = yBound;
-        }
-    }
-
-    private void drawTextureRect(BasicTexture texture, float[] textureMatrix, RectF target) {
-        ShaderParameter[] params = prepareTexture(texture);
-        setPosition(params, OFFSET_FILL_RECT);
-        GLES20.glUniformMatrix4fv(params[INDEX_TEXTURE_MATRIX].handle, 1, false, textureMatrix, 0);
-        checkError();
-        if (texture.isFlippedVertically()) {
-            save(SAVE_FLAG_MATRIX);
-            translate(0, target.centerY());
-            scale(1, -1, 1);
-            translate(0, -target.centerY());
-        }
-        draw(params, GLES20.GL_TRIANGLE_STRIP, COUNT_FILL_VERTEX, target.left, target.top,
-                target.width(), target.height());
-        if (texture.isFlippedVertically()) {
-            restore();
-        }
-        mCountTextureRect++;
-    }
-
-    private ShaderParameter[] prepareTexture(BasicTexture texture) {
-        ShaderParameter[] params;
-        int program;
-        if (texture.getTarget() == GLES20.GL_TEXTURE_2D) {
-            params = mTextureParameters;
-            program = mTextureProgram;
-        } else {
-            params = mOesTextureParameters;
-            program = mOesTextureProgram;
-        }
-        prepareTexture(texture, program, params);
-        return params;
-    }
-
-    private void prepareTexture(BasicTexture texture, int program, ShaderParameter[] params) {
-        GLES20.glUseProgram(program);
-        checkError();
-        enableBlending(!texture.isOpaque() || getAlpha() < OPAQUE_ALPHA);
-        GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
-        checkError();
-        texture.onBind(this);
-        GLES20.glBindTexture(texture.getTarget(), texture.getId());
-        checkError();
-        GLES20.glUniform1i(params[INDEX_TEXTURE_SAMPLER].handle, 0);
-        checkError();
-        GLES20.glUniform1f(params[INDEX_ALPHA].handle, getAlpha());
-        checkError();
-    }
-
-    @Override
-    public void drawMesh(BasicTexture texture, int x, int y, int xyBuffer, int uvBuffer,
-            int indexBuffer, int indexCount) {
-        prepareTexture(texture, mMeshProgram, mMeshParameters);
-
-        GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
-        checkError();
-
-        GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, xyBuffer);
-        checkError();
-        int positionHandle = mMeshParameters[INDEX_POSITION].handle;
-        GLES20.glVertexAttribPointer(positionHandle, COORDS_PER_VERTEX, GLES20.GL_FLOAT, false,
-                VERTEX_STRIDE, 0);
-        checkError();
-
-        GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, uvBuffer);
-        checkError();
-        int texCoordHandle = mMeshParameters[INDEX_TEXTURE_COORD].handle;
-        GLES20.glVertexAttribPointer(texCoordHandle, COORDS_PER_VERTEX, GLES20.GL_FLOAT,
-                false, VERTEX_STRIDE, 0);
-        checkError();
-        GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, 0);
-        checkError();
-
-        GLES20.glEnableVertexAttribArray(positionHandle);
-        checkError();
-        GLES20.glEnableVertexAttribArray(texCoordHandle);
-        checkError();
-
-        setMatrix(mMeshParameters, x, y, 1, 1);
-        GLES20.glDrawElements(GLES20.GL_TRIANGLE_STRIP, indexCount, GLES20.GL_UNSIGNED_BYTE, 0);
-        checkError();
-
-        GLES20.glDisableVertexAttribArray(positionHandle);
-        checkError();
-        GLES20.glDisableVertexAttribArray(texCoordHandle);
-        checkError();
-        GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, 0);
-        checkError();
-        mCountDrawMesh++;
-    }
-
-    @Override
-    public void drawMixed(BasicTexture texture, int toColor, float ratio, int x, int y, int w, int h) {
-        copyTextureCoordinates(texture, mTempSourceRect);
-        mTempTargetRect.set(x, y, x + w, y + h);
-        drawMixed(texture, toColor, ratio, mTempSourceRect, mTempTargetRect);
-    }
-
-    @Override
-    public void drawMixed(BasicTexture texture, int toColor, float ratio, RectF source, RectF target) {
-        if (target.width() <= 0 || target.height() <= 0) {
-            return;
-        }
-        save(SAVE_FLAG_ALPHA);
-
-        float currentAlpha = getAlpha();
-        float cappedRatio = Math.min(1f, Math.max(0f, ratio));
-
-        float textureAlpha = (1f - cappedRatio) * currentAlpha;
-        setAlpha(textureAlpha);
-        drawTexture(texture, source, target);
-
-        float colorAlpha = cappedRatio * currentAlpha;
-        setAlpha(colorAlpha);
-        fillRect(target.left, target.top, target.width(), target.height(), toColor);
-
-        restore();
-    }
-
-    @Override
-    public boolean unloadTexture(BasicTexture texture) {
-        boolean unload = texture.isLoaded();
-        if (unload) {
-            synchronized (mUnboundTextures) {
-                mUnboundTextures.add(texture.getId());
-            }
-        }
-        return unload;
-    }
-
-    @Override
-    public void deleteBuffer(int bufferId) {
-        synchronized (mUnboundTextures) {
-            mDeleteBuffers.add(bufferId);
-        }
-    }
-
-    @Override
-    public void deleteRecycledResources() {
-        synchronized (mUnboundTextures) {
-            IntArray ids = mUnboundTextures;
-            if (mUnboundTextures.size() > 0) {
-                mGLId.glDeleteTextures(null, ids.size(), ids.getInternalArray(), 0);
-                ids.clear();
-            }
-
-            ids = mDeleteBuffers;
-            if (ids.size() > 0) {
-                mGLId.glDeleteBuffers(null, ids.size(), ids.getInternalArray(), 0);
-                ids.clear();
-            }
-        }
-    }
-
-    @Override
-    public void dumpStatisticsAndClear() {
-        String line = String.format("MESH:%d, TEX_RECT:%d, FILL_RECT:%d, LINE:%d", mCountDrawMesh,
-                mCountTextureRect, mCountFillRect, mCountDrawLine);
-        mCountDrawMesh = 0;
-        mCountTextureRect = 0;
-        mCountFillRect = 0;
-        mCountDrawLine = 0;
-        Log.d(TAG, line);
-    }
-
-    @Override
-    public void endRenderTarget() {
-        RawTexture oldTexture = mTargetTextures.remove(mTargetTextures.size() - 1);
-        RawTexture texture = getTargetTexture();
-        setRenderTarget(oldTexture, texture);
-        restore(); // restore matrix and alpha
-    }
-
-    @Override
-    public void beginRenderTarget(RawTexture texture) {
-        save(); // save matrix and alpha and blending
-        RawTexture oldTexture = getTargetTexture();
-        mTargetTextures.add(texture);
-        setRenderTarget(oldTexture, texture);
-    }
-
-    private RawTexture getTargetTexture() {
-        return mTargetTextures.get(mTargetTextures.size() - 1);
-    }
-
-    private void setRenderTarget(BasicTexture oldTexture, RawTexture texture) {
-        if (oldTexture == null && texture != null) {
-            GLES20.glGenFramebuffers(1, mFrameBuffer, 0);
-            checkError();
-            GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, mFrameBuffer[0]);
-            checkError();
-        } else if (oldTexture != null && texture == null) {
-            GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, 0);
-            checkError();
-            GLES20.glDeleteFramebuffers(1, mFrameBuffer, 0);
-            checkError();
-        }
-
-        if (texture == null) {
-            setSize(mScreenWidth, mScreenHeight);
-        } else {
-            setSize(texture.getWidth(), texture.getHeight());
-
-            if (!texture.isLoaded()) {
-                texture.prepare(this);
-            }
-
-            GLES20.glFramebufferTexture2D(GLES20.GL_FRAMEBUFFER, GLES20.GL_COLOR_ATTACHMENT0,
-                    texture.getTarget(), texture.getId(), 0);
-            checkError();
-
-            checkFramebufferStatus();
-        }
-    }
-
-    private static void checkFramebufferStatus() {
-        int status = GLES20.glCheckFramebufferStatus(GLES20.GL_FRAMEBUFFER);
-        if (status != GLES20.GL_FRAMEBUFFER_COMPLETE) {
-            String msg = "";
-            switch (status) {
-                case GLES20.GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT:
-                    msg = "GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT";
-                    break;
-                case GLES20.GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS:
-                    msg = "GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS";
-                    break;
-                case GLES20.GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT:
-                    msg = "GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT";
-                    break;
-                case GLES20.GL_FRAMEBUFFER_UNSUPPORTED:
-                    msg = "GL_FRAMEBUFFER_UNSUPPORTED";
-                    break;
-            }
-            throw new RuntimeException(msg + ":" + Integer.toHexString(status));
-        }
-    }
-
-    @Override
-    public void setTextureParameters(BasicTexture texture) {
-        int target = texture.getTarget();
-        GLES20.glBindTexture(target, texture.getId());
-        checkError();
-        GLES20.glTexParameteri(target, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_CLAMP_TO_EDGE);
-        GLES20.glTexParameteri(target, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_CLAMP_TO_EDGE);
-        GLES20.glTexParameterf(target, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_LINEAR);
-        GLES20.glTexParameterf(target, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR);
-    }
-
-    @Override
-    public void initializeTextureSize(BasicTexture texture, int format, int type) {
-        int target = texture.getTarget();
-        GLES20.glBindTexture(target, texture.getId());
-        checkError();
-        int width = texture.getTextureWidth();
-        int height = texture.getTextureHeight();
-        GLES20.glTexImage2D(target, 0, format, width, height, 0, format, type, null);
-    }
-
-    @Override
-    public void initializeTexture(BasicTexture texture, Bitmap bitmap) {
-        int target = texture.getTarget();
-        GLES20.glBindTexture(target, texture.getId());
-        checkError();
-        GLUtils.texImage2D(target, 0, bitmap, 0);
-    }
-
-    @Override
-    public void texSubImage2D(BasicTexture texture, int xOffset, int yOffset, Bitmap bitmap,
-            int format, int type) {
-        int target = texture.getTarget();
-        GLES20.glBindTexture(target, texture.getId());
-        checkError();
-        GLUtils.texSubImage2D(target, 0, xOffset, yOffset, bitmap, format, type);
-    }
-
-    @Override
-    public int uploadBuffer(FloatBuffer buf) {
-        return uploadBuffer(buf, FLOAT_SIZE);
-    }
-
-    @Override
-    public int uploadBuffer(ByteBuffer buf) {
-        return uploadBuffer(buf, 1);
-    }
-
-    private int uploadBuffer(Buffer buffer, int elementSize) {
-        mGLId.glGenBuffers(1, mTempIntArray, 0);
-        checkError();
-        int bufferId = mTempIntArray[0];
-        GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, bufferId);
-        checkError();
-        GLES20.glBufferData(GLES20.GL_ARRAY_BUFFER, buffer.capacity() * elementSize, buffer,
-                GLES20.GL_STATIC_DRAW);
-        checkError();
-        return bufferId;
-    }
-
-    public static void checkError() {
-        int error = GLES20.glGetError();
-        if (error != 0) {
-            Throwable t = new Throwable();
-            Log.e(TAG, "GL error: " + error, t);
-        }
-    }
-
-    @SuppressWarnings("unused")
-    private static void printMatrix(String message, float[] m, int offset) {
-        StringBuilder b = new StringBuilder(message);
-        for (int i = 0; i < MATRIX_SIZE; i++) {
-            b.append(' ');
-            if (i % 4 == 0) {
-                b.append('\n');
-            }
-            b.append(m[offset + i]);
-        }
-        Log.v(TAG, b.toString());
-    }
-
-    @Override
-    public void recoverFromLightCycle() {
-        GLES20.glViewport(0, 0, mWidth, mHeight);
-        GLES20.glDisable(GLES20.GL_DEPTH_TEST);
-        GLES20.glBlendFunc(GLES20.GL_ONE, GLES20.GL_ONE_MINUS_SRC_ALPHA);
-        checkError();
-    }
-
-    @Override
-    public void getBounds(Rect bounds, int x, int y, int width, int height) {
-        Matrix.translateM(mTempMatrix, 0, mMatrices, mCurrentMatrixIndex, x, y, 0f);
-        Matrix.scaleM(mTempMatrix, 0, width, height, 1f);
-        Matrix.multiplyMV(mTempMatrix, MATRIX_SIZE, mTempMatrix, 0, BOUNDS_COORDINATES, 0);
-        Matrix.multiplyMV(mTempMatrix, MATRIX_SIZE + 4, mTempMatrix, 0, BOUNDS_COORDINATES, 4);
-        bounds.left = Math.round(mTempMatrix[MATRIX_SIZE]);
-        bounds.right = Math.round(mTempMatrix[MATRIX_SIZE + 4]);
-        bounds.top = Math.round(mTempMatrix[MATRIX_SIZE + 1]);
-        bounds.bottom = Math.round(mTempMatrix[MATRIX_SIZE + 5]);
-        bounds.sort();
-    }
-
-    @Override
-    public GLId getGLId() {
-        return mGLId;
-    }
-}
diff --git a/src/com/android/gallery3d/glrenderer/GLES20IdImpl.java b/src/com/android/gallery3d/glrenderer/GLES20IdImpl.java
deleted file mode 100644
index 6cd7149..0000000
--- a/src/com/android/gallery3d/glrenderer/GLES20IdImpl.java
+++ /dev/null
@@ -1,42 +0,0 @@
-package com.android.gallery3d.glrenderer;
-
-import android.opengl.GLES20;
-
-import javax.microedition.khronos.opengles.GL11;
-import javax.microedition.khronos.opengles.GL11ExtensionPack;
-
-public class GLES20IdImpl implements GLId {
-    private final int[] mTempIntArray = new int[1];
-
-    @Override
-    public int generateTexture() {
-        GLES20.glGenTextures(1, mTempIntArray, 0);
-        GLES20Canvas.checkError();
-        return mTempIntArray[0];
-    }
-
-    @Override
-    public void glGenBuffers(int n, int[] buffers, int offset) {
-        GLES20.glGenBuffers(n, buffers, offset);
-        GLES20Canvas.checkError();
-    }
-
-    @Override
-    public void glDeleteTextures(GL11 gl, int n, int[] textures, int offset) {
-        GLES20.glDeleteTextures(n, textures, offset);
-        GLES20Canvas.checkError();
-    }
-
-
-    @Override
-    public void glDeleteBuffers(GL11 gl, int n, int[] buffers, int offset) {
-        GLES20.glDeleteBuffers(n, buffers, offset);
-        GLES20Canvas.checkError();
-    }
-
-    @Override
-    public void glDeleteFramebuffers(GL11ExtensionPack gl11ep, int n, int[] buffers, int offset) {
-        GLES20.glDeleteFramebuffers(n, buffers, offset);
-        GLES20Canvas.checkError();
-    }
-}
diff --git a/src/com/android/gallery3d/glrenderer/GLId.java b/src/com/android/gallery3d/glrenderer/GLId.java
deleted file mode 100644
index 3cec558..0000000
--- a/src/com/android/gallery3d/glrenderer/GLId.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * 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.gallery3d.glrenderer;
-
-import javax.microedition.khronos.opengles.GL11;
-import javax.microedition.khronos.opengles.GL11ExtensionPack;
-
-// This mimics corresponding GL functions.
-public interface GLId {
-    public int generateTexture();
-
-    public void glGenBuffers(int n, int[] buffers, int offset);
-
-    public void glDeleteTextures(GL11 gl, int n, int[] textures, int offset);
-
-    public void glDeleteBuffers(GL11 gl, int n, int[] buffers, int offset);
-
-    public void glDeleteFramebuffers(GL11ExtensionPack gl11ep, int n, int[] buffers, int offset);
-}
diff --git a/src/com/android/gallery3d/glrenderer/GLPaint.java b/src/com/android/gallery3d/glrenderer/GLPaint.java
deleted file mode 100644
index 16b2206..0000000
--- a/src/com/android/gallery3d/glrenderer/GLPaint.java
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright (C) 2010 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.gallery3d.glrenderer;
-
-import junit.framework.Assert;
-
-public class GLPaint {
-    private float mLineWidth = 1f;
-    private int mColor = 0;
-
-    public void setColor(int color) {
-        mColor = color;
-    }
-
-    public int getColor() {
-        return mColor;
-    }
-
-    public void setLineWidth(float width) {
-        Assert.assertTrue(width >= 0);
-        mLineWidth = width;
-    }
-
-    public float getLineWidth() {
-        return mLineWidth;
-    }
-}
diff --git a/src/com/android/gallery3d/glrenderer/MultiLineTexture.java b/src/com/android/gallery3d/glrenderer/MultiLineTexture.java
deleted file mode 100644
index 82839f1..0000000
--- a/src/com/android/gallery3d/glrenderer/MultiLineTexture.java
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Copyright (C) 2010 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.gallery3d.glrenderer;
-
-import android.graphics.Bitmap;
-import android.graphics.Canvas;
-import android.text.Layout;
-import android.text.StaticLayout;
-import android.text.TextPaint;
-
-
-// MultiLineTexture is a texture shows the content of a specified String.
-//
-// To create a MultiLineTexture, use the newInstance() method and specify
-// the String, the font size, and the color.
-class MultiLineTexture extends CanvasTexture {
-    private final Layout mLayout;
-
-    private MultiLineTexture(Layout layout) {
-        super(layout.getWidth(), layout.getHeight());
-        mLayout = layout;
-    }
-
-    public static MultiLineTexture newInstance(
-            String text, int maxWidth, float textSize, int color,
-            Layout.Alignment alignment) {
-        TextPaint paint = StringTexture.getDefaultPaint(textSize, color);
-        Layout layout = new StaticLayout(text, 0, text.length(), paint,
-                maxWidth, alignment, 1, 0, true, null, 0);
-
-        return new MultiLineTexture(layout);
-    }
-
-    @Override
-    protected void onDraw(Canvas canvas, Bitmap backing) {
-        mLayout.draw(canvas);
-    }
-}
diff --git a/src/com/android/gallery3d/glrenderer/NinePatchChunk.java b/src/com/android/gallery3d/glrenderer/NinePatchChunk.java
deleted file mode 100644
index 9dc3266..0000000
--- a/src/com/android/gallery3d/glrenderer/NinePatchChunk.java
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * Copyright (C) 2010 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.gallery3d.glrenderer;
-
-import android.graphics.Rect;
-
-import java.nio.ByteBuffer;
-import java.nio.ByteOrder;
-
-// See "frameworks/base/include/utils/ResourceTypes.h" for the format of
-// NinePatch chunk.
-class NinePatchChunk {
-
-    public static final int NO_COLOR = 0x00000001;
-    public static final int TRANSPARENT_COLOR = 0x00000000;
-
-    public Rect mPaddings = new Rect();
-
-    public int mDivX[];
-    public int mDivY[];
-    public int mColor[];
-
-    private static void readIntArray(int[] data, ByteBuffer buffer) {
-        for (int i = 0, n = data.length; i < n; ++i) {
-            data[i] = buffer.getInt();
-        }
-    }
-
-    private static void checkDivCount(int length) {
-        if (length == 0 || (length & 0x01) != 0) {
-            throw new RuntimeException("invalid nine-patch: " + length);
-        }
-    }
-
-    public static NinePatchChunk deserialize(byte[] data) {
-        ByteBuffer byteBuffer =
-                ByteBuffer.wrap(data).order(ByteOrder.nativeOrder());
-
-        byte wasSerialized = byteBuffer.get();
-        if (wasSerialized == 0) return null;
-
-        NinePatchChunk chunk = new NinePatchChunk();
-        chunk.mDivX = new int[byteBuffer.get()];
-        chunk.mDivY = new int[byteBuffer.get()];
-        chunk.mColor = new int[byteBuffer.get()];
-
-        checkDivCount(chunk.mDivX.length);
-        checkDivCount(chunk.mDivY.length);
-
-        // skip 8 bytes
-        byteBuffer.getInt();
-        byteBuffer.getInt();
-
-        chunk.mPaddings.left = byteBuffer.getInt();
-        chunk.mPaddings.right = byteBuffer.getInt();
-        chunk.mPaddings.top = byteBuffer.getInt();
-        chunk.mPaddings.bottom = byteBuffer.getInt();
-
-        // skip 4 bytes
-        byteBuffer.getInt();
-
-        readIntArray(chunk.mDivX, byteBuffer);
-        readIntArray(chunk.mDivY, byteBuffer);
-        readIntArray(chunk.mColor, byteBuffer);
-
-        return chunk;
-    }
-}
\ No newline at end of file
diff --git a/src/com/android/gallery3d/glrenderer/NinePatchTexture.java b/src/com/android/gallery3d/glrenderer/NinePatchTexture.java
deleted file mode 100644
index d0ddc46..0000000
--- a/src/com/android/gallery3d/glrenderer/NinePatchTexture.java
+++ /dev/null
@@ -1,424 +0,0 @@
-/*
- * Copyright (C) 2010 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.gallery3d.glrenderer;
-
-import android.content.Context;
-import android.graphics.Bitmap;
-import android.graphics.BitmapFactory;
-import android.graphics.Rect;
-
-import com.android.gallery3d.common.Utils;
-
-import java.nio.ByteBuffer;
-import java.nio.ByteOrder;
-import java.nio.FloatBuffer;
-
-// NinePatchTexture is a texture backed by a NinePatch resource.
-//
-// getPaddings() returns paddings specified in the NinePatch.
-// getNinePatchChunk() returns the layout data specified in the NinePatch.
-//
-public class NinePatchTexture extends ResourceTexture {
-    @SuppressWarnings("unused")
-    private static final String TAG = "NinePatchTexture";
-    private NinePatchChunk mChunk;
-    private SmallCache<NinePatchInstance> mInstanceCache
-            = new SmallCache<NinePatchInstance>();
-
-    public NinePatchTexture(Context context, int resId) {
-        super(context, resId);
-    }
-
-    @Override
-    protected Bitmap onGetBitmap() {
-        if (mBitmap != null) return mBitmap;
-
-        BitmapFactory.Options options = new BitmapFactory.Options();
-        options.inPreferredConfig = Bitmap.Config.ARGB_8888;
-        Bitmap bitmap = BitmapFactory.decodeResource(
-                mContext.getResources(), mResId, options);
-        mBitmap = bitmap;
-        setSize(bitmap.getWidth(), bitmap.getHeight());
-        byte[] chunkData = bitmap.getNinePatchChunk();
-        mChunk = chunkData == null
-                ? null
-                : NinePatchChunk.deserialize(bitmap.getNinePatchChunk());
-        if (mChunk == null) {
-            throw new RuntimeException("invalid nine-patch image: " + mResId);
-        }
-        return bitmap;
-    }
-
-    public Rect getPaddings() {
-        // get the paddings from nine patch
-        if (mChunk == null) onGetBitmap();
-        return mChunk.mPaddings;
-    }
-
-    public NinePatchChunk getNinePatchChunk() {
-        if (mChunk == null) onGetBitmap();
-        return mChunk;
-    }
-
-    // This is a simple cache for a small number of things. Linear search
-    // is used because the cache is small. It also tries to remove less used
-    // item when the cache is full by moving the often-used items to the front.
-    private static class SmallCache<V> {
-        private static final int CACHE_SIZE = 16;
-        private static final int CACHE_SIZE_START_MOVE = CACHE_SIZE / 2;
-        private int[] mKey = new int[CACHE_SIZE];
-        private V[] mValue = (V[]) new Object[CACHE_SIZE];
-        private int mCount;  // number of items in this cache
-
-        // Puts a value into the cache. If the cache is full, also returns
-        // a less used item, otherwise returns null.
-        public V put(int key, V value) {
-            if (mCount == CACHE_SIZE) {
-                V old = mValue[CACHE_SIZE - 1];  // remove the last item
-                mKey[CACHE_SIZE - 1] = key;
-                mValue[CACHE_SIZE - 1] = value;
-                return old;
-            } else {
-                mKey[mCount] = key;
-                mValue[mCount] = value;
-                mCount++;
-                return null;
-            }
-        }
-
-        public V get(int key) {
-            for (int i = 0; i < mCount; i++) {
-                if (mKey[i] == key) {
-                    // Move the accessed item one position to the front, so it
-                    // will less likely to be removed when cache is full. Only
-                    // do this if the cache is starting to get full.
-                    if (mCount > CACHE_SIZE_START_MOVE && i > 0) {
-                        int tmpKey = mKey[i];
-                        mKey[i] = mKey[i - 1];
-                        mKey[i - 1] = tmpKey;
-
-                        V tmpValue = mValue[i];
-                        mValue[i] = mValue[i - 1];
-                        mValue[i - 1] = tmpValue;
-                    }
-                    return mValue[i];
-                }
-            }
-            return null;
-        }
-
-        public void clear() {
-            for (int i = 0; i < mCount; i++) {
-                mValue[i] = null;  // make sure it's can be garbage-collected.
-            }
-            mCount = 0;
-        }
-
-        public int size() {
-            return mCount;
-        }
-
-        public V valueAt(int i) {
-            return mValue[i];
-        }
-    }
-
-    private NinePatchInstance findInstance(GLCanvas canvas, int w, int h) {
-        int key = w;
-        key = (key << 16) | h;
-        NinePatchInstance instance = mInstanceCache.get(key);
-
-        if (instance == null) {
-            instance = new NinePatchInstance(this, w, h);
-            NinePatchInstance removed = mInstanceCache.put(key, instance);
-            if (removed != null) {
-                removed.recycle(canvas);
-            }
-        }
-
-        return instance;
-    }
-
-    @Override
-    public void draw(GLCanvas canvas, int x, int y, int w, int h) {
-        if (!isLoaded()) {
-            mInstanceCache.clear();
-        }
-
-        if (w != 0 && h != 0) {
-            findInstance(canvas, w, h).draw(canvas, this, x, y);
-        }
-    }
-
-    @Override
-    public void recycle() {
-        super.recycle();
-        GLCanvas canvas = mCanvasRef;
-        if (canvas == null) return;
-        int n = mInstanceCache.size();
-        for (int i = 0; i < n; i++) {
-            NinePatchInstance instance = mInstanceCache.valueAt(i);
-            instance.recycle(canvas);
-        }
-        mInstanceCache.clear();
-    }
-}
-
-// This keeps data for a specialization of NinePatchTexture with the size
-// (width, height). We pre-compute the coordinates for efficiency.
-class NinePatchInstance {
-
-    @SuppressWarnings("unused")
-    private static final String TAG = "NinePatchInstance";
-
-    // We need 16 vertices for a normal nine-patch image (the 4x4 vertices)
-    private static final int VERTEX_BUFFER_SIZE = 16 * 2;
-
-    // We need 22 indices for a normal nine-patch image, plus 2 for each
-    // transparent region. Current there are at most 1 transparent region.
-    private static final int INDEX_BUFFER_SIZE = 22 + 2;
-
-    private FloatBuffer mXyBuffer;
-    private FloatBuffer mUvBuffer;
-    private ByteBuffer mIndexBuffer;
-
-    // Names for buffer names: xy, uv, index.
-    private int mXyBufferName = -1;
-    private int mUvBufferName;
-    private int mIndexBufferName;
-
-    private int mIdxCount;
-
-    public NinePatchInstance(NinePatchTexture tex, int width, int height) {
-        NinePatchChunk chunk = tex.getNinePatchChunk();
-
-        if (width <= 0 || height <= 0) {
-            throw new RuntimeException("invalid dimension");
-        }
-
-        // The code should be easily extended to handle the general cases by
-        // allocating more space for buffers. But let's just handle the only
-        // use case.
-        if (chunk.mDivX.length != 2 || chunk.mDivY.length != 2) {
-            throw new RuntimeException("unsupported nine patch");
-        }
-
-        float divX[] = new float[4];
-        float divY[] = new float[4];
-        float divU[] = new float[4];
-        float divV[] = new float[4];
-
-        int nx = stretch(divX, divU, chunk.mDivX, tex.getWidth(), width);
-        int ny = stretch(divY, divV, chunk.mDivY, tex.getHeight(), height);
-
-        prepareVertexData(divX, divY, divU, divV, nx, ny, chunk.mColor);
-    }
-
-    /**
-     * Stretches the texture according to the nine-patch rules. It will
-     * linearly distribute the strechy parts defined in the nine-patch chunk to
-     * the target area.
-     *
-     * <pre>
-     *                      source
-     *          /--------------^---------------\
-     *         u0    u1       u2  u3     u4   u5
-     * div ---> |fffff|ssssssss|fff|ssssss|ffff| ---> u
-     *          |    div0    div1 div2   div3  |
-     *          |     |       /   /      /    /
-     *          |     |      /   /     /    /
-     *          |     |     /   /    /    /
-     *          |fffff|ssss|fff|sss|ffff| ---> x
-     *         x0    x1   x2  x3  x4   x5
-     *          \----------v------------/
-     *                  target
-     *
-     * f: fixed segment
-     * s: stretchy segment
-     * </pre>
-     *
-     * @param div the stretch parts defined in nine-patch chunk
-     * @param source the length of the texture
-     * @param target the length on the drawing plan
-     * @param u output, the positions of these dividers in the texture
-     *        coordinate
-     * @param x output, the corresponding position of these dividers on the
-     *        drawing plan
-     * @return the number of these dividers.
-     */
-    private static int stretch(
-            float x[], float u[], int div[], int source, int target) {
-        int textureSize = Utils.nextPowerOf2(source);
-        float textureBound = (float) source / textureSize;
-
-        float stretch = 0;
-        for (int i = 0, n = div.length; i < n; i += 2) {
-            stretch += div[i + 1] - div[i];
-        }
-
-        float remaining = target - source + stretch;
-
-        float lastX = 0;
-        float lastU = 0;
-
-        x[0] = 0;
-        u[0] = 0;
-        for (int i = 0, n = div.length; i < n; i += 2) {
-            // Make the stretchy segment a little smaller to prevent sampling
-            // on neighboring fixed segments.
-            // fixed segment
-            x[i + 1] = lastX + (div[i] - lastU) + 0.5f;
-            u[i + 1] = Math.min((div[i] + 0.5f) / textureSize, textureBound);
-
-            // stretchy segment
-            float partU = div[i + 1] - div[i];
-            float partX = remaining * partU / stretch;
-            remaining -= partX;
-            stretch -= partU;
-
-            lastX = x[i + 1] + partX;
-            lastU = div[i + 1];
-            x[i + 2] = lastX - 0.5f;
-            u[i + 2] = Math.min((lastU - 0.5f)/ textureSize, textureBound);
-        }
-        // the last fixed segment
-        x[div.length + 1] = target;
-        u[div.length + 1] = textureBound;
-
-        // remove segments with length 0.
-        int last = 0;
-        for (int i = 1, n = div.length + 2; i < n; ++i) {
-            if ((x[i] - x[last]) < 1f) continue;
-            x[++last] = x[i];
-            u[last] = u[i];
-        }
-        return last + 1;
-    }
-
-    private void prepareVertexData(float x[], float y[], float u[], float v[],
-            int nx, int ny, int[] color) {
-        /*
-         * Given a 3x3 nine-patch image, the vertex order is defined as the
-         * following graph:
-         *
-         * (0) (1) (2) (3)
-         *  |  /|  /|  /|
-         *  | / | / | / |
-         * (4) (5) (6) (7)
-         *  | \ | \ | \ |
-         *  |  \|  \|  \|
-         * (8) (9) (A) (B)
-         *  |  /|  /|  /|
-         *  | / | / | / |
-         * (C) (D) (E) (F)
-         *
-         * And we draw the triangle strip in the following index order:
-         *
-         * index: 04152637B6A5948C9DAEBF
-         */
-        int pntCount = 0;
-        float xy[] = new float[VERTEX_BUFFER_SIZE];
-        float uv[] = new float[VERTEX_BUFFER_SIZE];
-        for (int j = 0; j < ny; ++j) {
-            for (int i = 0; i < nx; ++i) {
-                int xIndex = (pntCount++) << 1;
-                int yIndex = xIndex + 1;
-                xy[xIndex] = x[i];
-                xy[yIndex] = y[j];
-                uv[xIndex] = u[i];
-                uv[yIndex] = v[j];
-            }
-        }
-
-        int idxCount = 1;
-        boolean isForward = false;
-        byte index[] = new byte[INDEX_BUFFER_SIZE];
-        for (int row = 0; row < ny - 1; row++) {
-            --idxCount;
-            isForward = !isForward;
-
-            int start, end, inc;
-            if (isForward) {
-                start = 0;
-                end = nx;
-                inc = 1;
-            } else {
-                start = nx - 1;
-                end = -1;
-                inc = -1;
-            }
-
-            for (int col = start; col != end; col += inc) {
-                int k = row * nx + col;
-                if (col != start) {
-                    int colorIdx = row * (nx - 1) + col;
-                    if (isForward) colorIdx--;
-                    if (color[colorIdx] == NinePatchChunk.TRANSPARENT_COLOR) {
-                        index[idxCount] = index[idxCount - 1];
-                        ++idxCount;
-                        index[idxCount++] = (byte) k;
-                    }
-                }
-
-                index[idxCount++] = (byte) k;
-                index[idxCount++] = (byte) (k + nx);
-            }
-        }
-
-        mIdxCount = idxCount;
-
-        int size = (pntCount * 2) * (Float.SIZE / Byte.SIZE);
-        mXyBuffer = allocateDirectNativeOrderBuffer(size).asFloatBuffer();
-        mUvBuffer = allocateDirectNativeOrderBuffer(size).asFloatBuffer();
-        mIndexBuffer = allocateDirectNativeOrderBuffer(mIdxCount);
-
-        mXyBuffer.put(xy, 0, pntCount * 2).position(0);
-        mUvBuffer.put(uv, 0, pntCount * 2).position(0);
-        mIndexBuffer.put(index, 0, idxCount).position(0);
-    }
-
-    private static ByteBuffer allocateDirectNativeOrderBuffer(int size) {
-        return ByteBuffer.allocateDirect(size).order(ByteOrder.nativeOrder());
-    }
-
-    private void prepareBuffers(GLCanvas canvas) {
-        mXyBufferName = canvas.uploadBuffer(mXyBuffer);
-        mUvBufferName = canvas.uploadBuffer(mUvBuffer);
-        mIndexBufferName = canvas.uploadBuffer(mIndexBuffer);
-
-        // These buffers are never used again.
-        mXyBuffer = null;
-        mUvBuffer = null;
-        mIndexBuffer = null;
-    }
-
-    public void draw(GLCanvas canvas, NinePatchTexture tex, int x, int y) {
-        if (mXyBufferName == -1) {
-            prepareBuffers(canvas);
-        }
-        canvas.drawMesh(tex, x, y, mXyBufferName, mUvBufferName, mIndexBufferName, mIdxCount);
-    }
-
-    public void recycle(GLCanvas canvas) {
-        if (mXyBuffer == null) {
-            canvas.deleteBuffer(mXyBufferName);
-            canvas.deleteBuffer(mUvBufferName);
-            canvas.deleteBuffer(mIndexBufferName);
-            mXyBufferName = -1;
-        }
-    }
-}
diff --git a/src/com/android/gallery3d/glrenderer/RawTexture.java b/src/com/android/gallery3d/glrenderer/RawTexture.java
deleted file mode 100644
index 93f0fdf..0000000
--- a/src/com/android/gallery3d/glrenderer/RawTexture.java
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * Copyright (C) 2010 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.gallery3d.glrenderer;
-
-import android.util.Log;
-
-import javax.microedition.khronos.opengles.GL11;
-
-public class RawTexture extends BasicTexture {
-    private static final String TAG = "RawTexture";
-
-    private final boolean mOpaque;
-    private boolean mIsFlipped;
-
-    public RawTexture(int width, int height, boolean opaque) {
-        mOpaque = opaque;
-        setSize(width, height);
-    }
-
-    @Override
-    public boolean isOpaque() {
-        return mOpaque;
-    }
-
-    @Override
-    public boolean isFlippedVertically() {
-        return mIsFlipped;
-    }
-
-    public void setIsFlippedVertically(boolean isFlipped) {
-        mIsFlipped = isFlipped;
-    }
-
-    protected void prepare(GLCanvas canvas) {
-        GLId glId = canvas.getGLId();
-        mId = glId.generateTexture();
-        canvas.initializeTextureSize(this, GL11.GL_RGBA, GL11.GL_UNSIGNED_BYTE);
-        canvas.setTextureParameters(this);
-        mState = STATE_LOADED;
-        setAssociatedCanvas(canvas);
-    }
-
-    @Override
-    protected boolean onBind(GLCanvas canvas) {
-        if (isLoaded()) return true;
-        Log.w(TAG, "lost the content due to context change");
-        return false;
-    }
-
-    @Override
-     public void yield() {
-         // we cannot free the texture because we have no backup.
-     }
-
-    @Override
-    protected int getTarget() {
-        return GL11.GL_TEXTURE_2D;
-    }
-}
diff --git a/src/com/android/gallery3d/glrenderer/ResourceTexture.java b/src/com/android/gallery3d/glrenderer/ResourceTexture.java
deleted file mode 100644
index eb8e8a5..0000000
--- a/src/com/android/gallery3d/glrenderer/ResourceTexture.java
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Copyright (C) 2010 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.gallery3d.glrenderer;
-
-import android.content.Context;
-import android.graphics.Bitmap;
-import android.graphics.BitmapFactory;
-
-import junit.framework.Assert;
-
-// ResourceTexture is a texture whose Bitmap is decoded from a resource.
-// By default ResourceTexture is not opaque.
-public class ResourceTexture extends UploadedTexture {
-
-    protected final Context mContext;
-    protected final int mResId;
-
-    public ResourceTexture(Context context, int resId) {
-        Assert.assertNotNull(context);
-        mContext = context;
-        mResId = resId;
-        setOpaque(false);
-    }
-
-    @Override
-    protected Bitmap onGetBitmap() {
-        BitmapFactory.Options options = new BitmapFactory.Options();
-        options.inPreferredConfig = Bitmap.Config.ARGB_8888;
-        return BitmapFactory.decodeResource(
-                mContext.getResources(), mResId, options);
-    }
-
-    @Override
-    protected void onFreeBitmap(Bitmap bitmap) {
-        if (!inFinalizer()) {
-            bitmap.recycle();
-        }
-    }
-}
diff --git a/src/com/android/gallery3d/glrenderer/StringTexture.java b/src/com/android/gallery3d/glrenderer/StringTexture.java
deleted file mode 100644
index 56ca297..0000000
--- a/src/com/android/gallery3d/glrenderer/StringTexture.java
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- * Copyright (C) 2010 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.gallery3d.glrenderer;
-
-import android.graphics.Bitmap;
-import android.graphics.Canvas;
-import android.graphics.Color;
-import android.graphics.Paint.FontMetricsInt;
-import android.graphics.Typeface;
-import android.text.TextPaint;
-import android.text.TextUtils;
-import android.util.FloatMath;
-
-// StringTexture is a texture shows the content of a specified String.
-//
-// To create a StringTexture, use the newInstance() method and specify
-// the String, the font size, and the color.
-public class StringTexture extends CanvasTexture {
-    private final String mText;
-    private final TextPaint mPaint;
-    private final FontMetricsInt mMetrics;
-
-    private StringTexture(String text, TextPaint paint,
-            FontMetricsInt metrics, int width, int height) {
-        super(width, height);
-        mText = text;
-        mPaint = paint;
-        mMetrics = metrics;
-    }
-
-    public static TextPaint getDefaultPaint(float textSize, int color) {
-        TextPaint paint = new TextPaint();
-        paint.setTextSize(textSize);
-        paint.setAntiAlias(true);
-        paint.setColor(color);
-        paint.setShadowLayer(2f, 0f, 0f, Color.BLACK);
-        return paint;
-    }
-
-    public static StringTexture newInstance(
-            String text, float textSize, int color) {
-        return newInstance(text, getDefaultPaint(textSize, color));
-    }
-
-    public static StringTexture newInstance(
-            String text, float textSize, int color,
-            float lengthLimit, boolean isBold) {
-        TextPaint paint = getDefaultPaint(textSize, color);
-        if (isBold) {
-            paint.setTypeface(Typeface.defaultFromStyle(Typeface.BOLD));
-        }
-        if (lengthLimit > 0) {
-            text = TextUtils.ellipsize(
-                    text, paint, lengthLimit, TextUtils.TruncateAt.END).toString();
-        }
-        return newInstance(text, paint);
-    }
-
-    private static StringTexture newInstance(String text, TextPaint paint) {
-        FontMetricsInt metrics = paint.getFontMetricsInt();
-        int width = (int) FloatMath.ceil(paint.measureText(text));
-        int height = metrics.bottom - metrics.top;
-        // The texture size needs to be at least 1x1.
-        if (width <= 0) width = 1;
-        if (height <= 0) height = 1;
-        return new StringTexture(text, paint, metrics, width, height);
-    }
-
-    @Override
-    protected void onDraw(Canvas canvas, Bitmap backing) {
-        canvas.translate(0, -mMetrics.ascent);
-        canvas.drawText(mText, 0, 0, mPaint);
-    }
-}
diff --git a/src/com/android/gallery3d/glrenderer/Texture.java b/src/com/android/gallery3d/glrenderer/Texture.java
deleted file mode 100644
index 3dcae4a..0000000
--- a/src/com/android/gallery3d/glrenderer/Texture.java
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Copyright (C) 2010 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.gallery3d.glrenderer;
-
-
-// Texture is a rectangular image which can be drawn on GLCanvas.
-// The isOpaque() function gives a hint about whether the texture is opaque,
-// so the drawing can be done faster.
-//
-// This is the current texture hierarchy:
-//
-// Texture
-// -- ColorTexture
-// -- FadeInTexture
-// -- BasicTexture
-//    -- UploadedTexture
-//       -- BitmapTexture
-//       -- Tile
-//       -- ResourceTexture
-//          -- NinePatchTexture
-//       -- CanvasTexture
-//          -- StringTexture
-//
-public interface Texture {
-    public int getWidth();
-    public int getHeight();
-    public void draw(GLCanvas canvas, int x, int y);
-    public void draw(GLCanvas canvas, int x, int y, int w, int h);
-    public boolean isOpaque();
-}
diff --git a/src/com/android/gallery3d/glrenderer/TextureUploader.java b/src/com/android/gallery3d/glrenderer/TextureUploader.java
deleted file mode 100644
index f17ab84..0000000
--- a/src/com/android/gallery3d/glrenderer/TextureUploader.java
+++ /dev/null
@@ -1,105 +0,0 @@
-/*
- * 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.gallery3d.glrenderer;
-
-import com.android.gallery3d.ui.GLRoot;
-import com.android.gallery3d.ui.GLRoot.OnGLIdleListener;
-
-import java.util.ArrayDeque;
-
-public class TextureUploader implements OnGLIdleListener {
-    private static final int INIT_CAPACITY = 64;
-    private static final int QUOTA_PER_FRAME = 1;
-
-    private final ArrayDeque<UploadedTexture> mFgTextures =
-            new ArrayDeque<UploadedTexture>(INIT_CAPACITY);
-    private final ArrayDeque<UploadedTexture> mBgTextures =
-            new ArrayDeque<UploadedTexture>(INIT_CAPACITY);
-    private final GLRoot mGLRoot;
-    private volatile boolean mIsQueued = false;
-
-    public TextureUploader(GLRoot root) {
-        mGLRoot = root;
-    }
-
-    public synchronized void clear() {
-        while (!mFgTextures.isEmpty()) {
-            mFgTextures.pop().setIsUploading(false);
-        }
-        while (!mBgTextures.isEmpty()) {
-            mBgTextures.pop().setIsUploading(false);
-        }
-    }
-
-    // caller should hold synchronized on "this"
-    private void queueSelfIfNeed() {
-        if (mIsQueued) return;
-        mIsQueued = true;
-        mGLRoot.addOnGLIdleListener(this);
-    }
-
-    public synchronized void addBgTexture(UploadedTexture t) {
-        if (t.isContentValid()) return;
-        mBgTextures.addLast(t);
-        t.setIsUploading(true);
-        queueSelfIfNeed();
-    }
-
-    public synchronized void addFgTexture(UploadedTexture t) {
-        if (t.isContentValid()) return;
-        mFgTextures.addLast(t);
-        t.setIsUploading(true);
-        queueSelfIfNeed();
-    }
-
-    private int upload(GLCanvas canvas, ArrayDeque<UploadedTexture> deque,
-            int uploadQuota, boolean isBackground) {
-        while (uploadQuota > 0) {
-            UploadedTexture t;
-            synchronized (this) {
-                if (deque.isEmpty()) break;
-                t = deque.removeFirst();
-                t.setIsUploading(false);
-                if (t.isContentValid()) continue;
-
-                // this has to be protected by the synchronized block
-                // to prevent the inner bitmap get recycled
-                t.updateContent(canvas);
-            }
-
-            // It will took some more time for a texture to be drawn for
-            // the first time.
-            // Thus, when scrolling, if a new column appears on screen,
-            // it may cause a UI jank even these textures are uploaded.
-            if (isBackground) t.draw(canvas, 0, 0);
-            --uploadQuota;
-        }
-        return uploadQuota;
-    }
-
-    @Override
-    public boolean onGLIdle(GLCanvas canvas, boolean renderRequested) {
-        int uploadQuota = QUOTA_PER_FRAME;
-        uploadQuota = upload(canvas, mFgTextures, uploadQuota, false);
-        if (uploadQuota < QUOTA_PER_FRAME) mGLRoot.requestRender();
-        upload(canvas, mBgTextures, uploadQuota, true);
-        synchronized (this) {
-            mIsQueued = !mFgTextures.isEmpty() || !mBgTextures.isEmpty();
-            return mIsQueued;
-        }
-    }
-}
diff --git a/src/com/android/gallery3d/glrenderer/TiledTexture.java b/src/com/android/gallery3d/glrenderer/TiledTexture.java
deleted file mode 100644
index 6ca1de0..0000000
--- a/src/com/android/gallery3d/glrenderer/TiledTexture.java
+++ /dev/null
@@ -1,349 +0,0 @@
-/*
- * 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.gallery3d.glrenderer;
-
-import android.graphics.Bitmap;
-import android.graphics.Bitmap.Config;
-import android.graphics.Canvas;
-import android.graphics.Color;
-import android.graphics.Paint;
-import android.graphics.PorterDuff.Mode;
-import android.graphics.PorterDuffXfermode;
-import android.graphics.RectF;
-import android.os.SystemClock;
-
-import com.android.gallery3d.ui.GLRoot;
-import com.android.gallery3d.ui.GLRoot.OnGLIdleListener;
-
-import java.util.ArrayDeque;
-import java.util.ArrayList;
-
-// This class is similar to BitmapTexture, except the bitmap is
-// split into tiles. By doing so, we may increase the time required to
-// upload the whole bitmap but we reduce the time of uploading each tile
-// so it make the animation more smooth and prevents jank.
-public class TiledTexture implements Texture {
-    private static final int CONTENT_SIZE = 254;
-    private static final int BORDER_SIZE = 1;
-    private static final int TILE_SIZE = CONTENT_SIZE + 2 * BORDER_SIZE;
-    private static final int INIT_CAPACITY = 8;
-
-    // We are targeting at 60fps, so we have 16ms for each frame.
-    // In this 16ms, we use about 4~8 ms to upload tiles.
-    private static final long UPLOAD_TILE_LIMIT = 4; // ms
-
-    private static Tile sFreeTileHead = null;
-    private static final Object sFreeTileLock = new Object();
-
-    private static Bitmap sUploadBitmap;
-    private static Canvas sCanvas;
-    private static Paint sBitmapPaint;
-    private static Paint sPaint;
-
-    private int mUploadIndex = 0;
-
-    private final Tile[] mTiles;  // Can be modified in different threads.
-                                  // Should be protected by "synchronized."
-    private final int mWidth;
-    private final int mHeight;
-    private final RectF mSrcRect = new RectF();
-    private final RectF mDestRect = new RectF();
-
-    public static class Uploader implements OnGLIdleListener {
-        private final ArrayDeque<TiledTexture> mTextures =
-                new ArrayDeque<TiledTexture>(INIT_CAPACITY);
-
-        private final GLRoot mGlRoot;
-        private boolean mIsQueued = false;
-
-        public Uploader(GLRoot glRoot) {
-            mGlRoot = glRoot;
-        }
-
-        public synchronized void clear() {
-            mTextures.clear();
-        }
-
-        public synchronized void addTexture(TiledTexture t) {
-            if (t.isReady()) return;
-            mTextures.addLast(t);
-
-            if (mIsQueued) return;
-            mIsQueued = true;
-            mGlRoot.addOnGLIdleListener(this);
-        }
-
-        @Override
-        public boolean onGLIdle(GLCanvas canvas, boolean renderRequested) {
-            ArrayDeque<TiledTexture> deque = mTextures;
-            synchronized (this) {
-                long now = SystemClock.uptimeMillis();
-                long dueTime = now + UPLOAD_TILE_LIMIT;
-                while (now < dueTime && !deque.isEmpty()) {
-                    TiledTexture t = deque.peekFirst();
-                    if (t.uploadNextTile(canvas)) {
-                        deque.removeFirst();
-                        mGlRoot.requestRender();
-                    }
-                    now = SystemClock.uptimeMillis();
-                }
-                mIsQueued = !mTextures.isEmpty();
-
-                // return true to keep this listener in the queue
-                return mIsQueued;
-            }
-        }
-    }
-
-    private static class Tile extends UploadedTexture {
-        public int offsetX;
-        public int offsetY;
-        public Bitmap bitmap;
-        public Tile nextFreeTile;
-        public int contentWidth;
-        public int contentHeight;
-
-        @Override
-        public void setSize(int width, int height) {
-            contentWidth = width;
-            contentHeight = height;
-            mWidth = width + 2 * BORDER_SIZE;
-            mHeight = height + 2 * BORDER_SIZE;
-            mTextureWidth = TILE_SIZE;
-            mTextureHeight = TILE_SIZE;
-        }
-
-        @Override
-        protected Bitmap onGetBitmap() {
-            int x = BORDER_SIZE - offsetX;
-            int y = BORDER_SIZE - offsetY;
-            int r = bitmap.getWidth() + x;
-            int b = bitmap.getHeight() + y;
-            sCanvas.drawBitmap(bitmap, x, y, sBitmapPaint);
-            bitmap = null;
-
-            // draw borders if need
-            if (x > 0) sCanvas.drawLine(x - 1, 0, x - 1, TILE_SIZE, sPaint);
-            if (y > 0) sCanvas.drawLine(0, y - 1, TILE_SIZE, y - 1, sPaint);
-            if (r < CONTENT_SIZE) sCanvas.drawLine(r, 0, r, TILE_SIZE, sPaint);
-            if (b < CONTENT_SIZE) sCanvas.drawLine(0, b, TILE_SIZE, b, sPaint);
-
-            return sUploadBitmap;
-        }
-
-        @Override
-        protected void onFreeBitmap(Bitmap bitmap) {
-            // do nothing
-        }
-    }
-
-    private static void freeTile(Tile tile) {
-        tile.invalidateContent();
-        tile.bitmap = null;
-        synchronized (sFreeTileLock) {
-            tile.nextFreeTile = sFreeTileHead;
-            sFreeTileHead = tile;
-        }
-    }
-
-    private static Tile obtainTile() {
-        synchronized (sFreeTileLock) {
-            Tile result = sFreeTileHead;
-            if (result == null) return new Tile();
-            sFreeTileHead = result.nextFreeTile;
-            result.nextFreeTile = null;
-            return result;
-        }
-    }
-
-    private boolean uploadNextTile(GLCanvas canvas) {
-        if (mUploadIndex == mTiles.length) return true;
-
-        synchronized (mTiles) {
-            Tile next = mTiles[mUploadIndex++];
-
-            // Make sure tile has not already been recycled by the time
-            // this is called (race condition in onGLIdle)
-            if (next.bitmap != null) {
-                boolean hasBeenLoad = next.isLoaded();
-                next.updateContent(canvas);
-
-                // It will take some time for a texture to be drawn for the first
-                // time. When scrolling, we need to draw several tiles on the screen
-                // at the same time. It may cause a UI jank even these textures has
-                // been uploaded.
-                if (!hasBeenLoad) next.draw(canvas, 0, 0);
-            }
-        }
-        return mUploadIndex == mTiles.length;
-    }
-
-    public TiledTexture(Bitmap bitmap) {
-        mWidth = bitmap.getWidth();
-        mHeight = bitmap.getHeight();
-        ArrayList<Tile> list = new ArrayList<Tile>();
-
-        for (int x = 0, w = mWidth; x < w; x += CONTENT_SIZE) {
-            for (int y = 0, h = mHeight; y < h; y += CONTENT_SIZE) {
-                Tile tile = obtainTile();
-                tile.offsetX = x;
-                tile.offsetY = y;
-                tile.bitmap = bitmap;
-                tile.setSize(
-                        Math.min(CONTENT_SIZE, mWidth - x),
-                        Math.min(CONTENT_SIZE, mHeight - y));
-                list.add(tile);
-            }
-        }
-        mTiles = list.toArray(new Tile[list.size()]);
-    }
-
-    public boolean isReady() {
-        return mUploadIndex == mTiles.length;
-    }
-
-    // Can be called in UI thread.
-    public void recycle() {
-        synchronized (mTiles) {
-            for (int i = 0, n = mTiles.length; i < n; ++i) {
-                freeTile(mTiles[i]);
-            }
-        }
-    }
-
-    public static void freeResources() {
-        sUploadBitmap = null;
-        sCanvas = null;
-        sBitmapPaint = null;
-        sPaint = null;
-    }
-
-    public static void prepareResources() {
-        sUploadBitmap = Bitmap.createBitmap(TILE_SIZE, TILE_SIZE, Config.ARGB_8888);
-        sCanvas = new Canvas(sUploadBitmap);
-        sBitmapPaint = new Paint(Paint.FILTER_BITMAP_FLAG);
-        sBitmapPaint.setXfermode(new PorterDuffXfermode(Mode.SRC));
-        sPaint = new Paint();
-        sPaint.setXfermode(new PorterDuffXfermode(Mode.SRC));
-        sPaint.setColor(Color.TRANSPARENT);
-    }
-
-    // We want to draw the "source" on the "target".
-    // This method is to find the "output" rectangle which is
-    // the corresponding area of the "src".
-    //                                   (x,y)  target
-    // (x0,y0)  source                     +---------------+
-    //    +----------+                     |               |
-    //    | src      |                     | output        |
-    //    | +--+     |    linear map       | +----+        |
-    //    | +--+     |    ---------->      | |    |        |
-    //    |          | by (scaleX, scaleY) | +----+        |
-    //    +----------+                     |               |
-    //      Texture                        +---------------+
-    //                                          Canvas
-    private static void mapRect(RectF output,
-            RectF src, float x0, float y0, float x, float y, float scaleX,
-            float scaleY) {
-        output.set(x + (src.left - x0) * scaleX,
-                y + (src.top - y0) * scaleY,
-                x + (src.right - x0) * scaleX,
-                y + (src.bottom - y0) * scaleY);
-    }
-
-    // Draws a mixed color of this texture and a specified color onto the
-    // a rectangle. The used color is: from * (1 - ratio) + to * ratio.
-    public void drawMixed(GLCanvas canvas, int color, float ratio,
-            int x, int y, int width, int height) {
-        RectF src = mSrcRect;
-        RectF dest = mDestRect;
-        float scaleX = (float) width / mWidth;
-        float scaleY = (float) height / mHeight;
-        synchronized (mTiles) {
-            for (int i = 0, n = mTiles.length; i < n; ++i) {
-                Tile t = mTiles[i];
-                src.set(0, 0, t.contentWidth, t.contentHeight);
-                src.offset(t.offsetX, t.offsetY);
-                mapRect(dest, src, 0, 0, x, y, scaleX, scaleY);
-                src.offset(BORDER_SIZE - t.offsetX, BORDER_SIZE - t.offsetY);
-                canvas.drawMixed(t, color, ratio, mSrcRect, mDestRect);
-            }
-        }
-    }
-
-    // Draws the texture on to the specified rectangle.
-    @Override
-    public void draw(GLCanvas canvas, int x, int y, int width, int height) {
-        RectF src = mSrcRect;
-        RectF dest = mDestRect;
-        float scaleX = (float) width / mWidth;
-        float scaleY = (float) height / mHeight;
-        synchronized (mTiles) {
-            for (int i = 0, n = mTiles.length; i < n; ++i) {
-                Tile t = mTiles[i];
-                src.set(0, 0, t.contentWidth, t.contentHeight);
-                src.offset(t.offsetX, t.offsetY);
-                mapRect(dest, src, 0, 0, x, y, scaleX, scaleY);
-                src.offset(BORDER_SIZE - t.offsetX, BORDER_SIZE - t.offsetY);
-                canvas.drawTexture(t, mSrcRect, mDestRect);
-            }
-        }
-    }
-
-    // Draws a sub region of this texture on to the specified rectangle.
-    public void draw(GLCanvas canvas, RectF source, RectF target) {
-        RectF src = mSrcRect;
-        RectF dest = mDestRect;
-        float x0 = source.left;
-        float y0 = source.top;
-        float x = target.left;
-        float y = target.top;
-        float scaleX = target.width() / source.width();
-        float scaleY = target.height() / source.height();
-
-        synchronized (mTiles) {
-            for (int i = 0, n = mTiles.length; i < n; ++i) {
-                Tile t = mTiles[i];
-                src.set(0, 0, t.contentWidth, t.contentHeight);
-                src.offset(t.offsetX, t.offsetY);
-                if (!src.intersect(source)) continue;
-                mapRect(dest, src, x0, y0, x, y, scaleX, scaleY);
-                src.offset(BORDER_SIZE - t.offsetX, BORDER_SIZE - t.offsetY);
-                canvas.drawTexture(t, src, dest);
-            }
-        }
-    }
-
-    @Override
-    public int getWidth() {
-        return mWidth;
-    }
-
-    @Override
-    public int getHeight() {
-        return mHeight;
-    }
-
-    @Override
-    public void draw(GLCanvas canvas, int x, int y) {
-        draw(canvas, x, y, mWidth, mHeight);
-    }
-
-    @Override
-    public boolean isOpaque() {
-        return false;
-    }
-}
diff --git a/src/com/android/gallery3d/glrenderer/UploadedTexture.java b/src/com/android/gallery3d/glrenderer/UploadedTexture.java
deleted file mode 100644
index f41a979..0000000
--- a/src/com/android/gallery3d/glrenderer/UploadedTexture.java
+++ /dev/null
@@ -1,298 +0,0 @@
-/*
- * Copyright (C) 2010 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.gallery3d.glrenderer;
-
-import android.graphics.Bitmap;
-import android.graphics.Bitmap.Config;
-import android.opengl.GLUtils;
-
-import junit.framework.Assert;
-
-import java.util.HashMap;
-
-import javax.microedition.khronos.opengles.GL11;
-
-// UploadedTextures use a Bitmap for the content of the texture.
-//
-// Subclasses should implement onGetBitmap() to provide the Bitmap and
-// implement onFreeBitmap(mBitmap) which will be called when the Bitmap
-// is not needed anymore.
-//
-// isContentValid() is meaningful only when the isLoaded() returns true.
-// It means whether the content needs to be updated.
-//
-// The user of this class should call recycle() when the texture is not
-// needed anymore.
-//
-// By default an UploadedTexture is opaque (so it can be drawn faster without
-// blending). The user or subclass can override it using setOpaque().
-public abstract class UploadedTexture extends BasicTexture {
-
-    // To prevent keeping allocation the borders, we store those used borders here.
-    // Since the length will be power of two, it won't use too much memory.
-    private static HashMap<BorderKey, Bitmap> sBorderLines =
-            new HashMap<BorderKey, Bitmap>();
-    private static BorderKey sBorderKey = new BorderKey();
-
-    @SuppressWarnings("unused")
-    private static final String TAG = "Texture";
-    private boolean mContentValid = true;
-
-    // indicate this textures is being uploaded in background
-    private boolean mIsUploading = false;
-    private boolean mOpaque = true;
-    private boolean mThrottled = false;
-    private static int sUploadedCount;
-    private static final int UPLOAD_LIMIT = 100;
-
-    protected Bitmap mBitmap;
-    private int mBorder;
-
-    protected UploadedTexture() {
-        this(false);
-    }
-
-    protected UploadedTexture(boolean hasBorder) {
-        super(null, 0, STATE_UNLOADED);
-        if (hasBorder) {
-            setBorder(true);
-            mBorder = 1;
-        }
-    }
-
-    protected void setIsUploading(boolean uploading) {
-        mIsUploading = uploading;
-    }
-
-    public boolean isUploading() {
-        return mIsUploading;
-    }
-
-    private static class BorderKey implements Cloneable {
-        public boolean vertical;
-        public Config config;
-        public int length;
-
-        @Override
-        public int hashCode() {
-            int x = config.hashCode() ^ length;
-            return vertical ? x : -x;
-        }
-
-        @Override
-        public boolean equals(Object object) {
-            if (!(object instanceof BorderKey)) return false;
-            BorderKey o = (BorderKey) object;
-            return vertical == o.vertical
-                    && config == o.config && length == o.length;
-        }
-
-        @Override
-        public BorderKey clone() {
-            try {
-                return (BorderKey) super.clone();
-            } catch (CloneNotSupportedException e) {
-                throw new AssertionError(e);
-            }
-        }
-    }
-
-    protected void setThrottled(boolean throttled) {
-        mThrottled = throttled;
-    }
-
-    private static Bitmap getBorderLine(
-            boolean vertical, Config config, int length) {
-        BorderKey key = sBorderKey;
-        key.vertical = vertical;
-        key.config = config;
-        key.length = length;
-        Bitmap bitmap = sBorderLines.get(key);
-        if (bitmap == null) {
-            bitmap = vertical
-                    ? Bitmap.createBitmap(1, length, config)
-                    : Bitmap.createBitmap(length, 1, config);
-            sBorderLines.put(key.clone(), bitmap);
-        }
-        return bitmap;
-    }
-
-    private Bitmap getBitmap() {
-        if (mBitmap == null) {
-            mBitmap = onGetBitmap();
-            int w = mBitmap.getWidth() + mBorder * 2;
-            int h = mBitmap.getHeight() + mBorder * 2;
-            if (mWidth == UNSPECIFIED) {
-                setSize(w, h);
-            }
-        }
-        return mBitmap;
-    }
-
-    private void freeBitmap() {
-        Assert.assertTrue(mBitmap != null);
-        onFreeBitmap(mBitmap);
-        mBitmap = null;
-    }
-
-    @Override
-    public int getWidth() {
-        if (mWidth == UNSPECIFIED) getBitmap();
-        return mWidth;
-    }
-
-    @Override
-    public int getHeight() {
-        if (mWidth == UNSPECIFIED) getBitmap();
-        return mHeight;
-    }
-
-    protected abstract Bitmap onGetBitmap();
-
-    protected abstract void onFreeBitmap(Bitmap bitmap);
-
-    protected void invalidateContent() {
-        if (mBitmap != null) freeBitmap();
-        mContentValid = false;
-        mWidth = UNSPECIFIED;
-        mHeight = UNSPECIFIED;
-    }
-
-    /**
-     * Whether the content on GPU is valid.
-     */
-    public boolean isContentValid() {
-        return isLoaded() && mContentValid;
-    }
-
-    /**
-     * Updates the content on GPU's memory.
-     * @param canvas
-     */
-    public void updateContent(GLCanvas canvas) {
-        if (!isLoaded()) {
-            if (mThrottled && ++sUploadedCount > UPLOAD_LIMIT) {
-                return;
-            }
-            uploadToCanvas(canvas);
-        } else if (!mContentValid) {
-            Bitmap bitmap = getBitmap();
-            int format = GLUtils.getInternalFormat(bitmap);
-            int type = GLUtils.getType(bitmap);
-            canvas.texSubImage2D(this, mBorder, mBorder, bitmap, format, type);
-            freeBitmap();
-            mContentValid = true;
-        }
-    }
-
-    public static void resetUploadLimit() {
-        sUploadedCount = 0;
-    }
-
-    public static boolean uploadLimitReached() {
-        return sUploadedCount > UPLOAD_LIMIT;
-    }
-
-    private void uploadToCanvas(GLCanvas canvas) {
-
-        Bitmap bitmap = getBitmap();
-        if (bitmap != null) {
-            try {
-                int bWidth = bitmap.getWidth();
-                int bHeight = bitmap.getHeight();
-                int width = bWidth + mBorder * 2;
-                int height = bHeight + mBorder * 2;
-                int texWidth = getTextureWidth();
-                int texHeight = getTextureHeight();
-
-                Assert.assertTrue(bWidth <= texWidth && bHeight <= texHeight);
-
-                // Upload the bitmap to a new texture.
-                mId = canvas.getGLId().generateTexture();
-                canvas.setTextureParameters(this);
-
-                if (bWidth == texWidth && bHeight == texHeight) {
-                    canvas.initializeTexture(this, bitmap);
-                } else {
-                    int format = GLUtils.getInternalFormat(bitmap);
-                    int type = GLUtils.getType(bitmap);
-                    Config config = bitmap.getConfig();
-
-                    canvas.initializeTextureSize(this, format, type);
-                    canvas.texSubImage2D(this, mBorder, mBorder, bitmap, format, type);
-
-                    if (mBorder > 0) {
-                        // Left border
-                        Bitmap line = getBorderLine(true, config, texHeight);
-                        canvas.texSubImage2D(this, 0, 0, line, format, type);
-
-                        // Top border
-                        line = getBorderLine(false, config, texWidth);
-                        canvas.texSubImage2D(this, 0, 0, line, format, type);
-                    }
-
-                    // Right border
-                    if (mBorder + bWidth < texWidth) {
-                        Bitmap line = getBorderLine(true, config, texHeight);
-                        canvas.texSubImage2D(this, mBorder + bWidth, 0, line, format, type);
-                    }
-
-                    // Bottom border
-                    if (mBorder + bHeight < texHeight) {
-                        Bitmap line = getBorderLine(false, config, texWidth);
-                        canvas.texSubImage2D(this, 0, mBorder + bHeight, line, format, type);
-                    }
-                }
-            } finally {
-                freeBitmap();
-            }
-            // Update texture state.
-            setAssociatedCanvas(canvas);
-            mState = STATE_LOADED;
-            mContentValid = true;
-        } else {
-            mState = STATE_ERROR;
-            throw new RuntimeException("Texture load fail, no bitmap");
-        }
-    }
-
-    @Override
-    protected boolean onBind(GLCanvas canvas) {
-        updateContent(canvas);
-        return isContentValid();
-    }
-
-    @Override
-    protected int getTarget() {
-        return GL11.GL_TEXTURE_2D;
-    }
-
-    public void setOpaque(boolean isOpaque) {
-        mOpaque = isOpaque;
-    }
-
-    @Override
-    public boolean isOpaque() {
-        return mOpaque;
-    }
-
-    @Override
-    public void recycle() {
-        super.recycle();
-        if (mBitmap != null) freeBitmap();
-    }
-}
diff --git a/src/com/android/gallery3d/ingest/ImportTask.java b/src/com/android/gallery3d/ingest/ImportTask.java
deleted file mode 100644
index 7d2d641..0000000
--- a/src/com/android/gallery3d/ingest/ImportTask.java
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- * Copyright (C) 2013 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.gallery3d.ingest;
-
-import android.content.Context;
-import android.mtp.MtpDevice;
-import android.mtp.MtpObjectInfo;
-import android.os.Environment;
-import android.os.PowerManager;
-
-import com.android.gallery3d.util.GalleryUtils;
-
-import java.io.File;
-import java.util.Collection;
-import java.util.LinkedList;
-import java.util.List;
-
-public class ImportTask implements Runnable {
-
-    public interface Listener {
-        void onImportProgress(int visitedCount, int totalCount, String pathIfSuccessful);
-
-        void onImportFinish(Collection<MtpObjectInfo> objectsNotImported, int visitedCount);
-    }
-
-    static private final String WAKELOCK_LABEL = "MTP Import Task";
-
-    private Listener mListener;
-    private String mDestAlbumName;
-    private Collection<MtpObjectInfo> mObjectsToImport;
-    private MtpDevice mDevice;
-    private PowerManager.WakeLock mWakeLock;
-
-    public ImportTask(MtpDevice device, Collection<MtpObjectInfo> objectsToImport,
-            String destAlbumName, Context context) {
-        mDestAlbumName = destAlbumName;
-        mObjectsToImport = objectsToImport;
-        mDevice = device;
-        PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
-        mWakeLock = pm.newWakeLock(PowerManager.SCREEN_DIM_WAKE_LOCK, WAKELOCK_LABEL);
-    }
-
-    public void setListener(Listener listener) {
-        mListener = listener;
-    }
-
-    @Override
-    public void run() {
-        mWakeLock.acquire();
-        try {
-            List<MtpObjectInfo> objectsNotImported = new LinkedList<MtpObjectInfo>();
-            int visited = 0;
-            int total = mObjectsToImport.size();
-            mListener.onImportProgress(visited, total, null);
-            File dest = new File(Environment.getExternalStorageDirectory(), mDestAlbumName);
-            dest.mkdirs();
-            for (MtpObjectInfo object : mObjectsToImport) {
-                visited++;
-                String importedPath = null;
-                if (GalleryUtils.hasSpaceForSize(object.getCompressedSize())) {
-                    importedPath = new File(dest, object.getName()).getAbsolutePath();
-                    if (!mDevice.importFile(object.getObjectHandle(), importedPath)) {
-                        importedPath = null;
-                    }
-                }
-                if (importedPath == null) {
-                    objectsNotImported.add(object);
-                }
-                if (mListener != null) {
-                    mListener.onImportProgress(visited, total, importedPath);
-                }
-            }
-            if (mListener != null) {
-                mListener.onImportFinish(objectsNotImported, visited);
-            }
-        } finally {
-            mListener = null;
-            mWakeLock.release();
-        }
-    }
-}
diff --git a/src/com/android/gallery3d/ingest/IngestActivity.java b/src/com/android/gallery3d/ingest/IngestActivity.java
deleted file mode 100644
index 687e9fd..0000000
--- a/src/com/android/gallery3d/ingest/IngestActivity.java
+++ /dev/null
@@ -1,570 +0,0 @@
-/*
- * Copyright (C) 2013 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.gallery3d.ingest;
-
-import android.app.Activity;
-import android.app.ProgressDialog;
-import android.content.ComponentName;
-import android.content.Context;
-import android.content.Intent;
-import android.content.ServiceConnection;
-import android.content.res.Configuration;
-import android.database.DataSetObserver;
-import android.mtp.MtpObjectInfo;
-import android.os.Bundle;
-import android.os.Handler;
-import android.os.IBinder;
-import android.os.Message;
-import android.support.v4.view.ViewPager;
-import android.util.SparseBooleanArray;
-import android.view.ActionMode;
-import android.view.Menu;
-import android.view.MenuInflater;
-import android.view.MenuItem;
-import android.view.View;
-import android.widget.AbsListView.MultiChoiceModeListener;
-import android.widget.AdapterView;
-import android.widget.AdapterView.OnItemClickListener;
-import android.widget.TextView;
-
-import com.android.gallery3d.R;
-import com.android.gallery3d.ingest.adapter.CheckBroker;
-import com.android.gallery3d.ingest.adapter.MtpAdapter;
-import com.android.gallery3d.ingest.adapter.MtpPagerAdapter;
-import com.android.gallery3d.ingest.data.MtpBitmapFetch;
-import com.android.gallery3d.ingest.ui.DateTileView;
-import com.android.gallery3d.ingest.ui.IngestGridView;
-import com.android.gallery3d.ingest.ui.IngestGridView.OnClearChoicesListener;
-
-import java.lang.ref.WeakReference;
-import java.util.Collection;
-
-public class IngestActivity extends Activity implements
-        MtpDeviceIndex.ProgressListener, ImportTask.Listener {
-
-    private IngestService mHelperService;
-    private boolean mActive = false;
-    private IngestGridView mGridView;
-    private MtpAdapter mAdapter;
-    private Handler mHandler;
-    private ProgressDialog mProgressDialog;
-    private ActionMode mActiveActionMode;
-
-    private View mWarningView;
-    private TextView mWarningText;
-    private int mLastCheckedPosition = 0;
-
-    private ViewPager mFullscreenPager;
-    private MtpPagerAdapter mPagerAdapter;
-    private boolean mFullscreenPagerVisible = false;
-
-    private MenuItem mMenuSwitcherItem;
-    private MenuItem mActionMenuSwitcherItem;
-
-    // The MTP framework components don't give us fine-grained file copy
-    // progress updates, so for large photos and videos, we will be stuck
-    // with a dialog not updating for a long time. To give the user feedback,
-    // we switch to the animated indeterminate progress bar after the timeout
-    // specified by INDETERMINATE_SWITCH_TIMEOUT_MS. On the next update from
-    // the framework, we switch back to the normal progress bar.
-    private static final int INDETERMINATE_SWITCH_TIMEOUT_MS = 3000;
-
-    @Override
-    protected void onCreate(Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-        doBindHelperService();
-
-        setContentView(R.layout.ingest_activity_item_list);
-        mGridView = (IngestGridView) findViewById(R.id.ingest_gridview);
-        mAdapter = new MtpAdapter(this);
-        mAdapter.registerDataSetObserver(mMasterObserver);
-        mGridView.setAdapter(mAdapter);
-        mGridView.setMultiChoiceModeListener(mMultiChoiceModeListener);
-        mGridView.setOnItemClickListener(mOnItemClickListener);
-        mGridView.setOnClearChoicesListener(mPositionMappingCheckBroker);
-
-        mFullscreenPager = (ViewPager) findViewById(R.id.ingest_view_pager);
-
-        mHandler = new ItemListHandler(this);
-
-        MtpBitmapFetch.configureForContext(this);
-    }
-
-    private OnItemClickListener mOnItemClickListener = new OnItemClickListener() {
-        @Override
-        public void onItemClick(AdapterView<?> adapterView, View itemView, int position, long arg3) {
-            mLastCheckedPosition = position;
-            mGridView.setItemChecked(position, !mGridView.getCheckedItemPositions().get(position));
-        }
-    };
-
-    private MultiChoiceModeListener mMultiChoiceModeListener = new MultiChoiceModeListener() {
-        private boolean mIgnoreItemCheckedStateChanges = false;
-
-        private void updateSelectedTitle(ActionMode mode) {
-            int count = mGridView.getCheckedItemCount();
-            mode.setTitle(getResources().getQuantityString(
-                    R.plurals.number_of_items_selected, count, count));
-        }
-
-        @Override
-        public void onItemCheckedStateChanged(ActionMode mode, int position, long id,
-                boolean checked) {
-            if (mIgnoreItemCheckedStateChanges) return;
-            if (mAdapter.itemAtPositionIsBucket(position)) {
-                SparseBooleanArray checkedItems = mGridView.getCheckedItemPositions();
-                mIgnoreItemCheckedStateChanges = true;
-                mGridView.setItemChecked(position, false);
-
-                // Takes advantage of the fact that SectionIndexer imposes the
-                // need to clamp to the valid range
-                int nextSectionStart = mAdapter.getPositionForSection(
-                        mAdapter.getSectionForPosition(position) + 1);
-                if (nextSectionStart == position)
-                    nextSectionStart = mAdapter.getCount();
-
-                boolean rangeValue = false; // Value we want to set all of the bucket items to
-
-                // Determine if all the items in the bucket are currently checked, so that we
-                // can uncheck them, otherwise we will check all items in the bucket.
-                for (int i = position + 1; i < nextSectionStart; i++) {
-                    if (checkedItems.get(i) == false) {
-                        rangeValue = true;
-                        break;
-                    }
-                }
-
-                // Set all items in the bucket to the desired state
-                for (int i = position + 1; i < nextSectionStart; i++) {
-                    if (checkedItems.get(i) != rangeValue)
-                        mGridView.setItemChecked(i, rangeValue);
-                }
-
-                mPositionMappingCheckBroker.onBulkCheckedChange();
-                mIgnoreItemCheckedStateChanges = false;
-            } else {
-                mPositionMappingCheckBroker.onCheckedChange(position, checked);
-            }
-            mLastCheckedPosition = position;
-            updateSelectedTitle(mode);
-        }
-
-        @Override
-        public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
-            return onOptionsItemSelected(item);
-        }
-
-        @Override
-        public boolean onCreateActionMode(ActionMode mode, Menu menu) {
-            MenuInflater inflater = mode.getMenuInflater();
-            inflater.inflate(R.menu.ingest_menu_item_list_selection, menu);
-            updateSelectedTitle(mode);
-            mActiveActionMode = mode;
-            mActionMenuSwitcherItem = menu.findItem(R.id.ingest_switch_view);
-            setSwitcherMenuState(mActionMenuSwitcherItem, mFullscreenPagerVisible);
-            return true;
-        }
-
-        @Override
-        public void onDestroyActionMode(ActionMode mode) {
-            mActiveActionMode = null;
-            mActionMenuSwitcherItem = null;
-            mHandler.sendEmptyMessage(ItemListHandler.MSG_BULK_CHECKED_CHANGE);
-        }
-
-        @Override
-        public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
-            updateSelectedTitle(mode);
-            return false;
-        }
-    };
-
-    public boolean onOptionsItemSelected(MenuItem item) {
-        switch (item.getItemId()) {
-            case R.id.import_items:
-                if (mActiveActionMode != null) {
-                    mHelperService.importSelectedItems(
-                            mGridView.getCheckedItemPositions(),
-                            mAdapter);
-                    mActiveActionMode.finish();
-                }
-                return true;
-            case R.id.ingest_switch_view:
-                setFullscreenPagerVisibility(!mFullscreenPagerVisible);
-                return true;
-            default:
-                return false;
-        }
-    }
-
-    @Override
-    public boolean onCreateOptionsMenu(Menu menu) {
-        MenuInflater inflater = getMenuInflater();
-        inflater.inflate(R.menu.ingest_menu_item_list_selection, menu);
-        mMenuSwitcherItem = menu.findItem(R.id.ingest_switch_view);
-        menu.findItem(R.id.import_items).setVisible(false);
-        setSwitcherMenuState(mMenuSwitcherItem, mFullscreenPagerVisible);
-        return true;
-    }
-
-    @Override
-    protected void onDestroy() {
-        super.onDestroy();
-        doUnbindHelperService();
-    }
-
-    @Override
-    protected void onResume() {
-        DateTileView.refreshLocale();
-        mActive = true;
-        if (mHelperService != null) mHelperService.setClientActivity(this);
-        updateWarningView();
-        super.onResume();
-    }
-
-    @Override
-    protected void onPause() {
-        if (mHelperService != null) mHelperService.setClientActivity(null);
-        mActive = false;
-        cleanupProgressDialog();
-        super.onPause();
-    }
-
-    @Override
-    public void onConfigurationChanged(Configuration newConfig) {
-        super.onConfigurationChanged(newConfig);
-        MtpBitmapFetch.configureForContext(this);
-    }
-
-    private void showWarningView(int textResId) {
-        if (mWarningView == null) {
-            mWarningView = findViewById(R.id.ingest_warning_view);
-            mWarningText =
-                    (TextView)mWarningView.findViewById(R.id.ingest_warning_view_text);
-        }
-        mWarningText.setText(textResId);
-        mWarningView.setVisibility(View.VISIBLE);
-        setFullscreenPagerVisibility(false);
-        mGridView.setVisibility(View.GONE);
-    }
-
-    private void hideWarningView() {
-        if (mWarningView != null) {
-            mWarningView.setVisibility(View.GONE);
-            setFullscreenPagerVisibility(false);
-        }
-    }
-
-    private PositionMappingCheckBroker mPositionMappingCheckBroker = new PositionMappingCheckBroker();
-
-    private class PositionMappingCheckBroker extends CheckBroker
-        implements OnClearChoicesListener {
-        private int mLastMappingPager = -1;
-        private int mLastMappingGrid = -1;
-
-        private int mapPagerToGridPosition(int position) {
-            if (position != mLastMappingPager) {
-               mLastMappingPager = position;
-               mLastMappingGrid = mAdapter.translatePositionWithoutLabels(position);
-            }
-            return mLastMappingGrid;
-        }
-
-        private int mapGridToPagerPosition(int position) {
-            if (position != mLastMappingGrid) {
-                mLastMappingGrid = position;
-                mLastMappingPager = mPagerAdapter.translatePositionWithLabels(position);
-            }
-            return mLastMappingPager;
-        }
-
-        @Override
-        public void setItemChecked(int position, boolean checked) {
-            mGridView.setItemChecked(mapPagerToGridPosition(position), checked);
-        }
-
-        @Override
-        public void onCheckedChange(int position, boolean checked) {
-            if (mPagerAdapter != null) {
-                super.onCheckedChange(mapGridToPagerPosition(position), checked);
-            }
-        }
-
-        @Override
-        public boolean isItemChecked(int position) {
-            return mGridView.getCheckedItemPositions().get(mapPagerToGridPosition(position));
-        }
-
-        @Override
-        public void onClearChoices() {
-            onBulkCheckedChange();
-        }
-    };
-
-    private DataSetObserver mMasterObserver = new DataSetObserver() {
-        @Override
-        public void onChanged() {
-            if (mPagerAdapter != null) mPagerAdapter.notifyDataSetChanged();
-        }
-
-        @Override
-        public void onInvalidated() {
-            if (mPagerAdapter != null) mPagerAdapter.notifyDataSetChanged();
-        }
-    };
-
-    private int pickFullscreenStartingPosition() {
-        int firstVisiblePosition = mGridView.getFirstVisiblePosition();
-        if (mLastCheckedPosition <= firstVisiblePosition
-                || mLastCheckedPosition > mGridView.getLastVisiblePosition()) {
-            return firstVisiblePosition;
-        } else {
-            return mLastCheckedPosition;
-        }
-    }
-
-    private void setSwitcherMenuState(MenuItem menuItem, boolean inFullscreenMode) {
-        if (menuItem == null) return;
-        if (!inFullscreenMode) {
-            menuItem.setIcon(android.R.drawable.ic_menu_zoom);
-            menuItem.setTitle(R.string.switch_photo_fullscreen);
-        } else {
-            menuItem.setIcon(android.R.drawable.ic_dialog_dialer);
-            menuItem.setTitle(R.string.switch_photo_grid);
-        }
-    }
-
-    private void setFullscreenPagerVisibility(boolean visible) {
-        mFullscreenPagerVisible = visible;
-        if (visible) {
-            if (mPagerAdapter == null) {
-                mPagerAdapter = new MtpPagerAdapter(this, mPositionMappingCheckBroker);
-                mPagerAdapter.setMtpDeviceIndex(mAdapter.getMtpDeviceIndex());
-            }
-            mFullscreenPager.setAdapter(mPagerAdapter);
-            mFullscreenPager.setCurrentItem(mPagerAdapter.translatePositionWithLabels(
-                    pickFullscreenStartingPosition()), false);
-        } else if (mPagerAdapter != null) {
-            mGridView.setSelection(mAdapter.translatePositionWithoutLabels(
-                    mFullscreenPager.getCurrentItem()));
-            mFullscreenPager.setAdapter(null);
-        }
-        mGridView.setVisibility(visible ? View.INVISIBLE : View.VISIBLE);
-        mFullscreenPager.setVisibility(visible ? View.VISIBLE : View.INVISIBLE);
-        if (mActionMenuSwitcherItem != null) {
-            setSwitcherMenuState(mActionMenuSwitcherItem, visible);
-        }
-        setSwitcherMenuState(mMenuSwitcherItem, visible);
-    }
-
-    private void updateWarningView() {
-        if (!mAdapter.deviceConnected()) {
-            showWarningView(R.string.ingest_no_device);
-        } else if (mAdapter.indexReady() && mAdapter.getCount() == 0) {
-            showWarningView(R.string.ingest_empty_device);
-        } else {
-            hideWarningView();
-        }
-    }
-
-    private void UiThreadNotifyIndexChanged() {
-        mAdapter.notifyDataSetChanged();
-        if (mActiveActionMode != null) {
-            mActiveActionMode.finish();
-            mActiveActionMode = null;
-        }
-        updateWarningView();
-    }
-
-    protected void notifyIndexChanged() {
-        mHandler.sendEmptyMessage(ItemListHandler.MSG_NOTIFY_CHANGED);
-    }
-
-    private static class ProgressState {
-        String message;
-        String title;
-        int current;
-        int max;
-
-        public void reset() {
-            title = null;
-            message = null;
-            current = 0;
-            max = 0;
-        }
-    }
-
-    private ProgressState mProgressState = new ProgressState();
-
-    @Override
-    public void onObjectIndexed(MtpObjectInfo object, int numVisited) {
-        // Not guaranteed to be called on the UI thread
-        mProgressState.reset();
-        mProgressState.max = 0;
-        mProgressState.message = getResources().getQuantityString(
-                R.plurals.ingest_number_of_items_scanned, numVisited, numVisited);
-        mHandler.sendEmptyMessage(ItemListHandler.MSG_PROGRESS_UPDATE);
-    }
-
-    @Override
-    public void onSorting() {
-        // Not guaranteed to be called on the UI thread
-        mProgressState.reset();
-        mProgressState.max = 0;
-        mProgressState.message = getResources().getString(R.string.ingest_sorting);
-        mHandler.sendEmptyMessage(ItemListHandler.MSG_PROGRESS_UPDATE);
-    }
-
-    @Override
-    public void onIndexFinish() {
-        // Not guaranteed to be called on the UI thread
-        mHandler.sendEmptyMessage(ItemListHandler.MSG_PROGRESS_HIDE);
-        mHandler.sendEmptyMessage(ItemListHandler.MSG_NOTIFY_CHANGED);
-    }
-
-    @Override
-    public void onImportProgress(final int visitedCount, final int totalCount,
-            String pathIfSuccessful) {
-        // Not guaranteed to be called on the UI thread
-        mProgressState.reset();
-        mProgressState.max = totalCount;
-        mProgressState.current = visitedCount;
-        mProgressState.title = getResources().getString(R.string.ingest_importing);
-        mHandler.sendEmptyMessage(ItemListHandler.MSG_PROGRESS_UPDATE);
-        mHandler.removeMessages(ItemListHandler.MSG_PROGRESS_INDETERMINATE);
-        mHandler.sendEmptyMessageDelayed(ItemListHandler.MSG_PROGRESS_INDETERMINATE,
-                INDETERMINATE_SWITCH_TIMEOUT_MS);
-    }
-
-    @Override
-    public void onImportFinish(Collection<MtpObjectInfo> objectsNotImported,
-            int numVisited) {
-        // Not guaranteed to be called on the UI thread
-        mHandler.sendEmptyMessage(ItemListHandler.MSG_PROGRESS_HIDE);
-        mHandler.removeMessages(ItemListHandler.MSG_PROGRESS_INDETERMINATE);
-        // TODO: maybe show an extra dialog listing the ones that failed
-        // importing, if any?
-    }
-
-    private ProgressDialog getProgressDialog() {
-        if (mProgressDialog == null || !mProgressDialog.isShowing()) {
-            mProgressDialog = new ProgressDialog(this);
-            mProgressDialog.setCancelable(false);
-        }
-        return mProgressDialog;
-    }
-
-    private void updateProgressDialog() {
-        ProgressDialog dialog = getProgressDialog();
-        boolean indeterminate = (mProgressState.max == 0);
-        dialog.setIndeterminate(indeterminate);
-        dialog.setProgressStyle(indeterminate ? ProgressDialog.STYLE_SPINNER
-                : ProgressDialog.STYLE_HORIZONTAL);
-        if (mProgressState.title != null) {
-            dialog.setTitle(mProgressState.title);
-        }
-        if (mProgressState.message != null) {
-            dialog.setMessage(mProgressState.message);
-        }
-        if (!indeterminate) {
-            dialog.setProgress(mProgressState.current);
-            dialog.setMax(mProgressState.max);
-        }
-        if (!dialog.isShowing()) {
-            dialog.show();
-        }
-    }
-
-    private void makeProgressDialogIndeterminate() {
-        ProgressDialog dialog = getProgressDialog();
-        dialog.setIndeterminate(true);
-    }
-
-    private void cleanupProgressDialog() {
-        if (mProgressDialog != null) {
-            mProgressDialog.hide();
-            mProgressDialog = null;
-        }
-    }
-
-    // This is static and uses a WeakReference in order to avoid leaking the Activity
-    private static class ItemListHandler extends Handler {
-        public static final int MSG_PROGRESS_UPDATE = 0;
-        public static final int MSG_PROGRESS_HIDE = 1;
-        public static final int MSG_NOTIFY_CHANGED = 2;
-        public static final int MSG_BULK_CHECKED_CHANGE = 3;
-        public static final int MSG_PROGRESS_INDETERMINATE = 4;
-
-        WeakReference<IngestActivity> mParentReference;
-
-        public ItemListHandler(IngestActivity parent) {
-            super();
-            mParentReference = new WeakReference<IngestActivity>(parent);
-        }
-
-        public void handleMessage(Message message) {
-            IngestActivity parent = mParentReference.get();
-            if (parent == null || !parent.mActive)
-                return;
-            switch (message.what) {
-                case MSG_PROGRESS_HIDE:
-                    parent.cleanupProgressDialog();
-                    break;
-                case MSG_PROGRESS_UPDATE:
-                    parent.updateProgressDialog();
-                    break;
-                case MSG_NOTIFY_CHANGED:
-                    parent.UiThreadNotifyIndexChanged();
-                    break;
-                case MSG_BULK_CHECKED_CHANGE:
-                    parent.mPositionMappingCheckBroker.onBulkCheckedChange();
-                    break;
-                case MSG_PROGRESS_INDETERMINATE:
-                    parent.makeProgressDialogIndeterminate();
-                    break;
-                default:
-                    break;
-            }
-        }
-    }
-
-    private ServiceConnection mHelperServiceConnection = new ServiceConnection() {
-        public void onServiceConnected(ComponentName className, IBinder service) {
-            mHelperService = ((IngestService.LocalBinder) service).getService();
-            mHelperService.setClientActivity(IngestActivity.this);
-            MtpDeviceIndex index = mHelperService.getIndex();
-            mAdapter.setMtpDeviceIndex(index);
-            if (mPagerAdapter != null) mPagerAdapter.setMtpDeviceIndex(index);
-        }
-
-        public void onServiceDisconnected(ComponentName className) {
-            mHelperService = null;
-        }
-    };
-
-    private void doBindHelperService() {
-        bindService(new Intent(getApplicationContext(), IngestService.class),
-                mHelperServiceConnection, Context.BIND_AUTO_CREATE);
-    }
-
-    private void doUnbindHelperService() {
-        if (mHelperService != null) {
-            mHelperService.setClientActivity(null);
-            unbindService(mHelperServiceConnection);
-        }
-    }
-}
diff --git a/src/com/android/gallery3d/ingest/IngestService.java b/src/com/android/gallery3d/ingest/IngestService.java
deleted file mode 100644
index 0ce3ab6..0000000
--- a/src/com/android/gallery3d/ingest/IngestService.java
+++ /dev/null
@@ -1,320 +0,0 @@
-/*
- * Copyright (C) 2013 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.gallery3d.ingest;
-
-import android.app.NotificationManager;
-import android.app.PendingIntent;
-import android.app.Service;
-import android.content.Context;
-import android.content.Intent;
-import android.media.MediaScannerConnection;
-import android.media.MediaScannerConnection.MediaScannerConnectionClient;
-import android.mtp.MtpDevice;
-import android.mtp.MtpDeviceInfo;
-import android.mtp.MtpObjectInfo;
-import android.net.Uri;
-import android.os.Binder;
-import android.os.IBinder;
-import android.os.SystemClock;
-import android.support.v4.app.NotificationCompat;
-import android.util.SparseBooleanArray;
-import android.widget.Adapter;
-
-import com.android.gallery3d.R;
-import com.android.gallery3d.app.NotificationIds;
-import com.android.gallery3d.data.MtpClient;
-import com.android.gallery3d.util.BucketNames;
-import com.android.gallery3d.util.UsageStatistics;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.List;
-
-public class IngestService extends Service implements ImportTask.Listener,
-        MtpDeviceIndex.ProgressListener, MtpClient.Listener {
-
-    public class LocalBinder extends Binder {
-        IngestService getService() {
-            return IngestService.this;
-        }
-    }
-
-    private static final int PROGRESS_UPDATE_INTERVAL_MS = 180;
-
-    private static MtpClient sClient;
-
-    private final IBinder mBinder = new LocalBinder();
-    private ScannerClient mScannerClient;
-    private MtpDevice mDevice;
-    private String mDevicePrettyName;
-    private MtpDeviceIndex mIndex;
-    private IngestActivity mClientActivity;
-    private boolean mRedeliverImportFinish = false;
-    private int mRedeliverImportFinishCount = 0;
-    private Collection<MtpObjectInfo> mRedeliverObjectsNotImported;
-    private boolean mRedeliverNotifyIndexChanged = false;
-    private boolean mRedeliverIndexFinish = false;
-    private NotificationManager mNotificationManager;
-    private NotificationCompat.Builder mNotificationBuilder;
-    private long mLastProgressIndexTime = 0;
-    private boolean mNeedRelaunchNotification = false;
-
-    @Override
-    public void onCreate() {
-        super.onCreate();
-        mScannerClient = new ScannerClient(this);
-        mNotificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
-        mNotificationBuilder = new NotificationCompat.Builder(this);
-        mNotificationBuilder.setSmallIcon(android.R.drawable.stat_notify_sync) // TODO drawable
-                .setContentIntent(PendingIntent.getActivity(this, 0, new Intent(this, IngestActivity.class), 0));
-        mIndex = MtpDeviceIndex.getInstance();
-        mIndex.setProgressListener(this);
-
-        if (sClient == null) {
-            sClient = new MtpClient(getApplicationContext());
-        }
-        List<MtpDevice> devices = sClient.getDeviceList();
-        if (devices.size() > 0) {
-            setDevice(devices.get(0));
-        }
-        sClient.addListener(this);
-    }
-
-    @Override
-    public void onDestroy() {
-        sClient.removeListener(this);
-        mIndex.unsetProgressListener(this);
-        super.onDestroy();
-    }
-
-    @Override
-    public IBinder onBind(Intent intent) {
-        return mBinder;
-    }
-
-    private void setDevice(MtpDevice device) {
-        if (mDevice == device) return;
-        mRedeliverImportFinish = false;
-        mRedeliverObjectsNotImported = null;
-        mRedeliverNotifyIndexChanged = false;
-        mRedeliverIndexFinish = false;
-        mDevice = device;
-        mIndex.setDevice(mDevice);
-        if (mDevice != null) {
-            MtpDeviceInfo deviceInfo = mDevice.getDeviceInfo();
-            if (deviceInfo == null) {
-                setDevice(null);
-                return;
-            } else {
-                mDevicePrettyName = deviceInfo.getModel();
-                mNotificationBuilder.setContentTitle(mDevicePrettyName);
-                new Thread(mIndex.getIndexRunnable()).start();
-            }
-        } else {
-            mDevicePrettyName = null;
-        }
-        if (mClientActivity != null) {
-            mClientActivity.notifyIndexChanged();
-        } else {
-            mRedeliverNotifyIndexChanged = true;
-        }
-    }
-
-    protected MtpDeviceIndex getIndex() {
-        return mIndex;
-    }
-
-    protected void setClientActivity(IngestActivity activity) {
-        if (mClientActivity == activity) return;
-        mClientActivity = activity;
-        if (mClientActivity == null) {
-            if (mNeedRelaunchNotification) {
-                mNotificationBuilder.setProgress(0, 0, false)
-                    .setContentText(getResources().getText(R.string.ingest_scanning_done));
-                mNotificationManager.notify(NotificationIds.INGEST_NOTIFICATION_SCANNING,
-                    mNotificationBuilder.build());
-            }
-            return;
-        }
-        mNotificationManager.cancel(NotificationIds.INGEST_NOTIFICATION_IMPORTING);
-        mNotificationManager.cancel(NotificationIds.INGEST_NOTIFICATION_SCANNING);
-        if (mRedeliverImportFinish) {
-            mClientActivity.onImportFinish(mRedeliverObjectsNotImported,
-                    mRedeliverImportFinishCount);
-            mRedeliverImportFinish = false;
-            mRedeliverObjectsNotImported = null;
-        }
-        if (mRedeliverNotifyIndexChanged) {
-            mClientActivity.notifyIndexChanged();
-            mRedeliverNotifyIndexChanged = false;
-        }
-        if (mRedeliverIndexFinish) {
-            mClientActivity.onIndexFinish();
-            mRedeliverIndexFinish = false;
-        }
-    }
-
-    protected void importSelectedItems(SparseBooleanArray selected, Adapter adapter) {
-        List<MtpObjectInfo> importHandles = new ArrayList<MtpObjectInfo>();
-        for (int i = 0; i < selected.size(); i++) {
-            if (selected.valueAt(i)) {
-                Object item = adapter.getItem(selected.keyAt(i));
-                if (item instanceof MtpObjectInfo) {
-                    importHandles.add(((MtpObjectInfo) item));
-                }
-            }
-        }
-        ImportTask task = new ImportTask(mDevice, importHandles, BucketNames.IMPORTED, this);
-        task.setListener(this);
-        mNotificationBuilder.setProgress(0, 0, true)
-            .setContentText(getResources().getText(R.string.ingest_importing));
-        startForeground(NotificationIds.INGEST_NOTIFICATION_IMPORTING,
-                    mNotificationBuilder.build());
-        new Thread(task).start();
-    }
-
-    @Override
-    public void deviceAdded(MtpDevice device) {
-        if (mDevice == null) {
-            setDevice(device);
-            UsageStatistics.onEvent(UsageStatistics.COMPONENT_IMPORTER,
-                    "DeviceConnected", null);
-        }
-    }
-
-    @Override
-    public void deviceRemoved(MtpDevice device) {
-        if (device == mDevice) {
-            setDevice(null);
-            mNeedRelaunchNotification = false;
-            mNotificationManager.cancel(NotificationIds.INGEST_NOTIFICATION_SCANNING);
-        }
-    }
-
-    @Override
-    public void onImportProgress(int visitedCount, int totalCount,
-            String pathIfSuccessful) {
-        if (pathIfSuccessful != null) {
-            mScannerClient.scanPath(pathIfSuccessful);
-        }
-        mNeedRelaunchNotification = false;
-        if (mClientActivity != null) {
-            mClientActivity.onImportProgress(visitedCount, totalCount, pathIfSuccessful);
-        }
-        mNotificationBuilder.setProgress(totalCount, visitedCount, false)
-            .setContentText(getResources().getText(R.string.ingest_importing));
-        mNotificationManager.notify(NotificationIds.INGEST_NOTIFICATION_IMPORTING,
-                mNotificationBuilder.build());
-    }
-
-    @Override
-    public void onImportFinish(Collection<MtpObjectInfo> objectsNotImported,
-            int visitedCount) {
-        stopForeground(true);
-        mNeedRelaunchNotification = true;
-        if (mClientActivity != null) {
-            mClientActivity.onImportFinish(objectsNotImported, visitedCount);
-        } else {
-            mRedeliverImportFinish = true;
-            mRedeliverObjectsNotImported = objectsNotImported;
-            mRedeliverImportFinishCount = visitedCount;
-            mNotificationBuilder.setProgress(0, 0, false)
-                .setContentText(getResources().getText(R.string.import_complete));
-            mNotificationManager.notify(NotificationIds.INGEST_NOTIFICATION_IMPORTING,
-                    mNotificationBuilder.build());
-        }
-        UsageStatistics.onEvent(UsageStatistics.COMPONENT_IMPORTER,
-                "ImportFinished", null, visitedCount);
-    }
-
-    @Override
-    public void onObjectIndexed(MtpObjectInfo object, int numVisited) {
-        mNeedRelaunchNotification = false;
-        if (mClientActivity != null) {
-            mClientActivity.onObjectIndexed(object, numVisited);
-        } else {
-            // Throttle the updates to one every PROGRESS_UPDATE_INTERVAL_MS milliseconds
-            long currentTime = SystemClock.uptimeMillis();
-            if (currentTime > mLastProgressIndexTime + PROGRESS_UPDATE_INTERVAL_MS) {
-                mLastProgressIndexTime = currentTime;
-                mNotificationBuilder.setProgress(0, numVisited, true)
-                        .setContentText(getResources().getText(R.string.ingest_scanning));
-                mNotificationManager.notify(NotificationIds.INGEST_NOTIFICATION_SCANNING,
-                        mNotificationBuilder.build());
-            }
-        }
-    }
-
-    @Override
-    public void onSorting() {
-        if (mClientActivity != null) mClientActivity.onSorting();
-    }
-
-    @Override
-    public void onIndexFinish() {
-        mNeedRelaunchNotification = true;
-        if (mClientActivity != null) {
-            mClientActivity.onIndexFinish();
-        } else {
-            mNotificationBuilder.setProgress(0, 0, false)
-                .setContentText(getResources().getText(R.string.ingest_scanning_done));
-            mNotificationManager.notify(NotificationIds.INGEST_NOTIFICATION_SCANNING,
-                    mNotificationBuilder.build());
-            mRedeliverIndexFinish = true;
-        }
-    }
-
-    // Copied from old Gallery3d code
-    private static final class ScannerClient implements MediaScannerConnectionClient {
-        ArrayList<String> mPaths = new ArrayList<String>();
-        MediaScannerConnection mScannerConnection;
-        boolean mConnected;
-        Object mLock = new Object();
-
-        public ScannerClient(Context context) {
-            mScannerConnection = new MediaScannerConnection(context, this);
-        }
-
-        public void scanPath(String path) {
-            synchronized (mLock) {
-                if (mConnected) {
-                    mScannerConnection.scanFile(path, null);
-                } else {
-                    mPaths.add(path);
-                    mScannerConnection.connect();
-                }
-            }
-        }
-
-        @Override
-        public void onMediaScannerConnected() {
-            synchronized (mLock) {
-                mConnected = true;
-                if (!mPaths.isEmpty()) {
-                    for (String path : mPaths) {
-                        mScannerConnection.scanFile(path, null);
-                    }
-                    mPaths.clear();
-                }
-            }
-        }
-
-        @Override
-        public void onScanCompleted(String path, Uri uri) {
-        }
-    }
-}
diff --git a/src/com/android/gallery3d/ingest/MtpDeviceIndex.java b/src/com/android/gallery3d/ingest/MtpDeviceIndex.java
deleted file mode 100644
index d30f94a..0000000
--- a/src/com/android/gallery3d/ingest/MtpDeviceIndex.java
+++ /dev/null
@@ -1,596 +0,0 @@
-/*
- * Copyright (C) 2013 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.gallery3d.ingest;
-
-import android.mtp.MtpConstants;
-import android.mtp.MtpDevice;
-import android.mtp.MtpObjectInfo;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.Stack;
-
-/**
- * MTP objects in the index are organized into "buckets," or groupings.
- * At present, these buckets are based on the date an item was created.
- *
- * When the index is created, the buckets are sorted in their natural
- * order, and the items within the buckets sorted by the date they are taken.
- *
- * The index enables the access of items and bucket labels as one unified list.
- * For example, let's say we have the following data in the index:
- *    [Bucket A]: [photo 1], [photo 2]
- *    [Bucket B]: [photo 3]
- *
- * Then the items can be thought of as being organized as a 5 element list:
- *   [Bucket A], [photo 1], [photo 2], [Bucket B], [photo 3]
- *
- * The data can also be accessed in descending order, in which case the list
- * would be a bit different from simply reversing the ascending list, since the
- * bucket labels need to always be at the beginning:
- *   [Bucket B], [photo 3], [Bucket A], [photo 2], [photo 1]
- *
- * The index enables all the following operations in constant time, both for
- * ascending and descending views of the data:
- *   - get/getAscending/getDescending: get an item at a specified list position
- *   - size: get the total number of items (bucket labels and MTP objects)
- *   - getFirstPositionForBucketNumber
- *   - getBucketNumberForPosition
- *   - isFirstInBucket
- *
- * See the comments in buildLookupIndex for implementation notes.
- */
-public class MtpDeviceIndex {
-
-    public static final int FORMAT_MOV = 0x300D; // For some reason this is not in MtpConstants
-
-    public static final Set<Integer> SUPPORTED_IMAGE_FORMATS;
-    public static final Set<Integer> SUPPORTED_VIDEO_FORMATS;
-
-    static {
-        SUPPORTED_IMAGE_FORMATS = new HashSet<Integer>();
-        SUPPORTED_IMAGE_FORMATS.add(MtpConstants.FORMAT_JFIF);
-        SUPPORTED_IMAGE_FORMATS.add(MtpConstants.FORMAT_EXIF_JPEG);
-        SUPPORTED_IMAGE_FORMATS.add(MtpConstants.FORMAT_PNG);
-        SUPPORTED_IMAGE_FORMATS.add(MtpConstants.FORMAT_GIF);
-        SUPPORTED_IMAGE_FORMATS.add(MtpConstants.FORMAT_BMP);
-
-        SUPPORTED_VIDEO_FORMATS = new HashSet<Integer>();
-        SUPPORTED_VIDEO_FORMATS.add(MtpConstants.FORMAT_3GP_CONTAINER);
-        SUPPORTED_VIDEO_FORMATS.add(MtpConstants.FORMAT_AVI);
-        SUPPORTED_VIDEO_FORMATS.add(MtpConstants.FORMAT_MP4_CONTAINER);
-        SUPPORTED_VIDEO_FORMATS.add(MtpConstants.FORMAT_MPEG);
-        // TODO: add FORMAT_MOV once Media Scanner supports .mov files
-    }
-
-    @Override
-    public int hashCode() {
-        final int prime = 31;
-        int result = 1;
-        result = prime * result + ((mDevice == null) ? 0 : mDevice.getDeviceId());
-        result = prime * result + mGeneration;
-        return result;
-    }
-
-    public interface ProgressListener {
-        public void onObjectIndexed(MtpObjectInfo object, int numVisited);
-
-        public void onSorting();
-
-        public void onIndexFinish();
-    }
-
-    public enum SortOrder {
-        Ascending, Descending
-    }
-
-    private MtpDevice mDevice;
-    private int[] mUnifiedLookupIndex;
-    private MtpObjectInfo[] mMtpObjects;
-    private DateBucket[] mBuckets;
-    private int mGeneration = 0;
-
-    public enum Progress {
-        Uninitialized, Initialized, Pending, Started, Sorting, Finished
-    }
-
-    private Progress mProgress = Progress.Uninitialized;
-    private ProgressListener mProgressListener;
-
-    private static final MtpDeviceIndex sInstance = new MtpDeviceIndex();
-    private static final MtpObjectTimestampComparator sMtpObjectComparator =
-            new MtpObjectTimestampComparator();
-
-    public static MtpDeviceIndex getInstance() {
-        return sInstance;
-    }
-
-    private MtpDeviceIndex() {
-    }
-
-    synchronized public MtpDevice getDevice() {
-        return mDevice;
-    }
-
-    /**
-     * Sets the MtpDevice that should be indexed and initializes state, but does
-     * not kick off the actual indexing task, which is instead done by using
-     * {@link #getIndexRunnable()}
-     *
-     * @param device The MtpDevice that should be indexed
-     */
-    synchronized public void setDevice(MtpDevice device) {
-        if (device == mDevice) return;
-        mDevice = device;
-        resetState();
-    }
-
-    /**
-     * Provides a Runnable for the indexing task assuming the state has already
-     * been correctly initialized (by calling {@link #setDevice(MtpDevice)}) and
-     * has not already been run.
-     *
-     * @return Runnable for the main indexing task
-     */
-    synchronized public Runnable getIndexRunnable() {
-        if (mProgress != Progress.Initialized) return null;
-        mProgress = Progress.Pending;
-        return new IndexRunnable(mDevice);
-    }
-
-    synchronized public boolean indexReady() {
-        return mProgress == Progress.Finished;
-    }
-
-    synchronized public Progress getProgress() {
-        return mProgress;
-    }
-
-    /**
-     * @param listener Listener to change to
-     * @return Progress at the time the listener was added (useful for
-     *         configuring initial UI state)
-     */
-    synchronized public Progress setProgressListener(ProgressListener listener) {
-        mProgressListener = listener;
-        return mProgress;
-    }
-
-    /**
-     * Make the listener null if it matches the argument
-     *
-     * @param listener Listener to unset, if currently registered
-     */
-    synchronized public void unsetProgressListener(ProgressListener listener) {
-        if (mProgressListener == listener)
-            mProgressListener = null;
-    }
-
-    /**
-     * @return The total number of elements in the index (labels and items)
-     */
-    public int size() {
-        return mProgress == Progress.Finished ? mUnifiedLookupIndex.length : 0;
-    }
-
-    /**
-     * @param position Index of item to fetch, where 0 is the first item in the
-     *            specified order
-     * @param order
-     * @return the bucket label or MtpObjectInfo at the specified position and
-     *         order
-     */
-    public Object get(int position, SortOrder order) {
-        if (mProgress != Progress.Finished) return null;
-        if(order == SortOrder.Ascending) {
-            DateBucket bucket = mBuckets[mUnifiedLookupIndex[position]];
-            if (bucket.unifiedStartIndex == position) {
-                return bucket.bucket;
-            } else {
-                return mMtpObjects[bucket.itemsStartIndex + position - 1
-                                   - bucket.unifiedStartIndex];
-            }
-        } else {
-            int zeroIndex = mUnifiedLookupIndex.length - 1 - position;
-            DateBucket bucket = mBuckets[mUnifiedLookupIndex[zeroIndex]];
-            if (bucket.unifiedEndIndex == zeroIndex) {
-                return bucket.bucket;
-            } else {
-                return mMtpObjects[bucket.itemsStartIndex + zeroIndex
-                                   - bucket.unifiedStartIndex];
-            }
-        }
-    }
-
-    /**
-     * @param position Index of item to fetch from a view of the data that doesn't
-     *            include labels and is in the specified order
-     * @return position-th item in specified order, when not including labels
-     */
-    public MtpObjectInfo getWithoutLabels(int position, SortOrder order) {
-        if (mProgress != Progress.Finished) return null;
-        if (order == SortOrder.Ascending) {
-            return mMtpObjects[position];
-        } else {
-            return mMtpObjects[mMtpObjects.length - 1 - position];
-        }
-    }
-
-    /**
-     * Although this is O(log(number of buckets)), and thus should not be used
-     * in hotspots, even if the attached device has items for every day for
-     * a five-year timeframe, it would still only take 11 iterations at most,
-     * so shouldn't be a huge issue.
-     * @param position Index of item to map from a view of the data that doesn't
-     *            include labels and is in the specified order
-     * @param order
-     * @return position in a view of the data that does include labels
-     */
-    public int getPositionFromPositionWithoutLabels(int position, SortOrder order) {
-        if (mProgress != Progress.Finished) return -1;
-        if (order == SortOrder.Descending) {
-            position = mMtpObjects.length - 1 - position;
-        }
-        int bucketNumber = 0;
-        int iMin = 0;
-        int iMax = mBuckets.length - 1;
-        while (iMax >= iMin) {
-            int iMid = (iMax + iMin) / 2;
-            if (mBuckets[iMid].itemsStartIndex + mBuckets[iMid].numItems <= position) {
-                iMin = iMid + 1;
-            } else if (mBuckets[iMid].itemsStartIndex > position) {
-                iMax = iMid - 1;
-            } else {
-                bucketNumber = iMid;
-                break;
-            }
-        }
-        int mappedPos = mBuckets[bucketNumber].unifiedStartIndex
-                + position - mBuckets[bucketNumber].itemsStartIndex;
-        if (order == SortOrder.Descending) {
-            mappedPos = mUnifiedLookupIndex.length - 1 - mappedPos;
-        }
-        return mappedPos;
-    }
-
-    public int getPositionWithoutLabelsFromPosition(int position, SortOrder order) {
-        if (mProgress != Progress.Finished) return -1;
-        if(order == SortOrder.Ascending) {
-            DateBucket bucket = mBuckets[mUnifiedLookupIndex[position]];
-            if (bucket.unifiedStartIndex == position) position++;
-            return bucket.itemsStartIndex + position - 1 - bucket.unifiedStartIndex;
-        } else {
-            int zeroIndex = mUnifiedLookupIndex.length - 1 - position;
-            DateBucket bucket = mBuckets[mUnifiedLookupIndex[zeroIndex]];
-            if (bucket.unifiedEndIndex == zeroIndex) zeroIndex--;
-            return mMtpObjects.length - 1 - bucket.itemsStartIndex
-                    - zeroIndex + bucket.unifiedStartIndex;
-        }
-    }
-
-    /**
-     * @return The number of MTP items in the index (without labels)
-     */
-    public int sizeWithoutLabels() {
-        return mProgress == Progress.Finished ? mMtpObjects.length : 0;
-    }
-
-    public int getFirstPositionForBucketNumber(int bucketNumber, SortOrder order) {
-        if (order == SortOrder.Ascending) {
-            return mBuckets[bucketNumber].unifiedStartIndex;
-        } else {
-            return mUnifiedLookupIndex.length - mBuckets[mBuckets.length - 1 - bucketNumber].unifiedEndIndex - 1;
-        }
-    }
-
-    public int getBucketNumberForPosition(int position, SortOrder order) {
-        if (order == SortOrder.Ascending) {
-            return mUnifiedLookupIndex[position];
-        } else {
-            return mBuckets.length - 1 - mUnifiedLookupIndex[mUnifiedLookupIndex.length - 1 - position];
-        }
-    }
-
-    public boolean isFirstInBucket(int position, SortOrder order) {
-        if (order == SortOrder.Ascending) {
-            return mBuckets[mUnifiedLookupIndex[position]].unifiedStartIndex == position;
-        } else {
-            position = mUnifiedLookupIndex.length - 1 - position;
-            return mBuckets[mUnifiedLookupIndex[position]].unifiedEndIndex == position;
-        }
-    }
-
-    private Object[] mCachedReverseBuckets;
-
-    public Object[] getBuckets(SortOrder order) {
-        if (mBuckets == null) return null;
-        if (order == SortOrder.Ascending) {
-            return mBuckets;
-        } else {
-            if (mCachedReverseBuckets == null) {
-                computeReversedBuckets();
-            }
-            return mCachedReverseBuckets;
-        }
-    }
-
-    /*
-     * See the comments for buildLookupIndex for notes on the specific fields of
-     * this class.
-     */
-    private class DateBucket implements Comparable<DateBucket> {
-        SimpleDate bucket;
-        List<MtpObjectInfo> tempElementsList = new ArrayList<MtpObjectInfo>();
-        int unifiedStartIndex;
-        int unifiedEndIndex;
-        int itemsStartIndex;
-        int numItems;
-
-        public DateBucket(SimpleDate bucket) {
-            this.bucket = bucket;
-        }
-
-        public DateBucket(SimpleDate bucket, MtpObjectInfo firstElement) {
-            this(bucket);
-            tempElementsList.add(firstElement);
-        }
-
-        void sortElements(Comparator<MtpObjectInfo> comparator) {
-            Collections.sort(tempElementsList, comparator);
-        }
-
-        @Override
-        public String toString() {
-            return bucket.toString();
-        }
-
-        @Override
-        public int hashCode() {
-            return bucket.hashCode();
-        }
-
-        @Override
-        public boolean equals(Object obj) {
-            if (this == obj) return true;
-            if (obj == null) return false;
-            if (!(obj instanceof DateBucket)) return false;
-            DateBucket other = (DateBucket) obj;
-            if (bucket == null) {
-                if (other.bucket != null) return false;
-            } else if (!bucket.equals(other.bucket)) {
-                return false;
-            }
-            return true;
-        }
-
-        @Override
-        public int compareTo(DateBucket another) {
-            return this.bucket.compareTo(another.bucket);
-        }
-    }
-
-    /**
-     * Comparator to sort MtpObjectInfo objects by date created.
-     */
-    private static class MtpObjectTimestampComparator implements Comparator<MtpObjectInfo> {
-        @Override
-        public int compare(MtpObjectInfo o1, MtpObjectInfo o2) {
-            long diff = o1.getDateCreated() - o2.getDateCreated();
-            if (diff < 0) {
-                return -1;
-            } else if (diff == 0) {
-                return 0;
-            } else {
-                return 1;
-            }
-        }
-    }
-
-    private void resetState() {
-        mGeneration++;
-        mUnifiedLookupIndex = null;
-        mMtpObjects = null;
-        mBuckets = null;
-        mCachedReverseBuckets = null;
-        mProgress = (mDevice == null) ? Progress.Uninitialized : Progress.Initialized;
-    }
-
-
-    private class IndexRunnable implements Runnable {
-        private int[] mUnifiedLookupIndex;
-        private MtpObjectInfo[] mMtpObjects;
-        private DateBucket[] mBuckets;
-        private Map<SimpleDate, DateBucket> mBucketsTemp;
-        private MtpDevice mDevice;
-        private int mNumObjects = 0;
-
-        private class IndexingException extends Exception {};
-
-        public IndexRunnable(MtpDevice device) {
-            mDevice = device;
-        }
-
-        /*
-         * Implementation note: this is the way the index supports a lot of its operations in
-         * constant time and respecting the need to have bucket names always come before items
-         * in that bucket when accessing the list sequentially, both in ascending and descending
-         * orders.
-         *
-         * Let's say the data we have in the index is the following:
-         *  [Bucket A]: [photo 1], [photo 2]
-         *  [Bucket B]: [photo 3]
-         *
-         *  In this case, the lookup index array would be
-         *  [0, 0, 0, 1, 1]
-         *
-         *  Now, whether we access the list in ascending or descending order, we know which bucket
-         *  to look in (0 corresponds to A and 1 to B), and can return the bucket label as the first
-         *  item in a bucket as needed. The individual IndexBUckets have a startIndex and endIndex
-         *  that correspond to indices in this lookup index array, allowing us to calculate the
-         *  offset of the specific item we want from within a specific bucket.
-         */
-        private void buildLookupIndex() {
-            int numBuckets = mBuckets.length;
-            mUnifiedLookupIndex = new int[mNumObjects + numBuckets];
-            int currentUnifiedIndexEntry = 0;
-            int nextUnifiedEntry;
-
-            mMtpObjects = new MtpObjectInfo[mNumObjects];
-            int currentItemsEntry = 0;
-            for (int i = 0; i < numBuckets; i++) {
-                DateBucket bucket = mBuckets[i];
-                nextUnifiedEntry = currentUnifiedIndexEntry + bucket.tempElementsList.size() + 1;
-                Arrays.fill(mUnifiedLookupIndex, currentUnifiedIndexEntry, nextUnifiedEntry, i);
-                bucket.unifiedStartIndex = currentUnifiedIndexEntry;
-                bucket.unifiedEndIndex = nextUnifiedEntry - 1;
-                currentUnifiedIndexEntry = nextUnifiedEntry;
-
-                bucket.itemsStartIndex = currentItemsEntry;
-                bucket.numItems = bucket.tempElementsList.size();
-                for (int j = 0; j < bucket.numItems; j++) {
-                    mMtpObjects[currentItemsEntry] = bucket.tempElementsList.get(j);
-                    currentItemsEntry++;
-                }
-                bucket.tempElementsList = null;
-            }
-        }
-
-        private void copyResults() {
-            MtpDeviceIndex.this.mUnifiedLookupIndex = mUnifiedLookupIndex;
-            MtpDeviceIndex.this.mMtpObjects = mMtpObjects;
-            MtpDeviceIndex.this.mBuckets = mBuckets;
-            mUnifiedLookupIndex = null;
-            mMtpObjects = null;
-            mBuckets = null;
-        }
-
-        @Override
-        public void run() {
-            try {
-                indexDevice();
-            } catch (IndexingException e) {
-                synchronized (MtpDeviceIndex.this) {
-                    resetState();
-                    if (mProgressListener != null) {
-                        mProgressListener.onIndexFinish();
-                    }
-                }
-            }
-        }
-
-        private void indexDevice() throws IndexingException {
-            synchronized (MtpDeviceIndex.this) {
-                mProgress = Progress.Started;
-            }
-            mBucketsTemp = new HashMap<SimpleDate, DateBucket>();
-            for (int storageId : mDevice.getStorageIds()) {
-                if (mDevice != getDevice()) throw new IndexingException();
-                Stack<Integer> pendingDirectories = new Stack<Integer>();
-                pendingDirectories.add(0xFFFFFFFF); // start at the root of the device
-                while (!pendingDirectories.isEmpty()) {
-                    if (mDevice != getDevice()) throw new IndexingException();
-                    int dirHandle = pendingDirectories.pop();
-                    for (int objectHandle : mDevice.getObjectHandles(storageId, 0, dirHandle)) {
-                        MtpObjectInfo objectInfo = mDevice.getObjectInfo(objectHandle);
-                        if (objectInfo == null) throw new IndexingException();
-                        int format = objectInfo.getFormat();
-                        if (format == MtpConstants.FORMAT_ASSOCIATION) {
-                            pendingDirectories.add(objectHandle);
-                        } else if (SUPPORTED_IMAGE_FORMATS.contains(format)
-                                || SUPPORTED_VIDEO_FORMATS.contains(format)) {
-                            addObject(objectInfo);
-                        }
-                    }
-                }
-            }
-            Collection<DateBucket> values = mBucketsTemp.values();
-            mBucketsTemp = null;
-            mBuckets = values.toArray(new DateBucket[values.size()]);
-            values = null;
-            synchronized (MtpDeviceIndex.this) {
-                mProgress = Progress.Sorting;
-                if (mProgressListener != null) {
-                    mProgressListener.onSorting();
-                }
-            }
-            sortAll();
-            buildLookupIndex();
-            synchronized (MtpDeviceIndex.this) {
-                if (mDevice != getDevice()) throw new IndexingException();
-                copyResults();
-
-                /*
-                 * In order for getBuckets to operate in constant time for descending
-                 * order, we must precompute a reversed array of the buckets, mainly
-                 * because the android.widget.SectionIndexer interface which adapters
-                 * that call getBuckets implement depends on section numbers to be
-                 * ascending relative to the scroll position, so we must have this for
-                 * descending order or the scrollbar goes crazy.
-                 */
-                computeReversedBuckets();
-
-                mProgress = Progress.Finished;
-                if (mProgressListener != null) {
-                    mProgressListener.onIndexFinish();
-                }
-            }
-        }
-
-        private SimpleDate mDateInstance = new SimpleDate();
-
-        private void addObject(MtpObjectInfo objectInfo) {
-            mNumObjects++;
-            mDateInstance.setTimestamp(objectInfo.getDateCreated());
-            DateBucket bucket = mBucketsTemp.get(mDateInstance);
-            if (bucket == null) {
-                bucket = new DateBucket(mDateInstance, objectInfo);
-                mBucketsTemp.put(mDateInstance, bucket);
-                mDateInstance = new SimpleDate(); // only create new date
-                                                  // objects when they are used
-                return;
-            } else {
-                bucket.tempElementsList.add(objectInfo);
-            }
-            if (mProgressListener != null) {
-                mProgressListener.onObjectIndexed(objectInfo, mNumObjects);
-            }
-        }
-
-        private void sortAll() {
-            Arrays.sort(mBuckets);
-            for (DateBucket bucket : mBuckets) {
-                bucket.sortElements(sMtpObjectComparator);
-            }
-        }
-
-    }
-
-    private void computeReversedBuckets() {
-        mCachedReverseBuckets = new Object[mBuckets.length];
-        for (int i = 0; i < mCachedReverseBuckets.length; i++) {
-            mCachedReverseBuckets[i] = mBuckets[mBuckets.length - 1 - i];
-        }
-    }
-}
diff --git a/src/com/android/gallery3d/ingest/SimpleDate.java b/src/com/android/gallery3d/ingest/SimpleDate.java
deleted file mode 100644
index 05db2cd..0000000
--- a/src/com/android/gallery3d/ingest/SimpleDate.java
+++ /dev/null
@@ -1,114 +0,0 @@
-/*
- * Copyright (C) 2013 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.gallery3d.ingest;
-
-import java.text.DateFormat;
-import java.util.Calendar;
-
-/**
- * Represents a date (year, month, day)
- */
-public class SimpleDate implements Comparable<SimpleDate> {
-    public int month; // MM
-    public int day; // DD
-    public int year; // YYYY
-    private long timestamp;
-    private String mCachedStringRepresentation;
-
-    public SimpleDate() {
-    }
-
-    public SimpleDate(long timestamp) {
-        setTimestamp(timestamp);
-    }
-
-    private static Calendar sCalendarInstance = Calendar.getInstance();
-
-    public void setTimestamp(long timestamp) {
-        synchronized (sCalendarInstance) {
-            // TODO find a more efficient way to convert a timestamp to a date?
-            sCalendarInstance.setTimeInMillis(timestamp);
-            this.day = sCalendarInstance.get(Calendar.DATE);
-            this.month = sCalendarInstance.get(Calendar.MONTH);
-            this.year = sCalendarInstance.get(Calendar.YEAR);
-            this.timestamp = timestamp;
-            mCachedStringRepresentation = DateFormat.getDateInstance(DateFormat.SHORT).format(timestamp);
-        }
-    }
-
-    @Override
-    public int hashCode() {
-        final int prime = 31;
-        int result = 1;
-        result = prime * result + day;
-        result = prime * result + month;
-        result = prime * result + year;
-        return result;
-    }
-
-    @Override
-    public boolean equals(Object obj) {
-        if (this == obj)
-            return true;
-        if (obj == null)
-            return false;
-        if (!(obj instanceof SimpleDate))
-            return false;
-        SimpleDate other = (SimpleDate) obj;
-        if (year != other.year)
-            return false;
-        if (month != other.month)
-            return false;
-        if (day != other.day)
-            return false;
-        return true;
-    }
-
-    @Override
-    public int compareTo(SimpleDate other) {
-        int yearDiff = this.year - other.getYear();
-        if (yearDiff != 0)
-            return yearDiff;
-        else {
-            int monthDiff = this.month - other.getMonth();
-            if (monthDiff != 0)
-                return monthDiff;
-            else
-                return this.day - other.getDay();
-        }
-    }
-
-    public int getDay() {
-        return day;
-    }
-
-    public int getMonth() {
-        return month;
-    }
-
-    public int getYear() {
-        return year;
-    }
-
-    @Override
-    public String toString() {
-        if (mCachedStringRepresentation == null) {
-            mCachedStringRepresentation = DateFormat.getDateInstance(DateFormat.SHORT).format(timestamp);
-        }
-        return mCachedStringRepresentation;
-    }
-}
diff --git a/src/com/android/gallery3d/ingest/adapter/CheckBroker.java b/src/com/android/gallery3d/ingest/adapter/CheckBroker.java
deleted file mode 100644
index 6783f23..0000000
--- a/src/com/android/gallery3d/ingest/adapter/CheckBroker.java
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Copyright (C) 2013 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.gallery3d.ingest.adapter;
-
-import java.util.ArrayList;
-import java.util.Collection;
-
-public abstract class CheckBroker {
-    private Collection<OnCheckedChangedListener> mListeners =
-            new ArrayList<OnCheckedChangedListener>();
-
-    public interface OnCheckedChangedListener {
-        public void onCheckedChanged(int position, boolean isChecked);
-        public void onBulkCheckedChanged();
-    }
-
-    public abstract void setItemChecked(int position, boolean checked);
-
-    public void onCheckedChange(int position, boolean checked) {
-        if (isItemChecked(position) != checked) {
-            for (OnCheckedChangedListener l : mListeners) {
-                l.onCheckedChanged(position, checked);
-            }
-        }
-    }
-
-    public void onBulkCheckedChange() {
-        for (OnCheckedChangedListener l : mListeners) {
-            l.onBulkCheckedChanged();
-        }
-    }
-
-    public abstract boolean isItemChecked(int position);
-
-    public void registerOnCheckedChangeListener(OnCheckedChangedListener l) {
-        mListeners.add(l);
-    }
-
-    public void unregisterOnCheckedChangeListener(OnCheckedChangedListener l) {
-        mListeners.remove(l);
-    }
-}
diff --git a/src/com/android/gallery3d/ingest/adapter/MtpAdapter.java b/src/com/android/gallery3d/ingest/adapter/MtpAdapter.java
deleted file mode 100644
index e8dd69f..0000000
--- a/src/com/android/gallery3d/ingest/adapter/MtpAdapter.java
+++ /dev/null
@@ -1,192 +0,0 @@
-/*
- * Copyright (C) 2013 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.gallery3d.ingest.adapter;
-
-import android.app.Activity;
-import android.content.Context;
-import android.mtp.MtpObjectInfo;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.BaseAdapter;
-import android.widget.SectionIndexer;
-
-import com.android.gallery3d.R;
-import com.android.gallery3d.ingest.MtpDeviceIndex;
-import com.android.gallery3d.ingest.MtpDeviceIndex.SortOrder;
-import com.android.gallery3d.ingest.SimpleDate;
-import com.android.gallery3d.ingest.ui.DateTileView;
-import com.android.gallery3d.ingest.ui.MtpThumbnailTileView;
-
-public class MtpAdapter extends BaseAdapter implements SectionIndexer {
-    public static final int ITEM_TYPE_MEDIA = 0;
-    public static final int ITEM_TYPE_BUCKET = 1;
-
-    private Context mContext;
-    private MtpDeviceIndex mModel;
-    private SortOrder mSortOrder = SortOrder.Descending;
-    private LayoutInflater mInflater;
-    private int mGeneration = 0;
-
-    public MtpAdapter(Activity context) {
-        super();
-        mContext = context;
-        mInflater = LayoutInflater.from(context);
-    }
-
-    public void setMtpDeviceIndex(MtpDeviceIndex index) {
-        mModel = index;
-        notifyDataSetChanged();
-    }
-
-    public MtpDeviceIndex getMtpDeviceIndex() {
-        return mModel;
-    }
-
-    @Override
-    public void notifyDataSetChanged() {
-        mGeneration++;
-        super.notifyDataSetChanged();
-    }
-
-    @Override
-    public void notifyDataSetInvalidated() {
-        mGeneration++;
-        super.notifyDataSetInvalidated();
-    }
-
-    public boolean deviceConnected() {
-        return (mModel != null) && (mModel.getDevice() != null);
-    }
-
-    public boolean indexReady() {
-        return (mModel != null) && mModel.indexReady();
-    }
-
-    @Override
-    public int getCount() {
-        return mModel != null ? mModel.size() : 0;
-    }
-
-    @Override
-    public Object getItem(int position) {
-        return mModel.get(position, mSortOrder);
-    }
-
-    @Override
-    public boolean areAllItemsEnabled() {
-        return true;
-    }
-
-    @Override
-    public boolean isEnabled(int position) {
-        return true;
-    }
-
-    @Override
-    public long getItemId(int position) {
-        return position;
-    }
-
-    @Override
-    public int getViewTypeCount() {
-        return 2;
-    }
-
-    @Override
-    public int getItemViewType(int position) {
-        // If the position is the first in its section, then it corresponds to
-        // a title tile, if not it's a media tile
-        if (position == getPositionForSection(getSectionForPosition(position))) {
-            return ITEM_TYPE_BUCKET;
-        } else {
-            return ITEM_TYPE_MEDIA;
-        }
-    }
-
-    public boolean itemAtPositionIsBucket(int position) {
-        return getItemViewType(position) == ITEM_TYPE_BUCKET;
-    }
-
-    public boolean itemAtPositionIsMedia(int position) {
-        return getItemViewType(position) == ITEM_TYPE_MEDIA;
-    }
-
-    @Override
-    public View getView(int position, View convertView, ViewGroup parent) {
-        int type = getItemViewType(position);
-        if (type == ITEM_TYPE_MEDIA) {
-            MtpThumbnailTileView imageView;
-            if (convertView == null) {
-                imageView = (MtpThumbnailTileView) mInflater.inflate(
-                        R.layout.ingest_thumbnail, parent, false);
-            } else {
-                imageView = (MtpThumbnailTileView) convertView;
-            }
-            imageView.setMtpDeviceAndObjectInfo(mModel.getDevice(), (MtpObjectInfo)getItem(position), mGeneration);
-            return imageView;
-        } else {
-            DateTileView dateTile;
-            if (convertView == null) {
-                dateTile = (DateTileView) mInflater.inflate(
-                        R.layout.ingest_date_tile, parent, false);
-            } else {
-                dateTile = (DateTileView) convertView;
-            }
-            dateTile.setDate((SimpleDate)getItem(position));
-            return dateTile;
-        }
-    }
-
-    @Override
-    public int getPositionForSection(int section) {
-        if (getCount() == 0) {
-            return 0;
-        }
-        int numSections = getSections().length;
-        if (section >= numSections) {
-            section = numSections - 1;
-        }
-        return mModel.getFirstPositionForBucketNumber(section, mSortOrder);
-    }
-
-    @Override
-    public int getSectionForPosition(int position) {
-        int count = getCount();
-        if (count == 0) {
-            return 0;
-        }
-        if (position >= count) {
-            position = count - 1;
-        }
-        return mModel.getBucketNumberForPosition(position, mSortOrder);
-    }
-
-    @Override
-    public Object[] getSections() {
-        return getCount() > 0 ? mModel.getBuckets(mSortOrder) : null;
-    }
-
-    public SortOrder getSortOrder() {
-        return mSortOrder;
-    }
-
-    public int translatePositionWithoutLabels(int position) {
-        if (mModel == null) return -1;
-        return mModel.getPositionFromPositionWithoutLabels(position, mSortOrder);
-    }
-}
diff --git a/src/com/android/gallery3d/ingest/adapter/MtpPagerAdapter.java b/src/com/android/gallery3d/ingest/adapter/MtpPagerAdapter.java
deleted file mode 100644
index 9e7abc0..0000000
--- a/src/com/android/gallery3d/ingest/adapter/MtpPagerAdapter.java
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- * Copyright (C) 2013 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.gallery3d.ingest.adapter;
-
-import android.content.Context;
-import android.mtp.MtpObjectInfo;
-import android.support.v4.view.PagerAdapter;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-
-import com.android.gallery3d.R;
-import com.android.gallery3d.ingest.MtpDeviceIndex;
-import com.android.gallery3d.ingest.MtpDeviceIndex.SortOrder;
-import com.android.gallery3d.ingest.ui.MtpFullscreenView;
-
-public class MtpPagerAdapter extends PagerAdapter {
-
-    private LayoutInflater mInflater;
-    private int mGeneration = 0;
-    private CheckBroker mBroker;
-    private MtpDeviceIndex mModel;
-    private SortOrder mSortOrder = SortOrder.Descending;
-
-    private MtpFullscreenView mReusableView = null;
-
-    public MtpPagerAdapter(Context context, CheckBroker broker) {
-        super();
-        mInflater = LayoutInflater.from(context);
-        mBroker = broker;
-    }
-
-    public void setMtpDeviceIndex(MtpDeviceIndex index) {
-        mModel = index;
-        notifyDataSetChanged();
-    }
-
-    @Override
-    public int getCount() {
-        return mModel != null ? mModel.sizeWithoutLabels() : 0;
-    }
-
-    @Override
-    public void notifyDataSetChanged() {
-        mGeneration++;
-        super.notifyDataSetChanged();
-    }
-
-    public int translatePositionWithLabels(int position) {
-        if (mModel == null) return -1;
-        return mModel.getPositionWithoutLabelsFromPosition(position, mSortOrder);
-    }
-
-    @Override
-    public void finishUpdate(ViewGroup container) {
-        mReusableView = null;
-        super.finishUpdate(container);
-    }
-
-    @Override
-    public boolean isViewFromObject(View view, Object object) {
-        return view == object;
-    }
-
-    @Override
-    public void destroyItem(ViewGroup container, int position, Object object) {
-        MtpFullscreenView v = (MtpFullscreenView)object;
-        container.removeView(v);
-        mBroker.unregisterOnCheckedChangeListener(v);
-        mReusableView = v;
-    }
-
-    @Override
-    public Object instantiateItem(ViewGroup container, int position) {
-        MtpFullscreenView v;
-        if (mReusableView != null) {
-            v = mReusableView;
-            mReusableView = null;
-        } else {
-            v = (MtpFullscreenView) mInflater.inflate(R.layout.ingest_fullsize, container, false);
-        }
-        MtpObjectInfo i = mModel.getWithoutLabels(position, mSortOrder);
-        v.getImageView().setMtpDeviceAndObjectInfo(mModel.getDevice(), i, mGeneration);
-        v.setPositionAndBroker(position, mBroker);
-        container.addView(v);
-        return v;
-    }
-}
diff --git a/src/com/android/gallery3d/ingest/data/BitmapWithMetadata.java b/src/com/android/gallery3d/ingest/data/BitmapWithMetadata.java
deleted file mode 100644
index bbc90f6..0000000
--- a/src/com/android/gallery3d/ingest/data/BitmapWithMetadata.java
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright (C) 2013 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.gallery3d.ingest.data;
-
-import android.graphics.Bitmap;
-
-public class BitmapWithMetadata {
-    public Bitmap bitmap;
-    public int rotationDegrees;
-
-    public BitmapWithMetadata(Bitmap bitmap, int rotationDegrees) {
-        this.bitmap = bitmap;
-        this.rotationDegrees = rotationDegrees;
-    }
-}
diff --git a/src/com/android/gallery3d/ingest/data/MtpBitmapFetch.java b/src/com/android/gallery3d/ingest/data/MtpBitmapFetch.java
deleted file mode 100644
index 30868c2..0000000
--- a/src/com/android/gallery3d/ingest/data/MtpBitmapFetch.java
+++ /dev/null
@@ -1,106 +0,0 @@
-/*
- * Copyright (C) 2013 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.gallery3d.ingest.data;
-
-import android.content.Context;
-import android.graphics.Bitmap;
-import android.graphics.BitmapFactory;
-import android.mtp.MtpDevice;
-import android.mtp.MtpObjectInfo;
-import android.util.DisplayMetrics;
-import android.view.WindowManager;
-
-import com.android.camera.Exif;
-import com.android.photos.data.GalleryBitmapPool;
-
-public class MtpBitmapFetch {
-    private static int sMaxSize = 0;
-
-    public static void recycleThumbnail(Bitmap b) {
-        if (b != null) {
-            GalleryBitmapPool.getInstance().put(b);
-        }
-    }
-
-    public static Bitmap getThumbnail(MtpDevice device, MtpObjectInfo info) {
-        byte[] imageBytes = device.getThumbnail(info.getObjectHandle());
-        if (imageBytes == null) {
-            return null;
-        }
-        BitmapFactory.Options o = new BitmapFactory.Options();
-        o.inJustDecodeBounds = true;
-        BitmapFactory.decodeByteArray(imageBytes, 0, imageBytes.length, o);
-        if (o.outWidth == 0 || o.outHeight == 0) {
-            return null;
-        }
-        o.inBitmap = GalleryBitmapPool.getInstance().get(o.outWidth, o.outHeight);
-        o.inMutable = true;
-        o.inJustDecodeBounds = false;
-        o.inSampleSize = 1;
-        try {
-            return BitmapFactory.decodeByteArray(imageBytes, 0, imageBytes.length, o);
-        } catch (IllegalArgumentException e) {
-            // BitmapFactory throws an exception rather than returning null
-            // when image decoding fails and an existing bitmap was supplied
-            // for recycling, even if the failure was not caused by the use
-            // of that bitmap.
-            return BitmapFactory.decodeByteArray(imageBytes, 0, imageBytes.length);
-        }
-    }
-
-    public static BitmapWithMetadata getFullsize(MtpDevice device, MtpObjectInfo info) {
-        return getFullsize(device, info, sMaxSize);
-    }
-
-    public static BitmapWithMetadata getFullsize(MtpDevice device, MtpObjectInfo info, int maxSide) {
-        byte[] imageBytes = device.getObject(info.getObjectHandle(), info.getCompressedSize());
-        if (imageBytes == null) {
-            return null;
-        }
-        Bitmap created;
-        if (maxSide > 0) {
-            BitmapFactory.Options o = new BitmapFactory.Options();
-            o.inJustDecodeBounds = true;
-            BitmapFactory.decodeByteArray(imageBytes, 0, imageBytes.length, o);
-            int w = o.outWidth;
-            int h = o.outHeight;
-            int comp = Math.max(h, w);
-            int sampleSize = 1;
-            while ((comp >> 1) >= maxSide) {
-                comp = comp >> 1;
-                sampleSize++;
-            }
-            o.inSampleSize = sampleSize;
-            o.inJustDecodeBounds = false;
-            created = BitmapFactory.decodeByteArray(imageBytes, 0, imageBytes.length, o);
-        } else {
-            created = BitmapFactory.decodeByteArray(imageBytes, 0, imageBytes.length);
-        }
-        if (created == null) {
-            return null;
-        }
-
-        return new BitmapWithMetadata(created, Exif.getOrientation(imageBytes));
-    }
-
-    public static void configureForContext(Context context) {
-        DisplayMetrics metrics = new DisplayMetrics();
-        WindowManager wm = (WindowManager)context.getSystemService(Context.WINDOW_SERVICE);
-        wm.getDefaultDisplay().getMetrics(metrics);
-        sMaxSize = Math.max(metrics.heightPixels, metrics.widthPixels);
-    }
-}
diff --git a/src/com/android/gallery3d/ingest/ui/DateTileView.java b/src/com/android/gallery3d/ingest/ui/DateTileView.java
deleted file mode 100644
index 52fe9b8..0000000
--- a/src/com/android/gallery3d/ingest/ui/DateTileView.java
+++ /dev/null
@@ -1,107 +0,0 @@
-/*
- * Copyright (C) 2013 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.gallery3d.ingest.ui;
-
-import android.content.Context;
-import android.util.AttributeSet;
-import android.widget.FrameLayout;
-import android.widget.TextView;
-
-import com.android.gallery3d.R;
-import com.android.gallery3d.ingest.SimpleDate;
-
-import java.text.DateFormatSymbols;
-import java.util.Locale;
-
-public class DateTileView extends FrameLayout {
-    private static String[] sMonthNames = DateFormatSymbols.getInstance().getShortMonths();
-    private static Locale sLocale;
-
-    static {
-        refreshLocale();
-    }
-
-    public static boolean refreshLocale() {
-        Locale currentLocale = Locale.getDefault();
-        if (!currentLocale.equals(sLocale)) {
-            sLocale = currentLocale;
-            sMonthNames = DateFormatSymbols.getInstance(sLocale).getShortMonths();
-            return true;
-        } else {
-            return false;
-        }
-    }
-
-    private TextView mDateTextView;
-    private TextView mMonthTextView;
-    private TextView mYearTextView;
-    private int mMonth = -1;
-    private int mYear = -1;
-    private int mDate = -1;
-    private String[] mMonthNames = sMonthNames;
-
-    public DateTileView(Context context) {
-        super(context);
-    }
-
-    public DateTileView(Context context, AttributeSet attrs) {
-        super(context, attrs);
-    }
-
-    public DateTileView(Context context, AttributeSet attrs, int defStyle) {
-        super(context, attrs, defStyle);
-    }
-
-    @Override
-    public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
-        // Force this to be square
-        super.onMeasure(widthMeasureSpec, widthMeasureSpec);
-    }
-
-    @Override
-    protected void onFinishInflate() {
-        super.onFinishInflate();
-        mDateTextView = (TextView) findViewById(R.id.date_tile_day);
-        mMonthTextView = (TextView) findViewById(R.id.date_tile_month);
-        mYearTextView = (TextView) findViewById(R.id.date_tile_year);
-    }
-
-    public void setDate(SimpleDate date) {
-        setDate(date.getDay(), date.getMonth(), date.getYear());
-    }
-
-    public void setDate(int date, int month, int year) {
-        if (date != mDate) {
-            mDate = date;
-            mDateTextView.setText(mDate > 9 ? Integer.toString(mDate) : "0" + mDate);
-        }
-        if (mMonthNames != sMonthNames) {
-            mMonthNames = sMonthNames;
-            if (month == mMonth) {
-                mMonthTextView.setText(mMonthNames[mMonth]);
-            }
-        }
-        if (month != mMonth) {
-            mMonth = month;
-            mMonthTextView.setText(mMonthNames[mMonth]);
-        }
-        if (year != mYear) {
-            mYear = year;
-            mYearTextView.setText(Integer.toString(mYear));
-        }
-    }
-}
diff --git a/src/com/android/gallery3d/ingest/ui/IngestGridView.java b/src/com/android/gallery3d/ingest/ui/IngestGridView.java
deleted file mode 100644
index c821259..0000000
--- a/src/com/android/gallery3d/ingest/ui/IngestGridView.java
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Copyright (C) 2013 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.gallery3d.ingest.ui;
-
-import android.content.Context;
-import android.util.AttributeSet;
-import android.widget.GridView;
-
-/**
- * This just extends GridView with the ability to listen for calls
- * to clearChoices()
- */
-public class IngestGridView extends GridView {
-
-    public interface OnClearChoicesListener {
-        public void onClearChoices();
-    }
-
-    private OnClearChoicesListener mOnClearChoicesListener = null;
-
-    public IngestGridView(Context context) {
-        super(context);
-    }
-
-    public IngestGridView(Context context, AttributeSet attrs) {
-        super(context, attrs);
-    }
-
-    public IngestGridView(Context context, AttributeSet attrs, int defStyle) {
-        super(context, attrs, defStyle);
-    }
-
-    public void setOnClearChoicesListener(OnClearChoicesListener l) {
-        mOnClearChoicesListener = l;
-    }
-
-    @Override
-    public void clearChoices() {
-        super.clearChoices();
-        if (mOnClearChoicesListener != null) {
-            mOnClearChoicesListener.onClearChoices();
-        }
-    }
-}
diff --git a/src/com/android/gallery3d/ingest/ui/MtpFullscreenView.java b/src/com/android/gallery3d/ingest/ui/MtpFullscreenView.java
deleted file mode 100644
index 8d3884d..0000000
--- a/src/com/android/gallery3d/ingest/ui/MtpFullscreenView.java
+++ /dev/null
@@ -1,115 +0,0 @@
-/*
- * Copyright (C) 2013 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.gallery3d.ingest.ui;
-
-import android.content.Context;
-import android.util.AttributeSet;
-import android.widget.CheckBox;
-import android.widget.Checkable;
-import android.widget.CompoundButton;
-import android.widget.CompoundButton.OnCheckedChangeListener;
-import android.widget.RelativeLayout;
-
-import com.android.gallery3d.R;
-import com.android.gallery3d.ingest.adapter.CheckBroker;
-
-public class MtpFullscreenView extends RelativeLayout implements Checkable,
-    CompoundButton.OnCheckedChangeListener, CheckBroker.OnCheckedChangedListener {
-
-    private MtpImageView mImageView;
-    private CheckBox mCheckbox;
-    private int mPosition = -1;
-    private CheckBroker mBroker;
-
-    public MtpFullscreenView(Context context) {
-        super(context);
-    }
-
-    public MtpFullscreenView(Context context, AttributeSet attrs) {
-        super(context, attrs);
-    }
-
-    public MtpFullscreenView(Context context, AttributeSet attrs, int defStyle) {
-        super(context, attrs, defStyle);
-    }
-
-    @Override
-    protected void onFinishInflate() {
-        super.onFinishInflate();
-        mImageView = (MtpImageView) findViewById(R.id.ingest_fullsize_image);
-        mCheckbox = (CheckBox) findViewById(R.id.ingest_fullsize_image_checkbox);
-        mCheckbox.setOnCheckedChangeListener(this);
-    }
-
-    @Override
-    public boolean isChecked() {
-        return mCheckbox.isChecked();
-    }
-
-    @Override
-    public void setChecked(boolean checked) {
-        mCheckbox.setChecked(checked);
-    }
-
-    @Override
-    public void toggle() {
-        mCheckbox.toggle();
-    }
-
-    @Override
-    public void onDetachedFromWindow() {
-        setPositionAndBroker(-1, null);
-        super.onDetachedFromWindow();
-    }
-
-    public MtpImageView getImageView() {
-        return mImageView;
-    }
-
-    public int getPosition() {
-        return mPosition;
-    }
-
-    public void setPositionAndBroker(int position, CheckBroker b) {
-        if (mBroker != null) {
-            mBroker.unregisterOnCheckedChangeListener(this);
-        }
-        mPosition = position;
-        mBroker = b;
-        if (mBroker != null) {
-            setChecked(mBroker.isItemChecked(position));
-            mBroker.registerOnCheckedChangeListener(this);
-        }
-    }
-
-    @Override
-    public void onCheckedChanged(CompoundButton arg0, boolean isChecked) {
-        if (mBroker != null) mBroker.setItemChecked(mPosition, isChecked);
-    }
-
-    @Override
-    public void onCheckedChanged(int position, boolean isChecked) {
-        if (position == mPosition) {
-            setChecked(isChecked);
-        }
-    }
-
-    @Override
-    public void onBulkCheckedChanged() {
-        if(mBroker != null) setChecked(mBroker.isItemChecked(mPosition));
-    }
-}
diff --git a/src/com/android/gallery3d/ingest/ui/MtpImageView.java b/src/com/android/gallery3d/ingest/ui/MtpImageView.java
deleted file mode 100644
index 80c1051..0000000
--- a/src/com/android/gallery3d/ingest/ui/MtpImageView.java
+++ /dev/null
@@ -1,280 +0,0 @@
-/*
- * Copyright (C) 2013 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.gallery3d.ingest.ui;
-
-import android.content.Context;
-import android.graphics.Canvas;
-import android.graphics.Matrix;
-import android.graphics.drawable.Drawable;
-import android.mtp.MtpDevice;
-import android.mtp.MtpObjectInfo;
-import android.os.Handler;
-import android.os.HandlerThread;
-import android.os.Looper;
-import android.os.Message;
-import android.util.AttributeSet;
-import android.widget.ImageView;
-
-import com.android.gallery3d.R;
-import com.android.gallery3d.ingest.MtpDeviceIndex;
-import com.android.gallery3d.ingest.data.BitmapWithMetadata;
-import com.android.gallery3d.ingest.data.MtpBitmapFetch;
-
-import java.lang.ref.WeakReference;
-
-public class MtpImageView extends ImageView {
-    // We will use the thumbnail for images larger than this threshold
-    private static final int MAX_FULLSIZE_PREVIEW_SIZE = 8388608; // 8 megabytes
-
-    private int mObjectHandle;
-    private int mGeneration;
-
-    private WeakReference<MtpImageView> mWeakReference = new WeakReference<MtpImageView>(this);
-    private Object mFetchLock = new Object();
-    private boolean mFetchPending = false;
-    private MtpObjectInfo mFetchObjectInfo;
-    private MtpDevice mFetchDevice;
-    private Object mFetchResult;
-    private Drawable mOverlayIcon;
-    private boolean mShowOverlayIcon;
-
-    private static final FetchImageHandler sFetchHandler = FetchImageHandler.createOnNewThread();
-    private static final ShowImageHandler sFetchCompleteHandler = new ShowImageHandler();
-
-    private void init() {
-         showPlaceholder();
-    }
-
-    public MtpImageView(Context context) {
-        super(context);
-        init();
-    }
-
-    public MtpImageView(Context context, AttributeSet attrs) {
-        super(context, attrs);
-        init();
-    }
-
-    public MtpImageView(Context context, AttributeSet attrs, int defStyle) {
-        super(context, attrs, defStyle);
-        init();
-    }
-
-    private void showPlaceholder() {
-        setImageResource(android.R.color.transparent);
-    }
-
-    public void setMtpDeviceAndObjectInfo(MtpDevice device, MtpObjectInfo object, int gen) {
-        int handle = object.getObjectHandle();
-        if (handle == mObjectHandle && gen == mGeneration) {
-            return;
-        }
-        cancelLoadingAndClear();
-        showPlaceholder();
-        mGeneration = gen;
-        mObjectHandle = handle;
-        mShowOverlayIcon = MtpDeviceIndex.SUPPORTED_VIDEO_FORMATS.contains(object.getFormat());
-        if (mShowOverlayIcon && mOverlayIcon == null) {
-            mOverlayIcon = getResources().getDrawable(R.drawable.ic_control_play);
-            updateOverlayIconBounds();
-        }
-        synchronized (mFetchLock) {
-            mFetchObjectInfo = object;
-            mFetchDevice = device;
-            if (mFetchPending) return;
-            mFetchPending = true;
-            sFetchHandler.sendMessage(
-                    sFetchHandler.obtainMessage(0, mWeakReference));
-        }
-    }
-
-    protected Object fetchMtpImageDataFromDevice(MtpDevice device, MtpObjectInfo info) {
-        if (info.getCompressedSize() <= MAX_FULLSIZE_PREVIEW_SIZE
-                && MtpDeviceIndex.SUPPORTED_IMAGE_FORMATS.contains(info.getFormat())) {
-            return MtpBitmapFetch.getFullsize(device, info);
-        } else {
-            return new BitmapWithMetadata(MtpBitmapFetch.getThumbnail(device, info), 0);
-        }
-    }
-
-    private float mLastBitmapWidth;
-    private float mLastBitmapHeight;
-    private int mLastRotationDegrees;
-    private Matrix mDrawMatrix = new Matrix();
-
-    private void updateDrawMatrix() {
-        mDrawMatrix.reset();
-        float dwidth;
-        float dheight;
-        float vheight = getHeight();
-        float vwidth = getWidth();
-        float scale;
-        boolean rotated90 = (mLastRotationDegrees % 180 != 0);
-        if (rotated90) {
-            dwidth = mLastBitmapHeight;
-            dheight = mLastBitmapWidth;
-        } else {
-            dwidth = mLastBitmapWidth;
-            dheight = mLastBitmapHeight;
-        }
-        if (dwidth <= vwidth && dheight <= vheight) {
-            scale = 1.0f;
-        } else {
-            scale = Math.min(vwidth / dwidth, vheight / dheight);
-        }
-        mDrawMatrix.setScale(scale, scale);
-        if (rotated90) {
-            mDrawMatrix.postTranslate(-dheight * scale * 0.5f,
-                    -dwidth * scale * 0.5f);
-            mDrawMatrix.postRotate(mLastRotationDegrees);
-            mDrawMatrix.postTranslate(dwidth * scale * 0.5f,
-                    dheight * scale * 0.5f);
-        }
-        mDrawMatrix.postTranslate((vwidth - dwidth * scale) * 0.5f,
-                (vheight - dheight * scale) * 0.5f);
-        if (!rotated90 && mLastRotationDegrees > 0) {
-            // rotated by a multiple of 180
-            mDrawMatrix.postRotate(mLastRotationDegrees, vwidth / 2, vheight / 2);
-        }
-        setImageMatrix(mDrawMatrix);
-    }
-
-    private static final int OVERLAY_ICON_SIZE_DENOMINATOR = 4;
-
-    private void updateOverlayIconBounds() {
-        int iheight = mOverlayIcon.getIntrinsicHeight();
-        int iwidth = mOverlayIcon.getIntrinsicWidth();
-        int vheight = getHeight();
-        int vwidth = getWidth();
-        float scale_height = ((float) vheight) / (iheight * OVERLAY_ICON_SIZE_DENOMINATOR);
-        float scale_width = ((float) vwidth) / (iwidth * OVERLAY_ICON_SIZE_DENOMINATOR);
-        if (scale_height >= 1f && scale_width >= 1f) {
-            mOverlayIcon.setBounds((vwidth - iwidth) / 2,
-                    (vheight - iheight) / 2,
-                    (vwidth + iwidth) / 2,
-                    (vheight + iheight) / 2);
-        } else {
-            float scale = Math.min(scale_height, scale_width);
-            mOverlayIcon.setBounds((int) (vwidth - scale * iwidth) / 2,
-                    (int) (vheight - scale * iheight) / 2,
-                    (int) (vwidth + scale * iwidth) / 2,
-                    (int) (vheight + scale * iheight) / 2);
-        }
-    }
-
-    @Override
-    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
-        super.onLayout(changed, left, top, right, bottom);
-        if (changed && getScaleType() == ScaleType.MATRIX) {
-            updateDrawMatrix();
-        }
-        if (mShowOverlayIcon && changed && mOverlayIcon != null) {
-            updateOverlayIconBounds();
-        }
-    }
-
-    @Override
-    protected void onDraw(Canvas canvas) {
-        super.onDraw(canvas);
-        if (mShowOverlayIcon && mOverlayIcon != null) {
-            mOverlayIcon.draw(canvas);
-        }
-    }
-
-    protected void onMtpImageDataFetchedFromDevice(Object result) {
-        BitmapWithMetadata bitmapWithMetadata = (BitmapWithMetadata)result;
-        if (getScaleType() == ScaleType.MATRIX) {
-            mLastBitmapHeight = bitmapWithMetadata.bitmap.getHeight();
-            mLastBitmapWidth = bitmapWithMetadata.bitmap.getWidth();
-            mLastRotationDegrees = bitmapWithMetadata.rotationDegrees;
-            updateDrawMatrix();
-        } else {
-            setRotation(bitmapWithMetadata.rotationDegrees);
-        }
-        setAlpha(0f);
-        setImageBitmap(bitmapWithMetadata.bitmap);
-        animate().alpha(1f);
-    }
-
-    protected void cancelLoadingAndClear() {
-        synchronized (mFetchLock) {
-            mFetchDevice = null;
-            mFetchObjectInfo = null;
-            mFetchResult = null;
-        }
-        animate().cancel();
-        setImageResource(android.R.color.transparent);
-    }
-
-    @Override
-    public void onDetachedFromWindow() {
-        cancelLoadingAndClear();
-        super.onDetachedFromWindow();
-    }
-
-    private static class FetchImageHandler extends Handler {
-        public FetchImageHandler(Looper l) {
-            super(l);
-        }
-
-        public static FetchImageHandler createOnNewThread() {
-            HandlerThread t = new HandlerThread("MtpImageView Fetch");
-            t.start();
-            return new FetchImageHandler(t.getLooper());
-        }
-
-        @Override
-        public void handleMessage(Message msg) {
-            @SuppressWarnings("unchecked")
-            MtpImageView parent = ((WeakReference<MtpImageView>) msg.obj).get();
-            if (parent == null) return;
-            MtpObjectInfo objectInfo;
-            MtpDevice device;
-            synchronized (parent.mFetchLock) {
-                parent.mFetchPending = false;
-                device = parent.mFetchDevice;
-                objectInfo = parent.mFetchObjectInfo;
-            }
-            if (device == null) return;
-            Object result = parent.fetchMtpImageDataFromDevice(device, objectInfo);
-            if (result == null) return;
-            synchronized (parent.mFetchLock) {
-                if (parent.mFetchObjectInfo != objectInfo) return;
-                parent.mFetchResult = result;
-                parent.mFetchDevice = null;
-                parent.mFetchObjectInfo = null;
-                sFetchCompleteHandler.sendMessage(
-                        sFetchCompleteHandler.obtainMessage(0, parent.mWeakReference));
-            }
-        }
-    }
-
-    private static class ShowImageHandler extends Handler {
-        @Override
-        public void handleMessage(Message msg) {
-            @SuppressWarnings("unchecked")
-            MtpImageView parent = ((WeakReference<MtpImageView>) msg.obj).get();
-            if (parent == null) return;
-            Object result;
-            synchronized (parent.mFetchLock) {
-                result = parent.mFetchResult;
-            }
-            if (result == null) return;
-            parent.onMtpImageDataFetchedFromDevice(result);
-        }
-    }
-}
diff --git a/src/com/android/gallery3d/ingest/ui/MtpThumbnailTileView.java b/src/com/android/gallery3d/ingest/ui/MtpThumbnailTileView.java
deleted file mode 100644
index 3307e78..0000000
--- a/src/com/android/gallery3d/ingest/ui/MtpThumbnailTileView.java
+++ /dev/null
@@ -1,106 +0,0 @@
-/*
- * Copyright (C) 2013 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.gallery3d.ingest.ui;
-
-import android.content.Context;
-import android.graphics.Bitmap;
-import android.graphics.Canvas;
-import android.graphics.Paint;
-import android.mtp.MtpDevice;
-import android.mtp.MtpObjectInfo;
-import android.util.AttributeSet;
-import android.widget.Checkable;
-
-import com.android.gallery3d.R;
-import com.android.gallery3d.ingest.data.MtpBitmapFetch;
-
-
-public class MtpThumbnailTileView extends MtpImageView implements Checkable {
-
-    private Paint mForegroundPaint;
-    private boolean mIsChecked;
-    private Bitmap mBitmap;
-
-    private void init() {
-        mForegroundPaint = new Paint();
-        mForegroundPaint.setColor(getResources().getColor(R.color.ingest_highlight_semitransparent));
-    }
-
-    public MtpThumbnailTileView(Context context) {
-        super(context);
-        init();
-    }
-
-    public MtpThumbnailTileView(Context context, AttributeSet attrs) {
-        super(context, attrs);
-        init();
-    }
-
-    public MtpThumbnailTileView(Context context, AttributeSet attrs, int defStyle) {
-        super(context, attrs, defStyle);
-        init();
-    }
-
-    @Override
-    public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
-        // Force this to be square
-        super.onMeasure(widthMeasureSpec, widthMeasureSpec);
-    }
-
-    @Override
-    protected Object fetchMtpImageDataFromDevice(MtpDevice device, MtpObjectInfo info) {
-        return MtpBitmapFetch.getThumbnail(device, info);
-    }
-
-    @Override
-    protected void onMtpImageDataFetchedFromDevice(Object result) {
-        mBitmap = (Bitmap)result;
-        setImageBitmap(mBitmap);
-    }
-
-    @Override
-    public void draw(Canvas canvas) {
-        super.draw(canvas);
-        if (isChecked()) {
-            canvas.drawRect(canvas.getClipBounds(), mForegroundPaint);
-        }
-    }
-
-    @Override
-    public boolean isChecked() {
-        return mIsChecked;
-    }
-
-    @Override
-    public void setChecked(boolean checked) {
-        mIsChecked = checked;
-    }
-
-    @Override
-    public void toggle() {
-        setChecked(!mIsChecked);
-    }
-
-    @Override
-    protected void cancelLoadingAndClear() {
-        super.cancelLoadingAndClear();
-        if (mBitmap != null) {
-            MtpBitmapFetch.recycleThumbnail(mBitmap);
-            mBitmap = null;
-        }
-    }
-}
diff --git a/src/com/android/gallery3d/onetimeinitializer/GalleryWidgetMigrator.java b/src/com/android/gallery3d/onetimeinitializer/GalleryWidgetMigrator.java
deleted file mode 100644
index ef26b1b..0000000
--- a/src/com/android/gallery3d/onetimeinitializer/GalleryWidgetMigrator.java
+++ /dev/null
@@ -1,169 +0,0 @@
-/*
- * 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.gallery3d.onetimeinitializer;
-
-import android.content.Context;
-import android.content.SharedPreferences;
-import android.os.Build;
-import android.os.Environment;
-import android.preference.PreferenceManager;
-import android.util.Log;
-
-import com.android.gallery3d.app.GalleryApp;
-import com.android.gallery3d.common.ApiHelper;
-import com.android.gallery3d.data.DataManager;
-import com.android.gallery3d.data.LocalAlbum;
-import com.android.gallery3d.data.MediaSet;
-import com.android.gallery3d.data.Path;
-import com.android.gallery3d.gadget.WidgetDatabaseHelper;
-import com.android.gallery3d.gadget.WidgetDatabaseHelper.Entry;
-import com.android.gallery3d.util.GalleryUtils;
-
-import java.io.File;
-import java.util.HashMap;
-import java.util.List;
-
-/**
- * This one-timer migrates local-album gallery app widgets from old paths from prior releases 
- * to updated paths in the current build version. This migration is needed because of
- * bucket ID (i.e., directory hash) change in JB and JB MR1 (The external storage path has changed
- * from /mnt/sdcard in pre-JB releases, to /storage/sdcard0 in JB, then again
- * to /external/storage/sdcard/0 in JB MR1).
- */
-public class GalleryWidgetMigrator {
-    private static final String TAG = "GalleryWidgetMigrator";
-    private static final String PRE_JB_EXT_PATH = "/mnt/sdcard";
-    private static final String JB_EXT_PATH = "/storage/sdcard0";
-    private static final String NEW_EXT_PATH =
-            Environment.getExternalStorageDirectory().getAbsolutePath();
-    private static final int RELATIVE_PATH_START = NEW_EXT_PATH.length();
-    private static final String KEY_EXT_PATH = "external_storage_path";
-
-    /**
-     * Migrates local-album gallery widgets from prior releases to current release
-     * due to bucket ID (i.e., directory hash) change.
-     */
-    public static void migrateGalleryWidgets(Context context) {
-        SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
-        // Migration is only needed when external storage path has changed
-        String extPath = prefs.getString(KEY_EXT_PATH, null);
-        boolean isDone = NEW_EXT_PATH.equals(extPath);
-        if (isDone) return;
-
-        try {
-            migrateGalleryWidgetsInternal(context);
-            prefs.edit().putString(KEY_EXT_PATH, NEW_EXT_PATH).commit();
-        } catch (Throwable t) {
-            // exception may be thrown if external storage is not available(?)
-            Log.w(TAG, "migrateGalleryWidgets", t);
-        }
-    }
-
-    private static void migrateGalleryWidgetsInternal(Context context) {
-        GalleryApp galleryApp = (GalleryApp) context.getApplicationContext();
-        DataManager manager = galleryApp.getDataManager();
-        WidgetDatabaseHelper dbHelper = new WidgetDatabaseHelper(context);
-
-        // only need to migrate local-album entries of type TYPE_ALBUM
-        List<Entry> entries = dbHelper.getEntries(WidgetDatabaseHelper.TYPE_ALBUM);
-        if (entries == null) return;
-
-        // Check each entry's relativePath. If exists, update bucket id using relative
-        // path combined with external storage path. Otherwise, iterate through old external
-        // storage paths to find the relative path that matches the old bucket id, and then update
-        // bucket id and relative path
-        HashMap<Integer, Entry> localEntries = new HashMap<Integer, Entry>(entries.size());
-        for (Entry entry : entries) {
-            Path path = Path.fromString(entry.albumPath);
-            MediaSet mediaSet = (MediaSet) manager.getMediaObject(path);
-            if (mediaSet instanceof LocalAlbum) {
-                if (entry.relativePath != null && entry.relativePath.length() > 0) {
-                    // update entry using relative path + external storage path
-                    updateEntryUsingRelativePath(entry, dbHelper);
-                } else {
-                    int bucketId = Integer.parseInt(path.getSuffix());
-                    localEntries.put(bucketId, entry);
-                }
-            }
-        }
-        if (!localEntries.isEmpty()) migrateLocalEntries(context, localEntries, dbHelper);
-    }
-
-    private static void migrateLocalEntries(Context context,
-            HashMap<Integer, Entry> entries, WidgetDatabaseHelper dbHelper) {
-        SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
-        String oldExtPath = prefs.getString(KEY_EXT_PATH, null);
-        if (oldExtPath != null) {
-            migrateLocalEntries(entries, dbHelper, oldExtPath);
-            return;
-        }
-        // If old external storage path is unknown, it could be either Pre-JB or JB version
-        // we need to try both.
-        migrateLocalEntries(entries, dbHelper, PRE_JB_EXT_PATH);
-        if (!entries.isEmpty() &&
-                Build.VERSION.SDK_INT > ApiHelper.VERSION_CODES.JELLY_BEAN) {
-            migrateLocalEntries(entries, dbHelper, JB_EXT_PATH);
-        }
-    }
-
-    private static void migrateLocalEntries(HashMap<Integer, Entry> entries,
-             WidgetDatabaseHelper dbHelper, String oldExtPath) {
-        File root = Environment.getExternalStorageDirectory();
-        // check the DCIM directory first; this should take care of 99% use cases
-        updatePath(new File(root, "DCIM"), entries, dbHelper, oldExtPath);
-        // check other directories if DCIM doesn't cut it
-        if (!entries.isEmpty()) updatePath(root, entries, dbHelper, oldExtPath);
-    }
-    private static void updatePath(File root, HashMap<Integer, Entry> entries,
-            WidgetDatabaseHelper dbHelper, String oldExtStorage) {
-        File[] files = root.listFiles();
-        if (files != null) {
-            for (File file : files) {
-                if (file.isDirectory() && !entries.isEmpty()) {
-                    String path = file.getAbsolutePath();
-                    String oldPath = oldExtStorage + path.substring(RELATIVE_PATH_START);
-                    int oldBucketId = GalleryUtils.getBucketId(oldPath);
-                    Entry entry = entries.remove(oldBucketId);
-                    if (entry != null) {
-                        int newBucketId = GalleryUtils.getBucketId(path);
-                        String newAlbumPath = Path.fromString(entry.albumPath)
-                                .getParent()
-                                .getChild(newBucketId)
-                                .toString();
-                        Log.d(TAG, "migrate from " + entry.albumPath + " to " + newAlbumPath);
-                        entry.albumPath = newAlbumPath;
-                        // update entry's relative path
-                        entry.relativePath = path.substring(RELATIVE_PATH_START);
-                        dbHelper.updateEntry(entry);
-                    }
-                    updatePath(file, entries, dbHelper, oldExtStorage); // recursion
-                }
-            }
-        }
-    }
-
-    private static void updateEntryUsingRelativePath(Entry entry, WidgetDatabaseHelper dbHelper) {
-        String newPath = NEW_EXT_PATH + entry.relativePath;
-        int newBucketId = GalleryUtils.getBucketId(newPath);
-        String newAlbumPath = Path.fromString(entry.albumPath)
-                .getParent()
-                .getChild(newBucketId)
-                .toString();
-        entry.albumPath = newAlbumPath;
-        dbHelper.updateEntry(entry);
-    }
-}
diff --git a/src/com/android/gallery3d/provider/GalleryProvider.java b/src/com/android/gallery3d/provider/GalleryProvider.java
deleted file mode 100644
index d6c7ccd..0000000
--- a/src/com/android/gallery3d/provider/GalleryProvider.java
+++ /dev/null
@@ -1,228 +0,0 @@
-/*
- * Copyright (C) 2009 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.gallery3d.provider;
-
-import android.content.ContentProvider;
-import android.content.ContentValues;
-import android.content.Context;
-import android.database.Cursor;
-import android.database.MatrixCursor;
-import android.net.Uri;
-import android.os.AsyncTask;
-import android.os.Binder;
-import android.os.ParcelFileDescriptor;
-import android.provider.MediaStore.Images.ImageColumns;
-import android.util.Log;
-
-import com.android.gallery3d.app.GalleryApp;
-import com.android.gallery3d.common.AsyncTaskUtil;
-import com.android.gallery3d.common.Utils;
-import com.android.gallery3d.data.DataManager;
-import com.android.gallery3d.data.MediaItem;
-import com.android.gallery3d.data.MediaObject;
-import com.android.gallery3d.data.Path;
-import com.android.gallery3d.picasasource.PicasaSource;
-import com.android.gallery3d.util.GalleryUtils;
-
-import java.io.FileNotFoundException;
-import java.io.IOException;
-
-public class GalleryProvider extends ContentProvider {
-    private static final String TAG = "GalleryProvider";
-
-    public static final String AUTHORITY = "com.android.gallery3d.provider";
-    public static final Uri BASE_URI = Uri.parse("content://" + AUTHORITY);
-
-    public static interface PicasaColumns {
-        public static final String USER_ACCOUNT = "user_account";
-        public static final String PICASA_ID = "picasa_id";
-    }
-
-    private static final String[] SUPPORTED_PICASA_COLUMNS = {
-            PicasaColumns.USER_ACCOUNT,
-            PicasaColumns.PICASA_ID,
-            ImageColumns.DISPLAY_NAME,
-            ImageColumns.SIZE,
-            ImageColumns.MIME_TYPE,
-            ImageColumns.DATE_TAKEN,
-            ImageColumns.LATITUDE,
-            ImageColumns.LONGITUDE,
-            ImageColumns.ORIENTATION};
-
-    private DataManager mDataManager;
-    private static Uri sBaseUri;
-
-    public static String getAuthority(Context context) {
-        return context.getPackageName() + ".provider";
-    }
-
-    public static Uri getUriFor(Context context, Path path) {
-        if (sBaseUri == null) {
-            sBaseUri = Uri.parse("content://" + context.getPackageName() + ".provider");
-        }
-        return sBaseUri.buildUpon()
-                .appendEncodedPath(path.toString().substring(1)) // ignore the leading '/'
-                .build();
-    }
-
-    @Override
-    public int delete(Uri uri, String selection, String[] selectionArgs) {
-        throw new UnsupportedOperationException();
-    }
-
-    // TODO: consider concurrent access
-    @Override
-    public String getType(Uri uri) {
-        long token = Binder.clearCallingIdentity();
-        try {
-            Path path = Path.fromString(uri.getPath());
-            MediaItem item = (MediaItem) mDataManager.getMediaObject(path);
-            return item != null ? item.getMimeType() : null;
-        } finally {
-            Binder.restoreCallingIdentity(token);
-        }
-    }
-
-    @Override
-    public Uri insert(Uri uri, ContentValues values) {
-        throw new UnsupportedOperationException();
-    }
-
-    @Override
-    public boolean onCreate() {
-        GalleryApp app = (GalleryApp) getContext().getApplicationContext();
-        mDataManager = app.getDataManager();
-        return true;
-    }
-
-    // TODO: consider concurrent access
-    @Override
-    public Cursor query(Uri uri, String[] projection,
-            String selection, String[] selectionArgs, String sortOrder) {
-        long token = Binder.clearCallingIdentity();
-        try {
-            Path path = Path.fromString(uri.getPath());
-            MediaObject object = mDataManager.getMediaObject(path);
-            if (object == null) {
-                Log.w(TAG, "cannot find: " + uri);
-                return null;
-            }
-            if (PicasaSource.isPicasaImage(object)) {
-                return queryPicasaItem(object,
-                        projection, selection, selectionArgs, sortOrder);
-            } else {
-                    return null;
-            }
-        } finally {
-            Binder.restoreCallingIdentity(token);
-        }
-    }
-
-    private Cursor queryPicasaItem(MediaObject image, String[] projection,
-            String selection, String[] selectionArgs, String sortOrder) {
-        if (projection == null) projection = SUPPORTED_PICASA_COLUMNS;
-        Object[] columnValues = new Object[projection.length];
-        double latitude = PicasaSource.getLatitude(image);
-        double longitude = PicasaSource.getLongitude(image);
-        boolean isValidLatlong = GalleryUtils.isValidLocation(latitude, longitude);
-
-        for (int i = 0, n = projection.length; i < n; ++i) {
-            String column = projection[i];
-            if (PicasaColumns.USER_ACCOUNT.equals(column)) {
-                columnValues[i] = PicasaSource.getUserAccount(getContext(), image);
-            } else if (PicasaColumns.PICASA_ID.equals(column)) {
-                columnValues[i] = PicasaSource.getPicasaId(image);
-            } else if (ImageColumns.DISPLAY_NAME.equals(column)) {
-                columnValues[i] = PicasaSource.getImageTitle(image);
-            } else if (ImageColumns.SIZE.equals(column)){
-                columnValues[i] = PicasaSource.getImageSize(image);
-            } else if (ImageColumns.MIME_TYPE.equals(column)) {
-                columnValues[i] = PicasaSource.getContentType(image);
-            } else if (ImageColumns.DATE_TAKEN.equals(column)) {
-                columnValues[i] = PicasaSource.getDateTaken(image);
-            } else if (ImageColumns.LATITUDE.equals(column)) {
-                columnValues[i] = isValidLatlong ? latitude : null;
-            } else if (ImageColumns.LONGITUDE.equals(column)) {
-                columnValues[i] = isValidLatlong ? longitude : null;
-            } else if (ImageColumns.ORIENTATION.equals(column)) {
-                columnValues[i] = PicasaSource.getRotation(image);
-            } else {
-                Log.w(TAG, "unsupported column: " + column);
-            }
-        }
-        MatrixCursor cursor = new MatrixCursor(projection);
-        cursor.addRow(columnValues);
-        return cursor;
-    }
-
-    @Override
-    public ParcelFileDescriptor openFile(Uri uri, String mode)
-            throws FileNotFoundException {
-        long token = Binder.clearCallingIdentity();
-        try {
-            if (mode.contains("w")) {
-                throw new FileNotFoundException("cannot open file for write");
-            }
-            Path path = Path.fromString(uri.getPath());
-            MediaObject object = mDataManager.getMediaObject(path);
-            if (object == null) {
-                throw new FileNotFoundException(uri.toString());
-            }
-            if (PicasaSource.isPicasaImage(object)) {
-                return PicasaSource.openFile(getContext(), object, mode);
-            } else {
-                throw new FileNotFoundException("unspported type: " + object);
-            }
-        } finally {
-            Binder.restoreCallingIdentity(token);
-        }
-    }
-
-    @Override
-    public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
-        throw new UnsupportedOperationException();
-    }
-
-    private static interface PipeDataWriter<T> {
-        void writeDataToPipe(ParcelFileDescriptor output, T args);
-    }
-
-    // Modified from ContentProvider.openPipeHelper. We are target at API LEVEL 10.
-    // But openPipeHelper is available in API LEVEL 11.
-    private static <T> ParcelFileDescriptor openPipeHelper(
-            final T args, final PipeDataWriter<T> func) throws FileNotFoundException {
-        try {
-            final ParcelFileDescriptor[] pipe = ParcelFileDescriptor.createPipe();
-            AsyncTask<Object, Object, Object> task = new AsyncTask<Object, Object, Object>() {
-                @Override
-                protected Object doInBackground(Object... params) {
-                    try {
-                        func.writeDataToPipe(pipe[1], args);
-                        return null;
-                    } finally {
-                        Utils.closeSilently(pipe[1]);
-                    }
-                }
-            };
-            AsyncTaskUtil.executeInParallel(task, (Object[]) null);
-            return pipe[0];
-        } catch (IOException e) {
-            throw new FileNotFoundException("failure making pipe");
-        }
-    }
-
-}
diff --git a/src/com/android/gallery3d/ui/AbstractSlotRenderer.java b/src/com/android/gallery3d/ui/AbstractSlotRenderer.java
deleted file mode 100644
index 729439d..0000000
--- a/src/com/android/gallery3d/ui/AbstractSlotRenderer.java
+++ /dev/null
@@ -1,119 +0,0 @@
-/*
- * 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.gallery3d.ui;
-
-import android.content.Context;
-import android.graphics.Rect;
-
-import com.android.gallery3d.R;
-import com.android.gallery3d.glrenderer.FadeOutTexture;
-import com.android.gallery3d.glrenderer.GLCanvas;
-import com.android.gallery3d.glrenderer.NinePatchTexture;
-import com.android.gallery3d.glrenderer.ResourceTexture;
-import com.android.gallery3d.glrenderer.Texture;
-
-public abstract class AbstractSlotRenderer implements SlotView.SlotRenderer {
-
-    private final ResourceTexture mVideoOverlay;
-    private final ResourceTexture mVideoPlayIcon;
-    private final ResourceTexture mPanoramaIcon;
-    private final NinePatchTexture mFramePressed;
-    private final NinePatchTexture mFrameSelected;
-    private FadeOutTexture mFramePressedUp;
-
-    protected AbstractSlotRenderer(Context context) {
-        mVideoOverlay = new ResourceTexture(context, R.drawable.ic_video_thumb);
-        mVideoPlayIcon = new ResourceTexture(context, R.drawable.ic_gallery_play);
-        mPanoramaIcon = new ResourceTexture(context, R.drawable.ic_360pano_holo_light);
-        mFramePressed = new NinePatchTexture(context, R.drawable.grid_pressed);
-        mFrameSelected = new NinePatchTexture(context, R.drawable.grid_selected);
-    }
-
-    protected void drawContent(GLCanvas canvas,
-            Texture content, int width, int height, int rotation) {
-        canvas.save(GLCanvas.SAVE_FLAG_MATRIX);
-
-        // The content is always rendered in to the largest square that fits
-        // inside the slot, aligned to the top of the slot.
-        width = height = Math.min(width, height);
-        if (rotation != 0) {
-            canvas.translate(width / 2, height / 2);
-            canvas.rotate(rotation, 0, 0, 1);
-            canvas.translate(-width / 2, -height / 2);
-        }
-
-        // Fit the content into the box
-        float scale = Math.min(
-                (float) width / content.getWidth(),
-                (float) height / content.getHeight());
-        canvas.scale(scale, scale, 1);
-        content.draw(canvas, 0, 0);
-
-        canvas.restore();
-    }
-
-    protected void drawVideoOverlay(GLCanvas canvas, int width, int height) {
-        // Scale the video overlay to the height of the thumbnail and put it
-        // on the left side.
-        ResourceTexture v = mVideoOverlay;
-        float scale = (float) height / v.getHeight();
-        int w = Math.round(scale * v.getWidth());
-        int h = Math.round(scale * v.getHeight());
-        v.draw(canvas, 0, 0, w, h);
-
-        int s = Math.min(width, height) / 6;
-        mVideoPlayIcon.draw(canvas, (width - s) / 2, (height - s) / 2, s, s);
-    }
-
-    protected void drawPanoramaIcon(GLCanvas canvas, int width, int height) {
-        int iconSize = Math.min(width, height) / 6;
-        mPanoramaIcon.draw(canvas, (width - iconSize) / 2, (height - iconSize) / 2,
-                iconSize, iconSize);
-    }
-
-    protected boolean isPressedUpFrameFinished() {
-        if (mFramePressedUp != null) {
-            if (mFramePressedUp.isAnimating()) {
-                return false;
-            } else {
-                mFramePressedUp = null;
-            }
-        }
-        return true;
-    }
-
-    protected void drawPressedUpFrame(GLCanvas canvas, int width, int height) {
-        if (mFramePressedUp == null) {
-            mFramePressedUp = new FadeOutTexture(mFramePressed);
-        }
-        drawFrame(canvas, mFramePressed.getPaddings(), mFramePressedUp, 0, 0, width, height);
-    }
-
-    protected void drawPressedFrame(GLCanvas canvas, int width, int height) {
-        drawFrame(canvas, mFramePressed.getPaddings(), mFramePressed, 0, 0, width, height);
-    }
-
-    protected void drawSelectedFrame(GLCanvas canvas, int width, int height) {
-        drawFrame(canvas, mFrameSelected.getPaddings(), mFrameSelected, 0, 0, width, height);
-    }
-
-    protected static void drawFrame(GLCanvas canvas, Rect padding, Texture frame,
-            int x, int y, int width, int height) {
-        frame.draw(canvas, x - padding.left, y - padding.top, width + padding.left + padding.right,
-                 height + padding.top + padding.bottom);
-    }
-}
diff --git a/src/com/android/gallery3d/ui/ActionModeHandler.java b/src/com/android/gallery3d/ui/ActionModeHandler.java
deleted file mode 100644
index 6b4f103..0000000
--- a/src/com/android/gallery3d/ui/ActionModeHandler.java
+++ /dev/null
@@ -1,501 +0,0 @@
-/*
- * Copyright (C) 2010 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.gallery3d.ui;
-
-import android.annotation.TargetApi;
-import android.app.Activity;
-import android.content.Intent;
-import android.net.Uri;
-import android.nfc.NfcAdapter;
-import android.os.Handler;
-import android.view.ActionMode;
-import android.view.ActionMode.Callback;
-import android.view.LayoutInflater;
-import android.view.Menu;
-import android.view.MenuItem;
-import android.view.View;
-import android.widget.Button;
-import android.widget.ShareActionProvider;
-import android.widget.ShareActionProvider.OnShareTargetSelectedListener;
-
-import com.android.gallery3d.R;
-import com.android.gallery3d.app.AbstractGalleryActivity;
-import com.android.gallery3d.common.ApiHelper;
-import com.android.gallery3d.common.Utils;
-import com.android.gallery3d.data.DataManager;
-import com.android.gallery3d.data.MediaObject;
-import com.android.gallery3d.data.MediaObject.PanoramaSupportCallback;
-import com.android.gallery3d.data.Path;
-import com.android.gallery3d.ui.MenuExecutor.ProgressListener;
-import com.android.gallery3d.util.Future;
-import com.android.gallery3d.util.GalleryUtils;
-import com.android.gallery3d.util.ThreadPool.Job;
-import com.android.gallery3d.util.ThreadPool.JobContext;
-
-import java.util.ArrayList;
-
-public class ActionModeHandler implements Callback, PopupList.OnPopupItemClickListener {
-
-    @SuppressWarnings("unused")
-    private static final String TAG = "ActionModeHandler";
-
-    private static final int MAX_SELECTED_ITEMS_FOR_SHARE_INTENT = 300;
-    private static final int MAX_SELECTED_ITEMS_FOR_PANORAMA_SHARE_INTENT = 10;
-
-    private static final int SUPPORT_MULTIPLE_MASK = MediaObject.SUPPORT_DELETE
-            | MediaObject.SUPPORT_ROTATE | MediaObject.SUPPORT_SHARE
-            | MediaObject.SUPPORT_CACHE;
-
-    public interface ActionModeListener {
-        public boolean onActionItemClicked(MenuItem item);
-    }
-
-    private final AbstractGalleryActivity mActivity;
-    private final MenuExecutor mMenuExecutor;
-    private final SelectionManager mSelectionManager;
-    private final NfcAdapter mNfcAdapter;
-    private Menu mMenu;
-    private MenuItem mSharePanoramaMenuItem;
-    private MenuItem mShareMenuItem;
-    private ShareActionProvider mSharePanoramaActionProvider;
-    private ShareActionProvider mShareActionProvider;
-    private SelectionMenu mSelectionMenu;
-    private ActionModeListener mListener;
-    private Future<?> mMenuTask;
-    private final Handler mMainHandler;
-    private ActionMode mActionMode;
-
-    private static class GetAllPanoramaSupports implements PanoramaSupportCallback {
-        private int mNumInfoRequired;
-        private JobContext mJobContext;
-        public boolean mAllPanoramas = true;
-        public boolean mAllPanorama360 = true;
-        public boolean mHasPanorama360 = false;
-        private Object mLock = new Object();
-
-        public GetAllPanoramaSupports(ArrayList<MediaObject> mediaObjects, JobContext jc) {
-            mJobContext = jc;
-            mNumInfoRequired = mediaObjects.size();
-            for (MediaObject mediaObject : mediaObjects) {
-                mediaObject.getPanoramaSupport(this);
-            }
-        }
-
-        @Override
-        public void panoramaInfoAvailable(MediaObject mediaObject, boolean isPanorama,
-                boolean isPanorama360) {
-            synchronized (mLock) {
-                mNumInfoRequired--;
-                mAllPanoramas = isPanorama && mAllPanoramas;
-                mAllPanorama360 = isPanorama360 && mAllPanorama360;
-                mHasPanorama360 = mHasPanorama360 || isPanorama360;
-                if (mNumInfoRequired == 0 || mJobContext.isCancelled()) {
-                    mLock.notifyAll();
-                }
-            }
-        }
-
-        public void waitForPanoramaSupport() {
-            synchronized (mLock) {
-                while (mNumInfoRequired != 0 && !mJobContext.isCancelled()) {
-                    try {
-                        mLock.wait();
-                    } catch (InterruptedException e) {
-                        // May be a cancelled job context
-                    }
-                }
-            }
-        }
-    }
-
-    public ActionModeHandler(
-            AbstractGalleryActivity activity, SelectionManager selectionManager) {
-        mActivity = Utils.checkNotNull(activity);
-        mSelectionManager = Utils.checkNotNull(selectionManager);
-        mMenuExecutor = new MenuExecutor(activity, selectionManager);
-        mMainHandler = new Handler(activity.getMainLooper());
-        mNfcAdapter = NfcAdapter.getDefaultAdapter(mActivity.getAndroidContext());
-    }
-
-    public void startActionMode() {
-        Activity a = mActivity;
-        mActionMode = a.startActionMode(this);
-        View customView = LayoutInflater.from(a).inflate(
-                R.layout.action_mode, null);
-        mActionMode.setCustomView(customView);
-        mSelectionMenu = new SelectionMenu(a,
-                (Button) customView.findViewById(R.id.selection_menu), this);
-        updateSelectionMenu();
-    }
-
-    public void finishActionMode() {
-        mActionMode.finish();
-    }
-
-    public void setTitle(String title) {
-        mSelectionMenu.setTitle(title);
-    }
-
-    public void setActionModeListener(ActionModeListener listener) {
-        mListener = listener;
-    }
-
-    private WakeLockHoldingProgressListener mDeleteProgressListener;
-
-    @Override
-    public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
-        GLRoot root = mActivity.getGLRoot();
-        root.lockRenderThread();
-        try {
-            boolean result;
-            // Give listener a chance to process this command before it's routed to
-            // ActionModeHandler, which handles command only based on the action id.
-            // Sometimes the listener may have more background information to handle
-            // an action command.
-            if (mListener != null) {
-                result = mListener.onActionItemClicked(item);
-                if (result) {
-                    mSelectionManager.leaveSelectionMode();
-                    return result;
-                }
-            }
-            ProgressListener listener = null;
-            String confirmMsg = null;
-            int action = item.getItemId();
-            if (action == R.id.action_delete) {
-                confirmMsg = mActivity.getResources().getQuantityString(
-                        R.plurals.delete_selection, mSelectionManager.getSelectedCount());
-                if (mDeleteProgressListener == null) {
-                    mDeleteProgressListener = new WakeLockHoldingProgressListener(mActivity,
-                            "Gallery Delete Progress Listener");
-                }
-                listener = mDeleteProgressListener;
-            }
-            mMenuExecutor.onMenuClicked(item, confirmMsg, listener);
-        } finally {
-            root.unlockRenderThread();
-        }
-        return true;
-    }
-
-    @Override
-    public boolean onPopupItemClick(int itemId) {
-        GLRoot root = mActivity.getGLRoot();
-        root.lockRenderThread();
-        try {
-            if (itemId == R.id.action_select_all) {
-                updateSupportedOperation();
-                mMenuExecutor.onMenuClicked(itemId, null, false, true);
-            }
-            return true;
-        } finally {
-            root.unlockRenderThread();
-        }
-    }
-
-    private void updateSelectionMenu() {
-        // update title
-        int count = mSelectionManager.getSelectedCount();
-        String format = mActivity.getResources().getQuantityString(
-                R.plurals.number_of_items_selected, count);
-        setTitle(String.format(format, count));
-
-        // For clients who call SelectionManager.selectAll() directly, we need to ensure the
-        // menu status is consistent with selection manager.
-        mSelectionMenu.updateSelectAllMode(mSelectionManager.inSelectAllMode());
-    }
-
-    private final OnShareTargetSelectedListener mShareTargetSelectedListener =
-            new OnShareTargetSelectedListener() {
-        @Override
-        public boolean onShareTargetSelected(ShareActionProvider source, Intent intent) {
-            mSelectionManager.leaveSelectionMode();
-            return false;
-        }
-    };
-
-    @Override
-    public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
-        return false;
-    }
-
-    @Override
-    public boolean onCreateActionMode(ActionMode mode, Menu menu) {
-        mode.getMenuInflater().inflate(R.menu.operation, menu);
-
-        mMenu = menu;
-        mSharePanoramaMenuItem = menu.findItem(R.id.action_share_panorama);
-        if (mSharePanoramaMenuItem != null) {
-            mSharePanoramaActionProvider = (ShareActionProvider) mSharePanoramaMenuItem
-                .getActionProvider();
-            mSharePanoramaActionProvider.setOnShareTargetSelectedListener(
-                    mShareTargetSelectedListener);
-            mSharePanoramaActionProvider.setShareHistoryFileName("panorama_share_history.xml");
-        }
-        mShareMenuItem = menu.findItem(R.id.action_share);
-        if (mShareMenuItem != null) {
-            mShareActionProvider = (ShareActionProvider) mShareMenuItem
-                .getActionProvider();
-            mShareActionProvider.setOnShareTargetSelectedListener(
-                    mShareTargetSelectedListener);
-            mShareActionProvider.setShareHistoryFileName("share_history.xml");
-        }
-        return true;
-    }
-
-    @Override
-    public void onDestroyActionMode(ActionMode mode) {
-        mSelectionManager.leaveSelectionMode();
-    }
-
-    private ArrayList<MediaObject> getSelectedMediaObjects(JobContext jc) {
-        ArrayList<Path> unexpandedPaths = mSelectionManager.getSelected(false);
-        if (unexpandedPaths.isEmpty()) {
-            // This happens when starting selection mode from overflow menu
-            // (instead of long press a media object)
-            return null;
-        }
-        ArrayList<MediaObject> selected = new ArrayList<MediaObject>();
-        DataManager manager = mActivity.getDataManager();
-        for (Path path : unexpandedPaths) {
-            if (jc.isCancelled()) {
-                return null;
-            }
-            selected.add(manager.getMediaObject(path));
-        }
-
-        return selected;
-    }
-    // Menu options are determined by selection set itself.
-    // We cannot expand it because MenuExecuter executes it based on
-    // the selection set instead of the expanded result.
-    // e.g. LocalImage can be rotated but collections of them (LocalAlbum) can't.
-    private int computeMenuOptions(ArrayList<MediaObject> selected) {
-        int operation = MediaObject.SUPPORT_ALL;
-        int type = 0;
-        for (MediaObject mediaObject: selected) {
-            int support = mediaObject.getSupportedOperations();
-            type |= mediaObject.getMediaType();
-            operation &= support;
-        }
-
-        switch (selected.size()) {
-            case 1:
-                final String mimeType = MenuExecutor.getMimeType(type);
-                if (!GalleryUtils.isEditorAvailable(mActivity, mimeType)) {
-                    operation &= ~MediaObject.SUPPORT_EDIT;
-                }
-                break;
-            default:
-                operation &= SUPPORT_MULTIPLE_MASK;
-        }
-
-        return operation;
-    }
-
-    @TargetApi(ApiHelper.VERSION_CODES.JELLY_BEAN)
-    private void setNfcBeamPushUris(Uri[] uris) {
-        if (mNfcAdapter != null && ApiHelper.HAS_SET_BEAM_PUSH_URIS) {
-            mNfcAdapter.setBeamPushUrisCallback(null, mActivity);
-            mNfcAdapter.setBeamPushUris(uris, mActivity);
-        }
-    }
-
-    // Share intent needs to expand the selection set so we can get URI of
-    // each media item
-    private Intent computePanoramaSharingIntent(JobContext jc, int maxItems) {
-        ArrayList<Path> expandedPaths = mSelectionManager.getSelected(true, maxItems);
-        if (expandedPaths == null || expandedPaths.size() == 0) {
-            return new Intent();
-        }
-        final ArrayList<Uri> uris = new ArrayList<Uri>();
-        DataManager manager = mActivity.getDataManager();
-        final Intent intent = new Intent();
-        for (Path path : expandedPaths) {
-            if (jc.isCancelled()) return null;
-            uris.add(manager.getContentUri(path));
-        }
-
-        final int size = uris.size();
-        if (size > 0) {
-            if (size > 1) {
-                intent.setAction(Intent.ACTION_SEND_MULTIPLE);
-                intent.setType(GalleryUtils.MIME_TYPE_PANORAMA360);
-                intent.putParcelableArrayListExtra(Intent.EXTRA_STREAM, uris);
-            } else {
-                intent.setAction(Intent.ACTION_SEND);
-                intent.setType(GalleryUtils.MIME_TYPE_PANORAMA360);
-                intent.putExtra(Intent.EXTRA_STREAM, uris.get(0));
-            }
-            intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
-        }
-
-        return intent;
-    }
-
-    private Intent computeSharingIntent(JobContext jc, int maxItems) {
-        ArrayList<Path> expandedPaths = mSelectionManager.getSelected(true, maxItems);
-        if (expandedPaths == null || expandedPaths.size() == 0) {
-            setNfcBeamPushUris(null);
-            return new Intent();
-        }
-        final ArrayList<Uri> uris = new ArrayList<Uri>();
-        DataManager manager = mActivity.getDataManager();
-        int type = 0;
-        final Intent intent = new Intent();
-        for (Path path : expandedPaths) {
-            if (jc.isCancelled()) return null;
-            int support = manager.getSupportedOperations(path);
-            type |= manager.getMediaType(path);
-
-            if ((support & MediaObject.SUPPORT_SHARE) != 0) {
-                uris.add(manager.getContentUri(path));
-            }
-        }
-
-        final int size = uris.size();
-        if (size > 0) {
-            final String mimeType = MenuExecutor.getMimeType(type);
-            if (size > 1) {
-                intent.setAction(Intent.ACTION_SEND_MULTIPLE).setType(mimeType);
-                intent.putParcelableArrayListExtra(Intent.EXTRA_STREAM, uris);
-            } else {
-                intent.setAction(Intent.ACTION_SEND).setType(mimeType);
-                intent.putExtra(Intent.EXTRA_STREAM, uris.get(0));
-            }
-            intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
-            setNfcBeamPushUris(uris.toArray(new Uri[uris.size()]));
-        } else {
-            setNfcBeamPushUris(null);
-        }
-
-        return intent;
-    }
-
-    public void updateSupportedOperation(Path path, boolean selected) {
-        // TODO: We need to improve the performance
-        updateSupportedOperation();
-    }
-
-    public void updateSupportedOperation() {
-        // Interrupt previous unfinished task, mMenuTask is only accessed in main thread
-        if (mMenuTask != null) mMenuTask.cancel();
-
-        updateSelectionMenu();
-
-        // Disable share actions until share intent is in good shape
-        if (mSharePanoramaMenuItem != null) mSharePanoramaMenuItem.setEnabled(false);
-        if (mShareMenuItem != null) mShareMenuItem.setEnabled(false);
-
-        // Generate sharing intent and update supported operations in the background
-        // The task can take a long time and be canceled in the mean time.
-        mMenuTask = mActivity.getThreadPool().submit(new Job<Void>() {
-            @Override
-            public Void run(final JobContext jc) {
-                // Pass1: Deal with unexpanded media object list for menu operation.
-                ArrayList<MediaObject> selected = getSelectedMediaObjects(jc);
-                if (selected == null) {
-                    mMainHandler.post(new Runnable() {
-                        @Override
-                        public void run() {
-                            mMenuTask = null;
-                            if (jc.isCancelled()) return;
-                            // Disable all the operations when no item is selected
-                            MenuExecutor.updateMenuOperation(mMenu, 0);
-                        }
-                    });
-                    return null;
-                }
-                final int operation = computeMenuOptions(selected);
-                if (jc.isCancelled()) {
-                    return null;
-                }
-                int numSelected = selected.size();
-                final boolean canSharePanoramas =
-                        numSelected < MAX_SELECTED_ITEMS_FOR_PANORAMA_SHARE_INTENT;
-                final boolean canShare =
-                        numSelected < MAX_SELECTED_ITEMS_FOR_SHARE_INTENT;
-
-                final GetAllPanoramaSupports supportCallback = canSharePanoramas ?
-                        new GetAllPanoramaSupports(selected, jc)
-                        : null;
-
-                // Pass2: Deal with expanded media object list for sharing operation.
-                final Intent share_panorama_intent = canSharePanoramas ?
-                        computePanoramaSharingIntent(jc, MAX_SELECTED_ITEMS_FOR_PANORAMA_SHARE_INTENT)
-                        : new Intent();
-                final Intent share_intent = canShare ?
-                        computeSharingIntent(jc, MAX_SELECTED_ITEMS_FOR_SHARE_INTENT)
-                        : new Intent();
-
-                if (canSharePanoramas) {
-                    supportCallback.waitForPanoramaSupport();
-                }
-                if (jc.isCancelled()) {
-                    return null;
-                }
-                mMainHandler.post(new Runnable() {
-                    @Override
-                    public void run() {
-                        mMenuTask = null;
-                        if (jc.isCancelled()) return;
-                        MenuExecutor.updateMenuOperation(mMenu, operation);
-                        MenuExecutor.updateMenuForPanorama(mMenu,
-                                canSharePanoramas && supportCallback.mAllPanorama360,
-                                canSharePanoramas && supportCallback.mHasPanorama360);
-                        if (mSharePanoramaMenuItem != null) {
-                            mSharePanoramaMenuItem.setEnabled(true);
-                            if (canSharePanoramas && supportCallback.mAllPanorama360) {
-                                mShareMenuItem.setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER);
-                                mShareMenuItem.setTitle(
-                                    mActivity.getResources().getString(R.string.share_as_photo));
-                            } else {
-                                mSharePanoramaMenuItem.setVisible(false);
-                                mShareMenuItem.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
-                                mShareMenuItem.setTitle(
-                                    mActivity.getResources().getString(R.string.share));
-                            }
-                            mSharePanoramaActionProvider.setShareIntent(share_panorama_intent);
-                        }
-                        if (mShareMenuItem != null) {
-                            mShareMenuItem.setEnabled(canShare);
-                            mShareActionProvider.setShareIntent(share_intent);
-                        }
-                    }
-                });
-                return null;
-            }
-        });
-    }
-
-    public void pause() {
-        if (mMenuTask != null) {
-            mMenuTask.cancel();
-            mMenuTask = null;
-        }
-        mMenuExecutor.pause();
-    }
-
-    public void destroy() {
-        mMenuExecutor.destroy();
-    }
-
-    public void resume() {
-        if (mSelectionManager.inSelectionMode()) updateSupportedOperation();
-        mMenuExecutor.resume();
-    }
-}
diff --git a/src/com/android/gallery3d/ui/AlbumLabelMaker.java b/src/com/android/gallery3d/ui/AlbumLabelMaker.java
deleted file mode 100644
index da1cac0..0000000
--- a/src/com/android/gallery3d/ui/AlbumLabelMaker.java
+++ /dev/null
@@ -1,206 +0,0 @@
-/*
- * 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.gallery3d.ui;
-
-import android.content.Context;
-import android.graphics.Bitmap;
-import android.graphics.Bitmap.Config;
-import android.graphics.BitmapFactory;
-import android.graphics.Canvas;
-import android.graphics.PorterDuff;
-import android.graphics.Typeface;
-import android.text.TextPaint;
-import android.text.TextUtils;
-
-import com.android.gallery3d.R;
-import com.android.gallery3d.data.DataSourceType;
-import com.android.photos.data.GalleryBitmapPool;
-import com.android.gallery3d.util.ThreadPool;
-import com.android.gallery3d.util.ThreadPool.JobContext;
-
-public class AlbumLabelMaker {
-    private static final int BORDER_SIZE = 0;
-
-    private final AlbumSetSlotRenderer.LabelSpec mSpec;
-    private final TextPaint mTitlePaint;
-    private final TextPaint mCountPaint;
-    private final Context mContext;
-
-    private int mLabelWidth;
-    private int mBitmapWidth;
-    private int mBitmapHeight;
-
-    private final LazyLoadedBitmap mLocalSetIcon;
-    private final LazyLoadedBitmap mPicasaIcon;
-    private final LazyLoadedBitmap mCameraIcon;
-
-    public AlbumLabelMaker(Context context, AlbumSetSlotRenderer.LabelSpec spec) {
-        mContext = context;
-        mSpec = spec;
-        mTitlePaint = getTextPaint(spec.titleFontSize, spec.titleColor, false);
-        mCountPaint = getTextPaint(spec.countFontSize, spec.countColor, false);
-
-        mLocalSetIcon = new LazyLoadedBitmap(R.drawable.frame_overlay_gallery_folder);
-        mPicasaIcon = new LazyLoadedBitmap(R.drawable.frame_overlay_gallery_picasa);
-        mCameraIcon = new LazyLoadedBitmap(R.drawable.frame_overlay_gallery_camera);
-    }
-
-    public static int getBorderSize() {
-        return BORDER_SIZE;
-    }
-
-    private Bitmap getOverlayAlbumIcon(int sourceType) {
-        switch (sourceType) {
-            case DataSourceType.TYPE_CAMERA:
-                return mCameraIcon.get();
-            case DataSourceType.TYPE_LOCAL:
-                return mLocalSetIcon.get();
-            case DataSourceType.TYPE_PICASA:
-                return mPicasaIcon.get();
-        }
-        return null;
-    }
-
-    private static TextPaint getTextPaint(int textSize, int color, boolean isBold) {
-        TextPaint paint = new TextPaint();
-        paint.setTextSize(textSize);
-        paint.setAntiAlias(true);
-        paint.setColor(color);
-        //paint.setShadowLayer(2f, 0f, 0f, Color.LTGRAY);
-        if (isBold) {
-            paint.setTypeface(Typeface.defaultFromStyle(Typeface.BOLD));
-        }
-        return paint;
-    }
-
-    private class LazyLoadedBitmap {
-        private Bitmap mBitmap;
-        private int mResId;
-
-        public LazyLoadedBitmap(int resId) {
-            mResId = resId;
-        }
-
-        public synchronized Bitmap get() {
-            if (mBitmap == null) {
-                BitmapFactory.Options options = new BitmapFactory.Options();
-                options.inPreferredConfig = Bitmap.Config.ARGB_8888;
-                mBitmap = BitmapFactory.decodeResource(
-                        mContext.getResources(), mResId, options);
-            }
-            return mBitmap;
-        }
-    }
-
-    public synchronized void setLabelWidth(int width) {
-        if (mLabelWidth == width) return;
-        mLabelWidth = width;
-        int borders = 2 * BORDER_SIZE;
-        mBitmapWidth = width + borders;
-        mBitmapHeight = mSpec.labelBackgroundHeight + borders;
-    }
-
-    public ThreadPool.Job<Bitmap> requestLabel(
-            String title, String count, int sourceType) {
-        return new AlbumLabelJob(title, count, sourceType);
-    }
-
-    static void drawText(Canvas canvas,
-            int x, int y, String text, int lengthLimit, TextPaint p) {
-        // The TextPaint cannot be used concurrently
-        synchronized (p) {
-            text = TextUtils.ellipsize(
-                    text, p, lengthLimit, TextUtils.TruncateAt.END).toString();
-            canvas.drawText(text, x, y - p.getFontMetricsInt().ascent, p);
-        }
-    }
-
-    private class AlbumLabelJob implements ThreadPool.Job<Bitmap> {
-        private final String mTitle;
-        private final String mCount;
-        private final int mSourceType;
-
-        public AlbumLabelJob(String title, String count, int sourceType) {
-            mTitle = title;
-            mCount = count;
-            mSourceType = sourceType;
-        }
-
-        @Override
-        public Bitmap run(JobContext jc) {
-            AlbumSetSlotRenderer.LabelSpec s = mSpec;
-
-            String title = mTitle;
-            String count = mCount;
-            Bitmap icon = getOverlayAlbumIcon(mSourceType);
-
-            Bitmap bitmap;
-            int labelWidth;
-
-            synchronized (this) {
-                labelWidth = mLabelWidth;
-                bitmap = GalleryBitmapPool.getInstance().get(mBitmapWidth, mBitmapHeight);
-            }
-
-            if (bitmap == null) {
-                int borders = 2 * BORDER_SIZE;
-                bitmap = Bitmap.createBitmap(labelWidth + borders,
-                        s.labelBackgroundHeight + borders, Config.ARGB_8888);
-            }
-
-            Canvas canvas = new Canvas(bitmap);
-            canvas.clipRect(BORDER_SIZE, BORDER_SIZE,
-                    bitmap.getWidth() - BORDER_SIZE,
-                    bitmap.getHeight() - BORDER_SIZE);
-            canvas.drawColor(mSpec.backgroundColor, PorterDuff.Mode.SRC);
-
-            canvas.translate(BORDER_SIZE, BORDER_SIZE);
-
-            // draw title
-            if (jc.isCancelled()) return null;
-            int x = s.leftMargin + s.iconSize;
-            // TODO: is the offset relevant in new reskin?
-            // int y = s.titleOffset;
-            int y = (s.labelBackgroundHeight - s.titleFontSize) / 2;
-            drawText(canvas, x, y, title, labelWidth - s.leftMargin - x - 
-                    s.titleRightMargin, mTitlePaint);
-
-            // draw count
-            if (jc.isCancelled()) return null;
-            x = labelWidth - s.titleRightMargin;
-            y = (s.labelBackgroundHeight - s.countFontSize) / 2;
-            drawText(canvas, x, y, count,
-                    labelWidth - x , mCountPaint);
-
-            // draw the icon
-            if (icon != null) {
-                if (jc.isCancelled()) return null;
-                float scale = (float) s.iconSize / icon.getWidth();
-                canvas.translate(s.leftMargin, (s.labelBackgroundHeight -
-                        Math.round(scale * icon.getHeight()))/2f);
-                canvas.scale(scale, scale);
-                canvas.drawBitmap(icon, 0, 0, null);
-            }
-
-            return bitmap;
-        }
-    }
-
-    public void recycleLabel(Bitmap label) {
-        GalleryBitmapPool.getInstance().put(label);
-    }
-}
diff --git a/src/com/android/gallery3d/ui/AlbumSetSlidingWindow.java b/src/com/android/gallery3d/ui/AlbumSetSlidingWindow.java
deleted file mode 100644
index 8149df4..0000000
--- a/src/com/android/gallery3d/ui/AlbumSetSlidingWindow.java
+++ /dev/null
@@ -1,549 +0,0 @@
-/*T
- * Copyright (C) 2010 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.gallery3d.ui;
-
-import android.graphics.Bitmap;
-import android.os.Message;
-
-import com.android.gallery3d.R;
-import com.android.gallery3d.app.AbstractGalleryActivity;
-import com.android.gallery3d.app.AlbumSetDataLoader;
-import com.android.gallery3d.common.Utils;
-import com.android.gallery3d.data.DataSourceType;
-import com.android.gallery3d.data.MediaItem;
-import com.android.gallery3d.data.MediaObject;
-import com.android.gallery3d.data.MediaSet;
-import com.android.gallery3d.data.Path;
-import com.android.gallery3d.glrenderer.BitmapTexture;
-import com.android.gallery3d.glrenderer.Texture;
-import com.android.gallery3d.glrenderer.TextureUploader;
-import com.android.gallery3d.glrenderer.TiledTexture;
-import com.android.gallery3d.util.Future;
-import com.android.gallery3d.util.FutureListener;
-import com.android.gallery3d.util.ThreadPool;
-
-public class AlbumSetSlidingWindow implements AlbumSetDataLoader.DataListener {
-    private static final String TAG = "AlbumSetSlidingWindow";
-    private static final int MSG_UPDATE_ALBUM_ENTRY = 1;
-
-    public static interface Listener {
-        public void onSizeChanged(int size);
-        public void onContentChanged();
-    }
-
-    private final AlbumSetDataLoader mSource;
-    private int mSize;
-
-    private int mContentStart = 0;
-    private int mContentEnd = 0;
-
-    private int mActiveStart = 0;
-    private int mActiveEnd = 0;
-
-    private Listener mListener;
-
-    private final AlbumSetEntry mData[];
-    private final SynchronizedHandler mHandler;
-    private final ThreadPool mThreadPool;
-    private final AlbumLabelMaker mLabelMaker;
-    private final String mLoadingText;
-
-    private final TiledTexture.Uploader mContentUploader;
-    private final TextureUploader mLabelUploader;
-
-    private int mActiveRequestCount = 0;
-    private boolean mIsActive = false;
-    private BitmapTexture mLoadingLabel;
-
-    private int mSlotWidth;
-
-    public static class AlbumSetEntry {
-        public MediaSet album;
-        public MediaItem coverItem;
-        public Texture content;
-        public BitmapTexture labelTexture;
-        public TiledTexture bitmapTexture;
-        public Path setPath;
-        public String title;
-        public int totalCount;
-        public int sourceType;
-        public int cacheFlag;
-        public int cacheStatus;
-        public int rotation;
-        public boolean isWaitLoadingDisplayed;
-        public long setDataVersion;
-        public long coverDataVersion;
-        private BitmapLoader labelLoader;
-        private BitmapLoader coverLoader;
-    }
-
-    public AlbumSetSlidingWindow(AbstractGalleryActivity activity,
-            AlbumSetDataLoader source, AlbumSetSlotRenderer.LabelSpec labelSpec, int cacheSize) {
-        source.setModelListener(this);
-        mSource = source;
-        mData = new AlbumSetEntry[cacheSize];
-        mSize = source.size();
-        mThreadPool = activity.getThreadPool();
-
-        mLabelMaker = new AlbumLabelMaker(activity.getAndroidContext(), labelSpec);
-        mLoadingText = activity.getAndroidContext().getString(R.string.loading);
-        mContentUploader = new TiledTexture.Uploader(activity.getGLRoot());
-        mLabelUploader = new TextureUploader(activity.getGLRoot());
-
-        mHandler = new SynchronizedHandler(activity.getGLRoot()) {
-            @Override
-            public void handleMessage(Message message) {
-                Utils.assertTrue(message.what == MSG_UPDATE_ALBUM_ENTRY);
-                ((EntryUpdater) message.obj).updateEntry();
-            }
-        };
-    }
-
-    public void setListener(Listener listener) {
-        mListener = listener;
-    }
-
-    public AlbumSetEntry get(int slotIndex) {
-        if (!isActiveSlot(slotIndex)) {
-            Utils.fail("invalid slot: %s outsides (%s, %s)",
-                    slotIndex, mActiveStart, mActiveEnd);
-        }
-        return mData[slotIndex % mData.length];
-    }
-
-    public int size() {
-        return mSize;
-    }
-
-    public boolean isActiveSlot(int slotIndex) {
-        return slotIndex >= mActiveStart && slotIndex < mActiveEnd;
-    }
-
-    private void setContentWindow(int contentStart, int contentEnd) {
-        if (contentStart == mContentStart && contentEnd == mContentEnd) return;
-
-        if (contentStart >= mContentEnd || mContentStart >= contentEnd) {
-            for (int i = mContentStart, n = mContentEnd; i < n; ++i) {
-                freeSlotContent(i);
-            }
-            mSource.setActiveWindow(contentStart, contentEnd);
-            for (int i = contentStart; i < contentEnd; ++i) {
-                prepareSlotContent(i);
-            }
-        } else {
-            for (int i = mContentStart; i < contentStart; ++i) {
-                freeSlotContent(i);
-            }
-            for (int i = contentEnd, n = mContentEnd; i < n; ++i) {
-                freeSlotContent(i);
-            }
-            mSource.setActiveWindow(contentStart, contentEnd);
-            for (int i = contentStart, n = mContentStart; i < n; ++i) {
-                prepareSlotContent(i);
-            }
-            for (int i = mContentEnd; i < contentEnd; ++i) {
-                prepareSlotContent(i);
-            }
-        }
-
-        mContentStart = contentStart;
-        mContentEnd = contentEnd;
-    }
-
-    public void setActiveWindow(int start, int end) {
-        if (!(start <= end && end - start <= mData.length && end <= mSize)) {
-            Utils.fail("start = %s, end = %s, length = %s, size = %s",
-                    start, end, mData.length, mSize);
-        }
-
-        AlbumSetEntry data[] = mData;
-        mActiveStart = start;
-        mActiveEnd = end;
-        int contentStart = Utils.clamp((start + end) / 2 - data.length / 2,
-                0, Math.max(0, mSize - data.length));
-        int contentEnd = Math.min(contentStart + data.length, mSize);
-        setContentWindow(contentStart, contentEnd);
-
-        if (mIsActive) {
-            updateTextureUploadQueue();
-            updateAllImageRequests();
-        }
-    }
-
-    // We would like to request non active slots in the following order:
-    // Order:    8 6 4 2                   1 3 5 7
-    //         |---------|---------------|---------|
-    //                   |<-  active  ->|
-    //         |<-------- cached range ----------->|
-    private void requestNonactiveImages() {
-        int range = Math.max(
-                mContentEnd - mActiveEnd, mActiveStart - mContentStart);
-        for (int i = 0 ;i < range; ++i) {
-            requestImagesInSlot(mActiveEnd + i);
-            requestImagesInSlot(mActiveStart - 1 - i);
-        }
-    }
-
-    private void cancelNonactiveImages() {
-        int range = Math.max(
-                mContentEnd - mActiveEnd, mActiveStart - mContentStart);
-        for (int i = 0 ;i < range; ++i) {
-            cancelImagesInSlot(mActiveEnd + i);
-            cancelImagesInSlot(mActiveStart - 1 - i);
-        }
-    }
-
-    private void requestImagesInSlot(int slotIndex) {
-        if (slotIndex < mContentStart || slotIndex >= mContentEnd) return;
-        AlbumSetEntry entry = mData[slotIndex % mData.length];
-        if (entry.coverLoader != null) entry.coverLoader.startLoad();
-        if (entry.labelLoader != null) entry.labelLoader.startLoad();
-    }
-
-    private void cancelImagesInSlot(int slotIndex) {
-        if (slotIndex < mContentStart || slotIndex >= mContentEnd) return;
-        AlbumSetEntry entry = mData[slotIndex % mData.length];
-        if (entry.coverLoader != null) entry.coverLoader.cancelLoad();
-        if (entry.labelLoader != null) entry.labelLoader.cancelLoad();
-    }
-
-    private static long getDataVersion(MediaObject object) {
-        return object == null
-                ? MediaSet.INVALID_DATA_VERSION
-                : object.getDataVersion();
-    }
-
-    private void freeSlotContent(int slotIndex) {
-        AlbumSetEntry entry = mData[slotIndex % mData.length];
-        if (entry.coverLoader != null) entry.coverLoader.recycle();
-        if (entry.labelLoader != null) entry.labelLoader.recycle();
-        if (entry.labelTexture != null) entry.labelTexture.recycle();
-        if (entry.bitmapTexture != null) entry.bitmapTexture.recycle();
-        mData[slotIndex % mData.length] = null;
-    }
-
-    private boolean isLabelChanged(
-            AlbumSetEntry entry, String title, int totalCount, int sourceType) {
-        return !Utils.equals(entry.title, title)
-                || entry.totalCount != totalCount
-                || entry.sourceType != sourceType;
-    }
-
-    private void updateAlbumSetEntry(AlbumSetEntry entry, int slotIndex) {
-        MediaSet album = mSource.getMediaSet(slotIndex);
-        MediaItem cover = mSource.getCoverItem(slotIndex);
-        int totalCount = mSource.getTotalCount(slotIndex);
-
-        entry.album = album;
-        entry.setDataVersion = getDataVersion(album);
-        entry.cacheFlag = identifyCacheFlag(album);
-        entry.cacheStatus = identifyCacheStatus(album);
-        entry.setPath = (album == null) ? null : album.getPath();
-
-        String title = (album == null) ? "" : Utils.ensureNotNull(album.getName());
-        int sourceType = DataSourceType.identifySourceType(album);
-        if (isLabelChanged(entry, title, totalCount, sourceType)) {
-            entry.title = title;
-            entry.totalCount = totalCount;
-            entry.sourceType = sourceType;
-            if (entry.labelLoader != null) {
-                entry.labelLoader.recycle();
-                entry.labelLoader = null;
-                entry.labelTexture = null;
-            }
-            if (album != null) {
-                entry.labelLoader = new AlbumLabelLoader(
-                        slotIndex, title, totalCount, sourceType);
-            }
-        }
-
-        entry.coverItem = cover;
-        if (getDataVersion(cover) != entry.coverDataVersion) {
-            entry.coverDataVersion = getDataVersion(cover);
-            entry.rotation = (cover == null) ? 0 : cover.getRotation();
-            if (entry.coverLoader != null) {
-                entry.coverLoader.recycle();
-                entry.coverLoader = null;
-                entry.bitmapTexture = null;
-                entry.content = null;
-            }
-            if (cover != null) {
-                entry.coverLoader = new AlbumCoverLoader(slotIndex, cover);
-            }
-        }
-    }
-
-    private void prepareSlotContent(int slotIndex) {
-        AlbumSetEntry entry = new AlbumSetEntry();
-        updateAlbumSetEntry(entry, slotIndex);
-        mData[slotIndex % mData.length] = entry;
-    }
-
-    private static boolean startLoadBitmap(BitmapLoader loader) {
-        if (loader == null) return false;
-        loader.startLoad();
-        return loader.isRequestInProgress();
-    }
-
-    private void uploadBackgroundTextureInSlot(int index) {
-        if (index < mContentStart || index >= mContentEnd) return;
-        AlbumSetEntry entry = mData[index % mData.length];
-        if (entry.bitmapTexture != null) {
-            mContentUploader.addTexture(entry.bitmapTexture);
-        }
-        if (entry.labelTexture != null) {
-            mLabelUploader.addBgTexture(entry.labelTexture);
-        }
-    }
-
-    private void updateTextureUploadQueue() {
-        if (!mIsActive) return;
-        mContentUploader.clear();
-        mLabelUploader.clear();
-
-        // Upload foreground texture
-        for (int i = mActiveStart, n = mActiveEnd; i < n; ++i) {
-            AlbumSetEntry entry = mData[i % mData.length];
-            if (entry.bitmapTexture != null) {
-                mContentUploader.addTexture(entry.bitmapTexture);
-            }
-            if (entry.labelTexture != null) {
-                mLabelUploader.addFgTexture(entry.labelTexture);
-            }
-        }
-
-        // add background textures
-        int range = Math.max(
-                (mContentEnd - mActiveEnd), (mActiveStart - mContentStart));
-        for (int i = 0; i < range; ++i) {
-            uploadBackgroundTextureInSlot(mActiveEnd + i);
-            uploadBackgroundTextureInSlot(mActiveStart - i - 1);
-        }
-    }
-
-    private void updateAllImageRequests() {
-        mActiveRequestCount = 0;
-        for (int i = mActiveStart, n = mActiveEnd; i < n; ++i) {
-            AlbumSetEntry entry = mData[i % mData.length];
-            if (startLoadBitmap(entry.coverLoader)) ++mActiveRequestCount;
-            if (startLoadBitmap(entry.labelLoader)) ++mActiveRequestCount;
-        }
-        if (mActiveRequestCount == 0) {
-            requestNonactiveImages();
-        } else {
-            cancelNonactiveImages();
-        }
-    }
-
-    @Override
-    public void onSizeChanged(int size) {
-        if (mIsActive && mSize != size) {
-            mSize = size;
-            if (mListener != null) mListener.onSizeChanged(mSize);
-            if (mContentEnd > mSize) mContentEnd = mSize;
-            if (mActiveEnd > mSize) mActiveEnd = mSize;
-        }
-    }
-
-    @Override
-    public void onContentChanged(int index) {
-        if (!mIsActive) {
-            // paused, ignore slot changed event
-            return;
-        }
-
-        // If the updated content is not cached, ignore it
-        if (index < mContentStart || index >= mContentEnd) {
-            Log.w(TAG, String.format(
-                    "invalid update: %s is outside (%s, %s)",
-                    index, mContentStart, mContentEnd) );
-            return;
-        }
-
-        AlbumSetEntry entry = mData[index % mData.length];
-        updateAlbumSetEntry(entry, index);
-        updateAllImageRequests();
-        updateTextureUploadQueue();
-        if (mListener != null && isActiveSlot(index)) {
-            mListener.onContentChanged();
-        }
-    }
-
-    public BitmapTexture getLoadingTexture() {
-        if (mLoadingLabel == null) {
-            Bitmap bitmap = mLabelMaker.requestLabel(
-                    mLoadingText, "", DataSourceType.TYPE_NOT_CATEGORIZED)
-                    .run(ThreadPool.JOB_CONTEXT_STUB);
-            mLoadingLabel = new BitmapTexture(bitmap);
-            mLoadingLabel.setOpaque(false);
-        }
-        return mLoadingLabel;
-    }
-
-    public void pause() {
-        mIsActive = false;
-        mLabelUploader.clear();
-        mContentUploader.clear();
-        TiledTexture.freeResources();
-        for (int i = mContentStart, n = mContentEnd; i < n; ++i) {
-            freeSlotContent(i);
-        }
-    }
-
-    public void resume() {
-        mIsActive = true;
-        TiledTexture.prepareResources();
-        for (int i = mContentStart, n = mContentEnd; i < n; ++i) {
-            prepareSlotContent(i);
-        }
-        updateAllImageRequests();
-    }
-
-    private static interface EntryUpdater {
-        public void updateEntry();
-    }
-
-    private class AlbumCoverLoader extends BitmapLoader implements EntryUpdater {
-        private MediaItem mMediaItem;
-        private final int mSlotIndex;
-
-        public AlbumCoverLoader(int slotIndex, MediaItem item) {
-            mSlotIndex = slotIndex;
-            mMediaItem = item;
-        }
-
-        @Override
-        protected Future<Bitmap> submitBitmapTask(FutureListener<Bitmap> l) {
-            return mThreadPool.submit(mMediaItem.requestImage(
-                    MediaItem.TYPE_MICROTHUMBNAIL), l);
-        }
-
-        @Override
-        protected void onLoadComplete(Bitmap bitmap) {
-            mHandler.obtainMessage(MSG_UPDATE_ALBUM_ENTRY, this).sendToTarget();
-        }
-
-        @Override
-        public void updateEntry() {
-            Bitmap bitmap = getBitmap();
-            if (bitmap == null) return; // error or recycled
-
-            AlbumSetEntry entry = mData[mSlotIndex % mData.length];
-            TiledTexture texture = new TiledTexture(bitmap);
-            entry.bitmapTexture = texture;
-            entry.content = texture;
-
-            if (isActiveSlot(mSlotIndex)) {
-                mContentUploader.addTexture(texture);
-                --mActiveRequestCount;
-                if (mActiveRequestCount == 0) requestNonactiveImages();
-                if (mListener != null) mListener.onContentChanged();
-            } else {
-                mContentUploader.addTexture(texture);
-            }
-        }
-    }
-
-    private static int identifyCacheFlag(MediaSet set) {
-        if (set == null || (set.getSupportedOperations()
-                & MediaSet.SUPPORT_CACHE) == 0) {
-            return MediaSet.CACHE_FLAG_NO;
-        }
-
-        return set.getCacheFlag();
-    }
-
-    private static int identifyCacheStatus(MediaSet set) {
-        if (set == null || (set.getSupportedOperations()
-                & MediaSet.SUPPORT_CACHE) == 0) {
-            return MediaSet.CACHE_STATUS_NOT_CACHED;
-        }
-
-        return set.getCacheStatus();
-    }
-
-    private class AlbumLabelLoader extends BitmapLoader implements EntryUpdater {
-        private final int mSlotIndex;
-        private final String mTitle;
-        private final int mTotalCount;
-        private final int mSourceType;
-
-        public AlbumLabelLoader(
-                int slotIndex, String title, int totalCount, int sourceType) {
-            mSlotIndex = slotIndex;
-            mTitle = title;
-            mTotalCount = totalCount;
-            mSourceType = sourceType;
-        }
-
-        @Override
-        protected Future<Bitmap> submitBitmapTask(FutureListener<Bitmap> l) {
-            return mThreadPool.submit(mLabelMaker.requestLabel(
-                    mTitle, String.valueOf(mTotalCount), mSourceType), l);
-        }
-
-        @Override
-        protected void onLoadComplete(Bitmap bitmap) {
-            mHandler.obtainMessage(MSG_UPDATE_ALBUM_ENTRY, this).sendToTarget();
-        }
-
-        @Override
-        public void updateEntry() {
-            Bitmap bitmap = getBitmap();
-            if (bitmap == null) return; // Error or recycled
-
-            AlbumSetEntry entry = mData[mSlotIndex % mData.length];
-            BitmapTexture texture = new BitmapTexture(bitmap);
-            texture.setOpaque(false);
-            entry.labelTexture = texture;
-
-            if (isActiveSlot(mSlotIndex)) {
-                mLabelUploader.addFgTexture(texture);
-                --mActiveRequestCount;
-                if (mActiveRequestCount == 0) requestNonactiveImages();
-                if (mListener != null) mListener.onContentChanged();
-            } else {
-                mLabelUploader.addBgTexture(texture);
-            }
-        }
-    }
-
-    public void onSlotSizeChanged(int width, int height) {
-        if (mSlotWidth == width) return;
-
-        mSlotWidth = width;
-        mLoadingLabel = null;
-        mLabelMaker.setLabelWidth(mSlotWidth);
-
-        if (!mIsActive) return;
-
-        for (int i = mContentStart, n = mContentEnd; i < n; ++i) {
-            AlbumSetEntry entry = mData[i % mData.length];
-            if (entry.labelLoader != null) {
-                entry.labelLoader.recycle();
-                entry.labelLoader = null;
-                entry.labelTexture = null;
-            }
-            if (entry.album != null) {
-                entry.labelLoader = new AlbumLabelLoader(i,
-                        entry.title, entry.totalCount, entry.sourceType);
-            }
-        }
-        updateAllImageRequests();
-        updateTextureUploadQueue();
-    }
-}
diff --git a/src/com/android/gallery3d/ui/AlbumSetSlotRenderer.java b/src/com/android/gallery3d/ui/AlbumSetSlotRenderer.java
deleted file mode 100644
index 5332ef8..0000000
--- a/src/com/android/gallery3d/ui/AlbumSetSlotRenderer.java
+++ /dev/null
@@ -1,242 +0,0 @@
-/*
- * Copyright (C) 2010 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.gallery3d.ui;
-
-import com.android.gallery3d.R;
-import com.android.gallery3d.app.AbstractGalleryActivity;
-import com.android.gallery3d.app.AlbumSetDataLoader;
-import com.android.gallery3d.data.MediaObject;
-import com.android.gallery3d.data.Path;
-import com.android.gallery3d.glrenderer.ColorTexture;
-import com.android.gallery3d.glrenderer.FadeInTexture;
-import com.android.gallery3d.glrenderer.GLCanvas;
-import com.android.gallery3d.glrenderer.ResourceTexture;
-import com.android.gallery3d.glrenderer.Texture;
-import com.android.gallery3d.glrenderer.TiledTexture;
-import com.android.gallery3d.glrenderer.UploadedTexture;
-import com.android.gallery3d.ui.AlbumSetSlidingWindow.AlbumSetEntry;
-
-public class AlbumSetSlotRenderer extends AbstractSlotRenderer {
-    @SuppressWarnings("unused")
-    private static final String TAG = "AlbumSetView";
-    private static final int CACHE_SIZE = 96;
-    private final int mPlaceholderColor;
-
-    private final ColorTexture mWaitLoadingTexture;
-    private final ResourceTexture mCameraOverlay;
-    private final AbstractGalleryActivity mActivity;
-    private final SelectionManager mSelectionManager;
-    protected final LabelSpec mLabelSpec;
-
-    protected AlbumSetSlidingWindow mDataWindow;
-    private SlotView mSlotView;
-
-    private int mPressedIndex = -1;
-    private boolean mAnimatePressedUp;
-    private Path mHighlightItemPath = null;
-    private boolean mInSelectionMode;
-
-    public static class LabelSpec {
-        public int labelBackgroundHeight;
-        public int titleOffset;
-        public int countOffset;
-        public int titleFontSize;
-        public int countFontSize;
-        public int leftMargin;
-        public int iconSize;
-        public int titleRightMargin;
-        public int backgroundColor;
-        public int titleColor;
-        public int countColor;
-        public int borderSize;
-    }
-
-    public AlbumSetSlotRenderer(AbstractGalleryActivity activity,
-            SelectionManager selectionManager,
-            SlotView slotView, LabelSpec labelSpec, int placeholderColor) {
-        super (activity);
-        mActivity = activity;
-        mSelectionManager = selectionManager;
-        mSlotView = slotView;
-        mLabelSpec = labelSpec;
-        mPlaceholderColor = placeholderColor;
-
-        mWaitLoadingTexture = new ColorTexture(mPlaceholderColor);
-        mWaitLoadingTexture.setSize(1, 1);
-        mCameraOverlay = new ResourceTexture(activity,
-                R.drawable.ic_cameraalbum_overlay);
-    }
-
-    public void setPressedIndex(int index) {
-        if (mPressedIndex == index) return;
-        mPressedIndex = index;
-        mSlotView.invalidate();
-    }
-
-    public void setPressedUp() {
-        if (mPressedIndex == -1) return;
-        mAnimatePressedUp = true;
-        mSlotView.invalidate();
-    }
-
-    public void setHighlightItemPath(Path path) {
-        if (mHighlightItemPath == path) return;
-        mHighlightItemPath = path;
-        mSlotView.invalidate();
-    }
-
-    public void setModel(AlbumSetDataLoader model) {
-        if (mDataWindow != null) {
-            mDataWindow.setListener(null);
-            mDataWindow = null;
-            mSlotView.setSlotCount(0);
-        }
-        if (model != null) {
-            mDataWindow = new AlbumSetSlidingWindow(
-                    mActivity, model, mLabelSpec, CACHE_SIZE);
-            mDataWindow.setListener(new MyCacheListener());
-            mSlotView.setSlotCount(mDataWindow.size());
-        }
-    }
-
-    private static Texture checkLabelTexture(Texture texture) {
-        return ((texture instanceof UploadedTexture)
-                && ((UploadedTexture) texture).isUploading())
-                ? null
-                : texture;
-    }
-
-    private static Texture checkContentTexture(Texture texture) {
-        return ((texture instanceof TiledTexture)
-                && !((TiledTexture) texture).isReady())
-                ? null
-                : texture;
-    }
-
-    @Override
-    public int renderSlot(GLCanvas canvas, int index, int pass, int width, int height) {
-        AlbumSetEntry entry = mDataWindow.get(index);
-        int renderRequestFlags = 0;
-        renderRequestFlags |= renderContent(canvas, entry, width, height);
-        renderRequestFlags |= renderLabel(canvas, entry, width, height);
-        renderRequestFlags |= renderOverlay(canvas, index, entry, width, height);
-        return renderRequestFlags;
-    }
-
-    protected int renderOverlay(
-            GLCanvas canvas, int index, AlbumSetEntry entry, int width, int height) {
-        int renderRequestFlags = 0;
-        if (entry.album != null && entry.album.isCameraRoll()) {
-            int uncoveredHeight = height - mLabelSpec.labelBackgroundHeight;
-            int dim = uncoveredHeight / 2;
-            mCameraOverlay.draw(canvas, (width - dim) / 2,
-                    (uncoveredHeight - dim) / 2, dim, dim);
-        }
-        if (mPressedIndex == index) {
-            if (mAnimatePressedUp) {
-                drawPressedUpFrame(canvas, width, height);
-                renderRequestFlags |= SlotView.RENDER_MORE_FRAME;
-                if (isPressedUpFrameFinished()) {
-                    mAnimatePressedUp = false;
-                    mPressedIndex = -1;
-                }
-            } else {
-                drawPressedFrame(canvas, width, height);
-            }
-        } else if ((mHighlightItemPath != null) && (mHighlightItemPath == entry.setPath)) {
-            drawSelectedFrame(canvas, width, height);
-        } else if (mInSelectionMode && mSelectionManager.isItemSelected(entry.setPath)) {
-            drawSelectedFrame(canvas, width, height);
-        }
-        return renderRequestFlags;
-    }
-
-    protected int renderContent(
-            GLCanvas canvas, AlbumSetEntry entry, int width, int height) {
-        int renderRequestFlags = 0;
-
-        Texture content = checkContentTexture(entry.content);
-        if (content == null) {
-            content = mWaitLoadingTexture;
-            entry.isWaitLoadingDisplayed = true;
-        } else if (entry.isWaitLoadingDisplayed) {
-            entry.isWaitLoadingDisplayed = false;
-            content = new FadeInTexture(mPlaceholderColor, entry.bitmapTexture);
-            entry.content = content;
-        }
-        drawContent(canvas, content, width, height, entry.rotation);
-        if ((content instanceof FadeInTexture) &&
-                ((FadeInTexture) content).isAnimating()) {
-            renderRequestFlags |= SlotView.RENDER_MORE_FRAME;
-        }
-
-        return renderRequestFlags;
-    }
-
-    protected int renderLabel(
-            GLCanvas canvas, AlbumSetEntry entry, int width, int height) {
-        Texture content = checkLabelTexture(entry.labelTexture);
-        if (content == null) {
-            content = mWaitLoadingTexture;
-        }
-        int b = AlbumLabelMaker.getBorderSize();
-        int h = mLabelSpec.labelBackgroundHeight;
-        content.draw(canvas, -b, height - h + b, width + b + b, h);
-
-        return 0;
-    }
-
-    @Override
-    public void prepareDrawing() {
-        mInSelectionMode = mSelectionManager.inSelectionMode();
-    }
-
-    private class MyCacheListener implements AlbumSetSlidingWindow.Listener {
-
-        @Override
-        public void onSizeChanged(int size) {
-            mSlotView.setSlotCount(size);
-        }
-
-        @Override
-        public void onContentChanged() {
-            mSlotView.invalidate();
-        }
-    }
-
-    public void pause() {
-        mDataWindow.pause();
-    }
-
-    public void resume() {
-        mDataWindow.resume();
-    }
-
-    @Override
-    public void onVisibleRangeChanged(int visibleStart, int visibleEnd) {
-        if (mDataWindow != null) {
-            mDataWindow.setActiveWindow(visibleStart, visibleEnd);
-        }
-    }
-
-    @Override
-    public void onSlotSizeChanged(int width, int height) {
-        if (mDataWindow != null) {
-            mDataWindow.onSlotSizeChanged(width, height);
-        }
-    }
-}
diff --git a/src/com/android/gallery3d/ui/AlbumSlidingWindow.java b/src/com/android/gallery3d/ui/AlbumSlidingWindow.java
deleted file mode 100644
index fec7d1e..0000000
--- a/src/com/android/gallery3d/ui/AlbumSlidingWindow.java
+++ /dev/null
@@ -1,365 +0,0 @@
-/*
- * Copyright (C) 2010 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.gallery3d.ui;
-
-import android.graphics.Bitmap;
-import android.os.Message;
-
-import com.android.gallery3d.app.AbstractGalleryActivity;
-import com.android.gallery3d.app.AlbumDataLoader;
-import com.android.gallery3d.common.Utils;
-import com.android.gallery3d.data.MediaItem;
-import com.android.gallery3d.data.MediaObject;
-import com.android.gallery3d.data.MediaObject.PanoramaSupportCallback;
-import com.android.gallery3d.data.Path;
-import com.android.gallery3d.glrenderer.Texture;
-import com.android.gallery3d.glrenderer.TiledTexture;
-import com.android.gallery3d.util.Future;
-import com.android.gallery3d.util.FutureListener;
-import com.android.gallery3d.util.JobLimiter;
-
-public class AlbumSlidingWindow implements AlbumDataLoader.DataListener {
-    @SuppressWarnings("unused")
-    private static final String TAG = "AlbumSlidingWindow";
-
-    private static final int MSG_UPDATE_ENTRY = 0;
-    private static final int JOB_LIMIT = 2;
-
-    public static interface Listener {
-        public void onSizeChanged(int size);
-        public void onContentChanged();
-    }
-
-    public static class AlbumEntry {
-        public MediaItem item;
-        public Path path;
-        public boolean isPanorama;
-        public int rotation;
-        public int mediaType;
-        public boolean isWaitDisplayed;
-        public TiledTexture bitmapTexture;
-        public Texture content;
-        private BitmapLoader contentLoader;
-        private PanoSupportListener mPanoSupportListener;
-    }
-
-    private final AlbumDataLoader mSource;
-    private final AlbumEntry mData[];
-    private final SynchronizedHandler mHandler;
-    private final JobLimiter mThreadPool;
-    private final TiledTexture.Uploader mTileUploader;
-
-    private int mSize;
-
-    private int mContentStart = 0;
-    private int mContentEnd = 0;
-
-    private int mActiveStart = 0;
-    private int mActiveEnd = 0;
-
-    private Listener mListener;
-
-    private int mActiveRequestCount = 0;
-    private boolean mIsActive = false;
-
-    private class PanoSupportListener implements PanoramaSupportCallback {
-        public final AlbumEntry mEntry;
-        public PanoSupportListener (AlbumEntry entry) {
-            mEntry = entry;
-        }
-        @Override
-        public void panoramaInfoAvailable(MediaObject mediaObject, boolean isPanorama,
-                boolean isPanorama360) {
-            if (mEntry != null) mEntry.isPanorama = isPanorama;
-        }
-    }
-
-    public AlbumSlidingWindow(AbstractGalleryActivity activity,
-            AlbumDataLoader source, int cacheSize) {
-        source.setDataListener(this);
-        mSource = source;
-        mData = new AlbumEntry[cacheSize];
-        mSize = source.size();
-
-        mHandler = new SynchronizedHandler(activity.getGLRoot()) {
-            @Override
-            public void handleMessage(Message message) {
-                Utils.assertTrue(message.what == MSG_UPDATE_ENTRY);
-                ((ThumbnailLoader) message.obj).updateEntry();
-            }
-        };
-
-        mThreadPool = new JobLimiter(activity.getThreadPool(), JOB_LIMIT);
-        mTileUploader = new TiledTexture.Uploader(activity.getGLRoot());
-    }
-
-    public void setListener(Listener listener) {
-        mListener = listener;
-    }
-
-    public AlbumEntry get(int slotIndex) {
-        if (!isActiveSlot(slotIndex)) {
-            Utils.fail("invalid slot: %s outsides (%s, %s)",
-                    slotIndex, mActiveStart, mActiveEnd);
-        }
-        return mData[slotIndex % mData.length];
-    }
-
-    public boolean isActiveSlot(int slotIndex) {
-        return slotIndex >= mActiveStart && slotIndex < mActiveEnd;
-    }
-
-    private void setContentWindow(int contentStart, int contentEnd) {
-        if (contentStart == mContentStart && contentEnd == mContentEnd) return;
-
-        if (!mIsActive) {
-            mContentStart = contentStart;
-            mContentEnd = contentEnd;
-            mSource.setActiveWindow(contentStart, contentEnd);
-            return;
-        }
-
-        if (contentStart >= mContentEnd || mContentStart >= contentEnd) {
-            for (int i = mContentStart, n = mContentEnd; i < n; ++i) {
-                freeSlotContent(i);
-            }
-            mSource.setActiveWindow(contentStart, contentEnd);
-            for (int i = contentStart; i < contentEnd; ++i) {
-                prepareSlotContent(i);
-            }
-        } else {
-            for (int i = mContentStart; i < contentStart; ++i) {
-                freeSlotContent(i);
-            }
-            for (int i = contentEnd, n = mContentEnd; i < n; ++i) {
-                freeSlotContent(i);
-            }
-            mSource.setActiveWindow(contentStart, contentEnd);
-            for (int i = contentStart, n = mContentStart; i < n; ++i) {
-                prepareSlotContent(i);
-            }
-            for (int i = mContentEnd; i < contentEnd; ++i) {
-                prepareSlotContent(i);
-            }
-        }
-
-        mContentStart = contentStart;
-        mContentEnd = contentEnd;
-    }
-
-    public void setActiveWindow(int start, int end) {
-        if (!(start <= end && end - start <= mData.length && end <= mSize)) {
-            Utils.fail("%s, %s, %s, %s", start, end, mData.length, mSize);
-        }
-        AlbumEntry data[] = mData;
-
-        mActiveStart = start;
-        mActiveEnd = end;
-
-        int contentStart = Utils.clamp((start + end) / 2 - data.length / 2,
-                0, Math.max(0, mSize - data.length));
-        int contentEnd = Math.min(contentStart + data.length, mSize);
-        setContentWindow(contentStart, contentEnd);
-        updateTextureUploadQueue();
-        if (mIsActive) updateAllImageRequests();
-    }
-
-    private void uploadBgTextureInSlot(int index) {
-        if (index < mContentEnd && index >= mContentStart) {
-            AlbumEntry entry = mData[index % mData.length];
-            if (entry.bitmapTexture != null) {
-                mTileUploader.addTexture(entry.bitmapTexture);
-            }
-        }
-    }
-
-    private void updateTextureUploadQueue() {
-        if (!mIsActive) return;
-        mTileUploader.clear();
-
-        // add foreground textures
-        for (int i = mActiveStart, n = mActiveEnd; i < n; ++i) {
-            AlbumEntry entry = mData[i % mData.length];
-            if (entry.bitmapTexture != null) {
-                mTileUploader.addTexture(entry.bitmapTexture);
-            }
-        }
-
-        // add background textures
-        int range = Math.max(
-                (mContentEnd - mActiveEnd), (mActiveStart - mContentStart));
-        for (int i = 0; i < range; ++i) {
-            uploadBgTextureInSlot(mActiveEnd + i);
-            uploadBgTextureInSlot(mActiveStart - i - 1);
-        }
-    }
-
-    // We would like to request non active slots in the following order:
-    // Order:    8 6 4 2                   1 3 5 7
-    //         |---------|---------------|---------|
-    //                   |<-  active  ->|
-    //         |<-------- cached range ----------->|
-    private void requestNonactiveImages() {
-        int range = Math.max(
-                (mContentEnd - mActiveEnd), (mActiveStart - mContentStart));
-        for (int i = 0 ;i < range; ++i) {
-            requestSlotImage(mActiveEnd + i);
-            requestSlotImage(mActiveStart - 1 - i);
-        }
-    }
-
-    // return whether the request is in progress or not
-    private boolean requestSlotImage(int slotIndex) {
-        if (slotIndex < mContentStart || slotIndex >= mContentEnd) return false;
-        AlbumEntry entry = mData[slotIndex % mData.length];
-        if (entry.content != null || entry.item == null) return false;
-
-        // Set up the panorama callback
-        entry.mPanoSupportListener = new PanoSupportListener(entry);
-        entry.item.getPanoramaSupport(entry.mPanoSupportListener);
-
-        entry.contentLoader.startLoad();
-        return entry.contentLoader.isRequestInProgress();
-    }
-
-    private void cancelNonactiveImages() {
-        int range = Math.max(
-                (mContentEnd - mActiveEnd), (mActiveStart - mContentStart));
-        for (int i = 0 ;i < range; ++i) {
-            cancelSlotImage(mActiveEnd + i);
-            cancelSlotImage(mActiveStart - 1 - i);
-        }
-    }
-
-    private void cancelSlotImage(int slotIndex) {
-        if (slotIndex < mContentStart || slotIndex >= mContentEnd) return;
-        AlbumEntry item = mData[slotIndex % mData.length];
-        if (item.contentLoader != null) item.contentLoader.cancelLoad();
-    }
-
-    private void freeSlotContent(int slotIndex) {
-        AlbumEntry data[] = mData;
-        int index = slotIndex % data.length;
-        AlbumEntry entry = data[index];
-        if (entry.contentLoader != null) entry.contentLoader.recycle();
-        if (entry.bitmapTexture != null) entry.bitmapTexture.recycle();
-        data[index] = null;
-    }
-
-    private void prepareSlotContent(int slotIndex) {
-        AlbumEntry entry = new AlbumEntry();
-        MediaItem item = mSource.get(slotIndex); // item could be null;
-        entry.item = item;
-        entry.mediaType = (item == null)
-                ? MediaItem.MEDIA_TYPE_UNKNOWN
-                : entry.item.getMediaType();
-        entry.path = (item == null) ? null : item.getPath();
-        entry.rotation = (item == null) ? 0 : item.getRotation();
-        entry.contentLoader = new ThumbnailLoader(slotIndex, entry.item);
-        mData[slotIndex % mData.length] = entry;
-    }
-
-    private void updateAllImageRequests() {
-        mActiveRequestCount = 0;
-        for (int i = mActiveStart, n = mActiveEnd; i < n; ++i) {
-            if (requestSlotImage(i)) ++mActiveRequestCount;
-        }
-        if (mActiveRequestCount == 0) {
-            requestNonactiveImages();
-        } else {
-            cancelNonactiveImages();
-        }
-    }
-
-    private class ThumbnailLoader extends BitmapLoader  {
-        private final int mSlotIndex;
-        private final MediaItem mItem;
-
-        public ThumbnailLoader(int slotIndex, MediaItem item) {
-            mSlotIndex = slotIndex;
-            mItem = item;
-        }
-
-        @Override
-        protected Future<Bitmap> submitBitmapTask(FutureListener<Bitmap> l) {
-            return mThreadPool.submit(
-                    mItem.requestImage(MediaItem.TYPE_MICROTHUMBNAIL), this);
-        }
-
-        @Override
-        protected void onLoadComplete(Bitmap bitmap) {
-            mHandler.obtainMessage(MSG_UPDATE_ENTRY, this).sendToTarget();
-        }
-
-        public void updateEntry() {
-            Bitmap bitmap = getBitmap();
-            if (bitmap == null) return; // error or recycled
-            AlbumEntry entry = mData[mSlotIndex % mData.length];
-            entry.bitmapTexture = new TiledTexture(bitmap);
-            entry.content = entry.bitmapTexture;
-
-            if (isActiveSlot(mSlotIndex)) {
-                mTileUploader.addTexture(entry.bitmapTexture);
-                --mActiveRequestCount;
-                if (mActiveRequestCount == 0) requestNonactiveImages();
-                if (mListener != null) mListener.onContentChanged();
-            } else {
-                mTileUploader.addTexture(entry.bitmapTexture);
-            }
-        }
-    }
-
-    @Override
-    public void onSizeChanged(int size) {
-        if (mSize != size) {
-            mSize = size;
-            if (mListener != null) mListener.onSizeChanged(mSize);
-            if (mContentEnd > mSize) mContentEnd = mSize;
-            if (mActiveEnd > mSize) mActiveEnd = mSize;
-        }
-    }
-
-    @Override
-    public void onContentChanged(int index) {
-        if (index >= mContentStart && index < mContentEnd && mIsActive) {
-            freeSlotContent(index);
-            prepareSlotContent(index);
-            updateAllImageRequests();
-            if (mListener != null && isActiveSlot(index)) {
-                mListener.onContentChanged();
-            }
-        }
-    }
-
-    public void resume() {
-        mIsActive = true;
-        TiledTexture.prepareResources();
-        for (int i = mContentStart, n = mContentEnd; i < n; ++i) {
-            prepareSlotContent(i);
-        }
-        updateAllImageRequests();
-    }
-
-    public void pause() {
-        mIsActive = false;
-        mTileUploader.clear();
-        TiledTexture.freeResources();
-        for (int i = mContentStart, n = mContentEnd; i < n; ++i) {
-            freeSlotContent(i);
-        }
-    }
-}
diff --git a/src/com/android/gallery3d/ui/AlbumSlotRenderer.java b/src/com/android/gallery3d/ui/AlbumSlotRenderer.java
deleted file mode 100644
index dc6c89b..0000000
--- a/src/com/android/gallery3d/ui/AlbumSlotRenderer.java
+++ /dev/null
@@ -1,201 +0,0 @@
-/*
- * Copyright (C) 2010 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.gallery3d.ui;
-
-import com.android.gallery3d.app.AbstractGalleryActivity;
-import com.android.gallery3d.app.AlbumDataLoader;
-import com.android.gallery3d.data.MediaObject;
-import com.android.gallery3d.data.Path;
-import com.android.gallery3d.glrenderer.ColorTexture;
-import com.android.gallery3d.glrenderer.FadeInTexture;
-import com.android.gallery3d.glrenderer.GLCanvas;
-import com.android.gallery3d.glrenderer.Texture;
-import com.android.gallery3d.glrenderer.TiledTexture;
-
-public class AlbumSlotRenderer extends AbstractSlotRenderer {
-    @SuppressWarnings("unused")
-    private static final String TAG = "AlbumView";
-
-    public interface SlotFilter {
-        public boolean acceptSlot(int index);
-    }
-
-    private final int mPlaceholderColor;
-    private static final int CACHE_SIZE = 96;
-
-    private AlbumSlidingWindow mDataWindow;
-    private final AbstractGalleryActivity mActivity;
-    private final ColorTexture mWaitLoadingTexture;
-    private final SlotView mSlotView;
-    private final SelectionManager mSelectionManager;
-
-    private int mPressedIndex = -1;
-    private boolean mAnimatePressedUp;
-    private Path mHighlightItemPath = null;
-    private boolean mInSelectionMode;
-
-    private SlotFilter mSlotFilter;
-
-    public AlbumSlotRenderer(AbstractGalleryActivity activity, SlotView slotView,
-            SelectionManager selectionManager, int placeholderColor) {
-        super(activity);
-        mActivity = activity;
-        mSlotView = slotView;
-        mSelectionManager = selectionManager;
-        mPlaceholderColor = placeholderColor;
-
-        mWaitLoadingTexture = new ColorTexture(mPlaceholderColor);
-        mWaitLoadingTexture.setSize(1, 1);
-    }
-
-    public void setPressedIndex(int index) {
-        if (mPressedIndex == index) return;
-        mPressedIndex = index;
-        mSlotView.invalidate();
-    }
-
-    public void setPressedUp() {
-        if (mPressedIndex == -1) return;
-        mAnimatePressedUp = true;
-        mSlotView.invalidate();
-    }
-
-    public void setHighlightItemPath(Path path) {
-        if (mHighlightItemPath == path) return;
-        mHighlightItemPath = path;
-        mSlotView.invalidate();
-    }
-
-    public void setModel(AlbumDataLoader model) {
-        if (mDataWindow != null) {
-            mDataWindow.setListener(null);
-            mSlotView.setSlotCount(0);
-            mDataWindow = null;
-        }
-        if (model != null) {
-            mDataWindow = new AlbumSlidingWindow(mActivity, model, CACHE_SIZE);
-            mDataWindow.setListener(new MyDataModelListener());
-            mSlotView.setSlotCount(model.size());
-        }
-    }
-
-    private static Texture checkTexture(Texture texture) {
-        return (texture instanceof TiledTexture)
-                && !((TiledTexture) texture).isReady()
-                ? null
-                : texture;
-    }
-
-    @Override
-    public int renderSlot(GLCanvas canvas, int index, int pass, int width, int height) {
-        if (mSlotFilter != null && !mSlotFilter.acceptSlot(index)) return 0;
-
-        AlbumSlidingWindow.AlbumEntry entry = mDataWindow.get(index);
-
-        int renderRequestFlags = 0;
-
-        Texture content = checkTexture(entry.content);
-        if (content == null) {
-            content = mWaitLoadingTexture;
-            entry.isWaitDisplayed = true;
-        } else if (entry.isWaitDisplayed) {
-            entry.isWaitDisplayed = false;
-            content = new FadeInTexture(mPlaceholderColor, entry.bitmapTexture);
-            entry.content = content;
-        }
-        drawContent(canvas, content, width, height, entry.rotation);
-        if ((content instanceof FadeInTexture) &&
-                ((FadeInTexture) content).isAnimating()) {
-            renderRequestFlags |= SlotView.RENDER_MORE_FRAME;
-        }
-
-        if (entry.mediaType == MediaObject.MEDIA_TYPE_VIDEO) {
-            drawVideoOverlay(canvas, width, height);
-        }
-
-        if (entry.isPanorama) {
-            drawPanoramaIcon(canvas, width, height);
-        }
-
-        renderRequestFlags |= renderOverlay(canvas, index, entry, width, height);
-
-        return renderRequestFlags;
-    }
-
-    private int renderOverlay(GLCanvas canvas, int index,
-            AlbumSlidingWindow.AlbumEntry entry, int width, int height) {
-        int renderRequestFlags = 0;
-        if (mPressedIndex == index) {
-            if (mAnimatePressedUp) {
-                drawPressedUpFrame(canvas, width, height);
-                renderRequestFlags |= SlotView.RENDER_MORE_FRAME;
-                if (isPressedUpFrameFinished()) {
-                    mAnimatePressedUp = false;
-                    mPressedIndex = -1;
-                }
-            } else {
-                drawPressedFrame(canvas, width, height);
-            }
-        } else if ((entry.path != null) && (mHighlightItemPath == entry.path)) {
-            drawSelectedFrame(canvas, width, height);
-        } else if (mInSelectionMode && mSelectionManager.isItemSelected(entry.path)) {
-            drawSelectedFrame(canvas, width, height);
-        }
-        return renderRequestFlags;
-    }
-
-    private class MyDataModelListener implements AlbumSlidingWindow.Listener {
-        @Override
-        public void onContentChanged() {
-            mSlotView.invalidate();
-        }
-
-        @Override
-        public void onSizeChanged(int size) {
-            mSlotView.setSlotCount(size);
-        }
-    }
-
-    public void resume() {
-        mDataWindow.resume();
-    }
-
-    public void pause() {
-        mDataWindow.pause();
-    }
-
-    @Override
-    public void prepareDrawing() {
-        mInSelectionMode = mSelectionManager.inSelectionMode();
-    }
-
-    @Override
-    public void onVisibleRangeChanged(int visibleStart, int visibleEnd) {
-        if (mDataWindow != null) {
-            mDataWindow.setActiveWindow(visibleStart, visibleEnd);
-        }
-    }
-
-    @Override
-    public void onSlotSizeChanged(int width, int height) {
-        // Do nothing
-    }
-
-    public void setSlotFilter(SlotFilter slotFilter) {
-        mSlotFilter = slotFilter;
-    }
-}
diff --git a/src/com/android/gallery3d/ui/AnimationTime.java b/src/com/android/gallery3d/ui/AnimationTime.java
deleted file mode 100644
index 0636774..0000000
--- a/src/com/android/gallery3d/ui/AnimationTime.java
+++ /dev/null
@@ -1,45 +0,0 @@
-
-/*
- * 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.gallery3d.ui;
-
-import android.os.SystemClock;
-
-//
-// The animation time should ideally be the vsync time the frame will be
-// displayed, but that is an unknown time in the future. So we use the system
-// time just after eglSwapBuffers (when GLSurfaceView.onDrawFrame is called)
-// as a approximation.
-//
-public class AnimationTime {
-    private static volatile long sTime;
-
-    // Sets current time as the animation time.
-    public static void update() {
-        sTime = SystemClock.uptimeMillis();
-    }
-
-    // Returns the animation time.
-    public static long get() {
-        return sTime;
-    }
-
-    public static long startTime() {
-        sTime = SystemClock.uptimeMillis();
-        return sTime;
-    }
-}
diff --git a/src/com/android/gallery3d/ui/BitmapLoader.java b/src/com/android/gallery3d/ui/BitmapLoader.java
deleted file mode 100644
index a708a90..0000000
--- a/src/com/android/gallery3d/ui/BitmapLoader.java
+++ /dev/null
@@ -1,108 +0,0 @@
-/*
- * Copyright (C) 2010 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.gallery3d.ui;
-
-import android.graphics.Bitmap;
-
-import com.android.photos.data.GalleryBitmapPool;
-import com.android.gallery3d.util.Future;
-import com.android.gallery3d.util.FutureListener;
-
-// We use this class to
-//     1.) load bitmaps in background.
-//     2.) as a place holder for the loaded bitmap
-public abstract class BitmapLoader implements FutureListener<Bitmap> {
-    @SuppressWarnings("unused")
-    private static final String TAG = "BitmapLoader";
-
-    /* Transition Map:
-     *   INIT -> REQUESTED, RECYCLED
-     *   REQUESTED -> INIT (cancel), LOADED, ERROR, RECYCLED
-     *   LOADED, ERROR -> RECYCLED
-     */
-    private static final int STATE_INIT = 0;
-    private static final int STATE_REQUESTED = 1;
-    private static final int STATE_LOADED = 2;
-    private static final int STATE_ERROR = 3;
-    private static final int STATE_RECYCLED = 4;
-
-    private int mState = STATE_INIT;
-    // mTask is not null only when a task is on the way
-    private Future<Bitmap> mTask;
-    private Bitmap mBitmap;
-
-    @Override
-    public void onFutureDone(Future<Bitmap> future) {
-        synchronized (this) {
-            mTask = null;
-            mBitmap = future.get();
-            if (mState == STATE_RECYCLED) {
-                if (mBitmap != null) {
-                    GalleryBitmapPool.getInstance().put(mBitmap);
-                    mBitmap = null;
-                }
-                return; // don't call callback
-            }
-            if (future.isCancelled() && mBitmap == null) {
-                if (mState == STATE_REQUESTED) mTask = submitBitmapTask(this);
-                return; // don't call callback
-            } else {
-                mState = mBitmap == null ? STATE_ERROR : STATE_LOADED;
-            }
-        }
-        onLoadComplete(mBitmap);
-    }
-
-    public synchronized void startLoad() {
-        if (mState == STATE_INIT) {
-            mState = STATE_REQUESTED;
-            if (mTask == null) mTask = submitBitmapTask(this);
-        }
-    }
-
-    public synchronized void cancelLoad() {
-        if (mState == STATE_REQUESTED) {
-            mState = STATE_INIT;
-            if (mTask != null) mTask.cancel();
-        }
-    }
-
-    // Recycle the loader and the bitmap
-    public synchronized void recycle() {
-        mState = STATE_RECYCLED;
-        if (mBitmap != null) {
-            GalleryBitmapPool.getInstance().put(mBitmap);
-            mBitmap = null;
-        }
-        if (mTask != null) mTask.cancel();
-    }
-
-    public synchronized boolean isRequestInProgress() {
-        return mState == STATE_REQUESTED;
-    }
-
-    public synchronized boolean isRecycled() {
-        return mState == STATE_RECYCLED;
-    }
-
-    public synchronized Bitmap getBitmap() {
-        return mBitmap;
-    }
-
-    abstract protected Future<Bitmap> submitBitmapTask(FutureListener<Bitmap> l);
-    abstract protected void onLoadComplete(Bitmap bitmap);
-}
diff --git a/src/com/android/gallery3d/ui/BitmapScreenNail.java b/src/com/android/gallery3d/ui/BitmapScreenNail.java
deleted file mode 100644
index a3d4039..0000000
--- a/src/com/android/gallery3d/ui/BitmapScreenNail.java
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * 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.gallery3d.ui;
-
-import android.graphics.Bitmap;
-import android.graphics.RectF;
-
-import com.android.gallery3d.glrenderer.BitmapTexture;
-import com.android.gallery3d.glrenderer.GLCanvas;
-
-public class BitmapScreenNail implements ScreenNail {
-    private final BitmapTexture mBitmapTexture;
-
-    public BitmapScreenNail(Bitmap bitmap) {
-        mBitmapTexture = new BitmapTexture(bitmap);
-    }
-
-    @Override
-    public int getWidth() {
-        return mBitmapTexture.getWidth();
-    }
-
-    @Override
-    public int getHeight() {
-        return mBitmapTexture.getHeight();
-    }
-
-    @Override
-    public void draw(GLCanvas canvas, int x, int y, int width, int height) {
-        mBitmapTexture.draw(canvas, x, y, width, height);
-    }
-
-    @Override
-    public void noDraw() {
-        // do nothing
-    }
-
-    @Override
-    public void recycle() {
-        mBitmapTexture.recycle();
-    }
-
-    @Override
-    public void draw(GLCanvas canvas, RectF source, RectF dest) {
-        canvas.drawTexture(mBitmapTexture, source, dest);
-    }
-}
diff --git a/src/com/android/gallery3d/ui/BitmapTileProvider.java b/src/com/android/gallery3d/ui/BitmapTileProvider.java
deleted file mode 100644
index e1a8b76..0000000
--- a/src/com/android/gallery3d/ui/BitmapTileProvider.java
+++ /dev/null
@@ -1,103 +0,0 @@
-/*
- * Copyright (C) 2010 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.gallery3d.ui;
-
-import android.graphics.Bitmap;
-import android.graphics.Bitmap.Config;
-import android.graphics.Canvas;
-
-import com.android.gallery3d.common.BitmapUtils;
-import com.android.photos.data.GalleryBitmapPool;
-
-import java.util.ArrayList;
-
-public class BitmapTileProvider implements TileImageView.TileSource {
-    private final ScreenNail mScreenNail;
-    private final Bitmap[] mMipmaps;
-    private final Config mConfig;
-    private final int mImageWidth;
-    private final int mImageHeight;
-
-    private boolean mRecycled = false;
-
-    public BitmapTileProvider(Bitmap bitmap, int maxBackupSize) {
-        mImageWidth = bitmap.getWidth();
-        mImageHeight = bitmap.getHeight();
-        ArrayList<Bitmap> list = new ArrayList<Bitmap>();
-        list.add(bitmap);
-        while (bitmap.getWidth() > maxBackupSize
-                || bitmap.getHeight() > maxBackupSize) {
-            bitmap = BitmapUtils.resizeBitmapByScale(bitmap, 0.5f, false);
-            list.add(bitmap);
-        }
-
-        mScreenNail = new BitmapScreenNail(list.remove(list.size() - 1));
-        mMipmaps = list.toArray(new Bitmap[list.size()]);
-        mConfig = Config.ARGB_8888;
-    }
-
-    @Override
-    public ScreenNail getScreenNail() {
-        return mScreenNail;
-    }
-
-    @Override
-    public int getImageHeight() {
-        return mImageHeight;
-    }
-
-    @Override
-    public int getImageWidth() {
-        return mImageWidth;
-    }
-
-    @Override
-    public int getLevelCount() {
-        return mMipmaps.length;
-    }
-
-    @Override
-    public Bitmap getTile(int level, int x, int y, int tileSize) {
-        x >>= level;
-        y >>= level;
-
-        Bitmap result = GalleryBitmapPool.getInstance().get(tileSize, tileSize);
-        if (result == null) {
-            result = Bitmap.createBitmap(tileSize, tileSize, mConfig);
-        } else {
-            result.eraseColor(0);
-        }
-
-        Bitmap mipmap = mMipmaps[level];
-        Canvas canvas = new Canvas(result);
-        int offsetX = -x;
-        int offsetY = -y;
-        canvas.drawBitmap(mipmap, offsetX, offsetY, null);
-        return result;
-    }
-
-    public void recycle() {
-        if (mRecycled) return;
-        mRecycled = true;
-        for (Bitmap bitmap : mMipmaps) {
-            BitmapUtils.recycleSilently(bitmap);
-        }
-        if (mScreenNail != null) {
-            mScreenNail.recycle();
-        }
-    }
-}
diff --git a/src/com/android/gallery3d/ui/CacheStorageUsageInfo.java b/src/com/android/gallery3d/ui/CacheStorageUsageInfo.java
deleted file mode 100644
index 46f7a24..0000000
--- a/src/com/android/gallery3d/ui/CacheStorageUsageInfo.java
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * Copyright (C) 2010 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.gallery3d.ui;
-
-import android.content.Context;
-import android.os.StatFs;
-
-import com.android.gallery3d.app.AbstractGalleryActivity;
-import com.android.gallery3d.util.ThreadPool.JobContext;
-
-import java.io.File;
-
-public class CacheStorageUsageInfo {
-    @SuppressWarnings("unused")
-    private static final String TAG = "CacheStorageUsageInfo";
-
-    // number of bytes the storage has.
-    private long mTotalBytes;
-
-    // number of bytes already used.
-    private long mUsedBytes;
-
-    // number of bytes used for the cache (should be less then usedBytes).
-    private long mUsedCacheBytes;
-
-    // number of bytes used for the cache if all pending downloads (and removals) are completed.
-    private long mTargetCacheBytes;
-
-    private AbstractGalleryActivity mActivity;
-    private Context mContext;
-    private long mUserChangeDelta;
-
-    public CacheStorageUsageInfo(AbstractGalleryActivity activity) {
-        mActivity = activity;
-        mContext = activity.getAndroidContext();
-    }
-
-    public void increaseTargetCacheSize(long delta) {
-        mUserChangeDelta += delta;
-    }
-
-    public void loadStorageInfo(JobContext jc) {
-        File cacheDir = mContext.getExternalCacheDir();
-        if (cacheDir == null) {
-            cacheDir = mContext.getCacheDir();
-        }
-
-        String path = cacheDir.getAbsolutePath();
-        StatFs stat = new StatFs(path);
-        long blockSize = stat.getBlockSize();
-        long availableBlocks = stat.getAvailableBlocks();
-        long totalBlocks = stat.getBlockCount();
-
-        mTotalBytes = blockSize * totalBlocks;
-        mUsedBytes = blockSize * (totalBlocks - availableBlocks);
-        mUsedCacheBytes = mActivity.getDataManager().getTotalUsedCacheSize();
-        mTargetCacheBytes = mActivity.getDataManager().getTotalTargetCacheSize();
-    }
-
-    public long getTotalBytes() {
-        return mTotalBytes;
-    }
-
-    public long getExpectedUsedBytes() {
-        return mUsedBytes - mUsedCacheBytes + mTargetCacheBytes + mUserChangeDelta;
-    }
-
-    public long getUsedBytes() {
-        // Should it be usedBytes - usedCacheBytes + targetCacheBytes ?
-        return mUsedBytes;
-    }
-
-    public long getFreeBytes() {
-        return mTotalBytes - mUsedBytes;
-    }
-}
diff --git a/src/com/android/gallery3d/ui/CaptureAnimation.java b/src/com/android/gallery3d/ui/CaptureAnimation.java
deleted file mode 100644
index 87c054a..0000000
--- a/src/com/android/gallery3d/ui/CaptureAnimation.java
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * 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.gallery3d.ui;
-
-import android.view.animation.AccelerateDecelerateInterpolator;
-import android.view.animation.AccelerateInterpolator;
-import android.view.animation.DecelerateInterpolator;
-import android.view.animation.Interpolator;
-
-public class CaptureAnimation {
-    // The amount of change for zooming out.
-    private static final float ZOOM_DELTA = 0.2f;
-    // Pre-calculated value for convenience.
-    private static final float ZOOM_IN_BEGIN = 1f - ZOOM_DELTA;
-
-    private static final Interpolator sZoomOutInterpolator =
-            new DecelerateInterpolator();
-    private static final Interpolator sZoomInInterpolator =
-            new AccelerateInterpolator();
-    private static final Interpolator sSlideInterpolator =
-        new AccelerateDecelerateInterpolator();
-
-    // Calculate the slide factor based on the give time fraction.
-    public static float calculateSlide(float fraction) {
-        return sSlideInterpolator.getInterpolation(fraction);
-    }
-
-    // Calculate the scale factor based on the given time fraction.
-    public static float calculateScale(float fraction) {
-        float value;
-        if (fraction <= 0.5f) {
-            // Zoom in for the beginning.
-            value = 1f - ZOOM_DELTA *
-                    sZoomOutInterpolator.getInterpolation(fraction * 2);
-        } else {
-            // Zoom out for the ending.
-            value = ZOOM_IN_BEGIN + ZOOM_DELTA *
-                    sZoomInInterpolator.getInterpolation((fraction - 0.5f) * 2f);
-        }
-        return value;
-    }
-}
diff --git a/src/com/android/gallery3d/ui/DetailsAddressResolver.java b/src/com/android/gallery3d/ui/DetailsAddressResolver.java
deleted file mode 100644
index 8de6677..0000000
--- a/src/com/android/gallery3d/ui/DetailsAddressResolver.java
+++ /dev/null
@@ -1,118 +0,0 @@
-/*
- * Copyright (C) 2011 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.gallery3d.ui;
-
-import android.content.Context;
-import android.location.Address;
-import android.os.Handler;
-import android.os.Looper;
-
-import com.android.gallery3d.app.AbstractGalleryActivity;
-import com.android.gallery3d.data.MediaDetails;
-import com.android.gallery3d.util.Future;
-import com.android.gallery3d.util.FutureListener;
-import com.android.gallery3d.util.GalleryUtils;
-import com.android.gallery3d.util.ReverseGeocoder;
-import com.android.gallery3d.util.ThreadPool.Job;
-import com.android.gallery3d.util.ThreadPool.JobContext;
-
-public class DetailsAddressResolver {
-    private AddressResolvingListener mListener;
-    private final AbstractGalleryActivity mContext;
-    private Future<Address> mAddressLookupJob;
-    private final Handler mHandler;
-
-    private class AddressLookupJob implements Job<Address> {
-        private double[] mLatlng;
-
-        protected AddressLookupJob(double[] latlng) {
-            mLatlng = latlng;
-        }
-
-        @Override
-        public Address run(JobContext jc) {
-            ReverseGeocoder geocoder = new ReverseGeocoder(mContext.getAndroidContext());
-            return geocoder.lookupAddress(mLatlng[0], mLatlng[1], true);
-        }
-    }
-
-    public interface AddressResolvingListener {
-        public void onAddressAvailable(String address);
-    }
-
-    public DetailsAddressResolver(AbstractGalleryActivity context) {
-        mContext = context;
-        mHandler = new Handler(Looper.getMainLooper());
-    }
-
-    public String resolveAddress(double[] latlng, AddressResolvingListener listener) {
-        mListener = listener;
-        mAddressLookupJob = mContext.getThreadPool().submit(
-                new AddressLookupJob(latlng),
-                new FutureListener<Address>() {
-                    @Override
-                    public void onFutureDone(final Future<Address> future) {
-                        mAddressLookupJob = null;
-                        if (!future.isCancelled()) {
-                            mHandler.post(new Runnable() {
-                                @Override
-                                public void run() {
-                                    updateLocation(future.get());
-                                }
-                            });
-                        }
-                    }
-                });
-        return GalleryUtils.formatLatitudeLongitude("(%f,%f)", latlng[0], latlng[1]);
-    }
-
-    private void updateLocation(Address address) {
-        if (address != null) {
-            Context context = mContext.getAndroidContext();
-            String parts[] = {
-                address.getAdminArea(),
-                address.getSubAdminArea(),
-                address.getLocality(),
-                address.getSubLocality(),
-                address.getThoroughfare(),
-                address.getSubThoroughfare(),
-                address.getPremises(),
-                address.getPostalCode(),
-                address.getCountryName()
-            };
-
-            String addressText = "";
-            for (int i = 0; i < parts.length; i++) {
-                if (parts[i] == null || parts[i].isEmpty()) continue;
-                if (!addressText.isEmpty()) {
-                    addressText += ", ";
-                }
-                addressText += parts[i];
-            }
-            String text = String.format("%s : %s", DetailsHelper.getDetailsName(
-                    context, MediaDetails.INDEX_LOCATION), addressText);
-            mListener.onAddressAvailable(text);
-        }
-    }
-
-    public void cancel() {
-        if (mAddressLookupJob != null) {
-            mAddressLookupJob.cancel();
-            mAddressLookupJob = null;
-        }
-    }
-}
diff --git a/src/com/android/gallery3d/ui/DetailsHelper.java b/src/com/android/gallery3d/ui/DetailsHelper.java
deleted file mode 100644
index 47296f6..0000000
--- a/src/com/android/gallery3d/ui/DetailsHelper.java
+++ /dev/null
@@ -1,148 +0,0 @@
-/*
- * Copyright (C) 2010 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.gallery3d.ui;
-
-import android.content.Context;
-import android.graphics.Bitmap;
-import android.graphics.BitmapFactory;
-import android.view.View.MeasureSpec;
-
-import com.android.gallery3d.R;
-import com.android.gallery3d.app.AbstractGalleryActivity;
-import com.android.gallery3d.data.MediaDetails;
-import com.android.gallery3d.ui.DetailsAddressResolver.AddressResolvingListener;
-
-public class DetailsHelper {
-    private static DetailsAddressResolver sAddressResolver;
-    private DetailsViewContainer mContainer;
-
-    public interface DetailsSource {
-        public int size();
-        public int setIndex();
-        public MediaDetails getDetails();
-    }
-
-    public interface CloseListener {
-        public void onClose();
-    }
-
-    public interface DetailsViewContainer {
-        public void reloadDetails();
-        public void setCloseListener(CloseListener listener);
-        public void show();
-        public void hide();
-    }
-
-    public interface ResolutionResolvingListener {
-        public void onResolutionAvailable(int width, int height);
-    }
-
-    public DetailsHelper(AbstractGalleryActivity activity, GLView rootPane, DetailsSource source) {
-        mContainer = new DialogDetailsView(activity, source);
-    }
-
-    public void layout(int left, int top, int right, int bottom) {
-        if (mContainer instanceof GLView) {
-            GLView view = (GLView) mContainer;
-            view.measure(MeasureSpec.UNSPECIFIED,
-                    MeasureSpec.makeMeasureSpec(bottom - top, MeasureSpec.AT_MOST));
-            view.layout(0, top, view.getMeasuredWidth(), top + view.getMeasuredHeight());
-        }
-    }
-
-    public void reloadDetails() {
-        mContainer.reloadDetails();
-    }
-
-    public void setCloseListener(CloseListener listener) {
-        mContainer.setCloseListener(listener);
-    }
-
-    public static String resolveAddress(AbstractGalleryActivity activity, double[] latlng,
-            AddressResolvingListener listener) {
-        if (sAddressResolver == null) {
-            sAddressResolver = new DetailsAddressResolver(activity);
-        } else {
-            sAddressResolver.cancel();
-        }
-        return sAddressResolver.resolveAddress(latlng, listener);
-    }
-
-    public static void resolveResolution(String path, ResolutionResolvingListener listener) {
-        Bitmap bitmap = BitmapFactory.decodeFile(path);
-        if (bitmap == null) return;
-        listener.onResolutionAvailable(bitmap.getWidth(), bitmap.getHeight());
-    }
-
-    public static void pause() {
-        if (sAddressResolver != null) sAddressResolver.cancel();
-    }
-
-    public void show() {
-        mContainer.show();
-    }
-
-    public void hide() {
-        mContainer.hide();
-    }
-
-    public static String getDetailsName(Context context, int key) {
-        switch (key) {
-            case MediaDetails.INDEX_TITLE:
-                return context.getString(R.string.title);
-            case MediaDetails.INDEX_DESCRIPTION:
-                return context.getString(R.string.description);
-            case MediaDetails.INDEX_DATETIME:
-                return context.getString(R.string.time);
-            case MediaDetails.INDEX_LOCATION:
-                return context.getString(R.string.location);
-            case MediaDetails.INDEX_PATH:
-                return context.getString(R.string.path);
-            case MediaDetails.INDEX_WIDTH:
-                return context.getString(R.string.width);
-            case MediaDetails.INDEX_HEIGHT:
-                return context.getString(R.string.height);
-            case MediaDetails.INDEX_ORIENTATION:
-                return context.getString(R.string.orientation);
-            case MediaDetails.INDEX_DURATION:
-                return context.getString(R.string.duration);
-            case MediaDetails.INDEX_MIMETYPE:
-                return context.getString(R.string.mimetype);
-            case MediaDetails.INDEX_SIZE:
-                return context.getString(R.string.file_size);
-            case MediaDetails.INDEX_MAKE:
-                return context.getString(R.string.maker);
-            case MediaDetails.INDEX_MODEL:
-                return context.getString(R.string.model);
-            case MediaDetails.INDEX_FLASH:
-                return context.getString(R.string.flash);
-            case MediaDetails.INDEX_APERTURE:
-                return context.getString(R.string.aperture);
-            case MediaDetails.INDEX_FOCAL_LENGTH:
-                return context.getString(R.string.focal_length);
-            case MediaDetails.INDEX_WHITE_BALANCE:
-                return context.getString(R.string.white_balance);
-            case MediaDetails.INDEX_EXPOSURE_TIME:
-                return context.getString(R.string.exposure_time);
-            case MediaDetails.INDEX_ISO:
-                return context.getString(R.string.iso);
-            default:
-                return "Unknown key" + key;
-        }
-    }
-}
-
-
diff --git a/src/com/android/gallery3d/ui/DialogDetailsView.java b/src/com/android/gallery3d/ui/DialogDetailsView.java
deleted file mode 100644
index 058c036..0000000
--- a/src/com/android/gallery3d/ui/DialogDetailsView.java
+++ /dev/null
@@ -1,288 +0,0 @@
-/*
- * Copyright (C) 2011 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.gallery3d.ui;
-
-import android.app.AlertDialog;
-import android.app.Dialog;
-import android.content.Context;
-import android.content.DialogInterface;
-import android.content.DialogInterface.OnDismissListener;
-import android.text.format.Formatter;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.BaseAdapter;
-import android.widget.ListView;
-import android.widget.TextView;
-
-import com.android.gallery3d.R;
-import com.android.gallery3d.app.AbstractGalleryActivity;
-import com.android.gallery3d.common.Utils;
-import com.android.gallery3d.data.MediaDetails;
-import com.android.gallery3d.ui.DetailsAddressResolver.AddressResolvingListener;
-import com.android.gallery3d.ui.DetailsHelper.CloseListener;
-import com.android.gallery3d.ui.DetailsHelper.DetailsSource;
-import com.android.gallery3d.ui.DetailsHelper.DetailsViewContainer;
-import com.android.gallery3d.ui.DetailsHelper.ResolutionResolvingListener;
-
-import java.util.ArrayList;
-import java.util.Map.Entry;
-
-public class DialogDetailsView implements DetailsViewContainer {
-    @SuppressWarnings("unused")
-    private static final String TAG = "DialogDetailsView";
-
-    private final AbstractGalleryActivity mActivity;
-    private DetailsAdapter mAdapter;
-    private MediaDetails mDetails;
-    private final DetailsSource mSource;
-    private int mIndex;
-    private Dialog mDialog;
-    private CloseListener mListener;
-
-    public DialogDetailsView(AbstractGalleryActivity activity, DetailsSource source) {
-        mActivity = activity;
-        mSource = source;
-    }
-
-    @Override
-    public void show() {
-        reloadDetails();
-        mDialog.show();
-    }
-
-    @Override
-    public void hide() {
-        mDialog.hide();
-    }
-
-    @Override
-    public void reloadDetails() {
-        int index = mSource.setIndex();
-        if (index == -1) return;
-        MediaDetails details = mSource.getDetails();
-        if (details != null) {
-            if (mIndex == index && mDetails == details) return;
-            mIndex = index;
-            mDetails = details;
-            setDetails(details);
-        }
-    }
-
-    private void setDetails(MediaDetails details) {
-        mAdapter = new DetailsAdapter(details);
-        String title = String.format(
-                mActivity.getAndroidContext().getString(R.string.details_title),
-                mIndex + 1, mSource.size());
-        ListView detailsList = (ListView) LayoutInflater.from(mActivity.getAndroidContext()).inflate(
-                R.layout.details_list, null, false);
-        detailsList.setAdapter(mAdapter);
-        mDialog = new AlertDialog.Builder(mActivity)
-            .setView(detailsList)
-            .setTitle(title)
-            .setPositiveButton(R.string.close, new DialogInterface.OnClickListener() {
-                @Override
-                public void onClick(DialogInterface dialog, int whichButton) {
-                    mDialog.dismiss();
-                }
-            })
-            .create();
-
-        mDialog.setOnDismissListener(new OnDismissListener() {
-            @Override
-            public void onDismiss(DialogInterface dialog) {
-                if (mListener != null) {
-                    mListener.onClose();
-                }
-            }
-        });
-    }
-
-
-    private class DetailsAdapter extends BaseAdapter
-        implements AddressResolvingListener, ResolutionResolvingListener {
-        private final ArrayList<String> mItems;
-        private int mLocationIndex;
-        private int mWidthIndex = -1;
-        private int mHeightIndex = -1;
-
-        public DetailsAdapter(MediaDetails details) {
-            Context context = mActivity.getAndroidContext();
-            mItems = new ArrayList<String>(details.size());
-            mLocationIndex = -1;
-            setDetails(context, details);
-        }
-
-        private void setDetails(Context context, MediaDetails details) {
-            boolean resolutionIsValid = true;
-            String path = null;
-            for (Entry<Integer, Object> detail : details) {
-                String value;
-                switch (detail.getKey()) {
-                    case MediaDetails.INDEX_LOCATION: {
-                        double[] latlng = (double[]) detail.getValue();
-                        mLocationIndex = mItems.size();
-                        value = DetailsHelper.resolveAddress(mActivity, latlng, this);
-                        break;
-                    }
-                    case MediaDetails.INDEX_SIZE: {
-                        value = Formatter.formatFileSize(
-                                context, (Long) detail.getValue());
-                        break;
-                    }
-                    case MediaDetails.INDEX_WHITE_BALANCE: {
-                        value = "1".equals(detail.getValue())
-                                ? context.getString(R.string.manual)
-                                : context.getString(R.string.auto);
-                        break;
-                    }
-                    case MediaDetails.INDEX_FLASH: {
-                        MediaDetails.FlashState flash =
-                                (MediaDetails.FlashState) detail.getValue();
-                        // TODO: camera doesn't fill in the complete values, show more information
-                        // when it is fixed.
-                        if (flash.isFlashFired()) {
-                            value = context.getString(R.string.flash_on);
-                        } else {
-                            value = context.getString(R.string.flash_off);
-                        }
-                        break;
-                    }
-                    case MediaDetails.INDEX_EXPOSURE_TIME: {
-                        value = (String) detail.getValue();
-                        double time = Double.valueOf(value);
-                        if (time < 1.0f) {
-                            value = String.format("1/%d", (int) (0.5f + 1 / time));
-                        } else {
-                            int integer = (int) time;
-                            time -= integer;
-                            value = String.valueOf(integer) + "''";
-                            if (time > 0.0001) {
-                                value += String.format(" 1/%d", (int) (0.5f + 1 / time));
-                            }
-                        }
-                        break;
-                    }
-                    case MediaDetails.INDEX_WIDTH:
-                        mWidthIndex = mItems.size();
-                        value = detail.getValue().toString();
-                        if (value.equalsIgnoreCase("0")) {
-                            value = context.getString(R.string.unknown);
-                            resolutionIsValid = false;
-                        }
-                        break;
-                    case MediaDetails.INDEX_HEIGHT: {
-                        mHeightIndex = mItems.size();
-                        value = detail.getValue().toString();
-                        if (value.equalsIgnoreCase("0")) {
-                            value = context.getString(R.string.unknown);
-                            resolutionIsValid = false;
-                        }
-                        break;
-                    }
-                    case MediaDetails.INDEX_PATH:
-                        // Get the path and then fall through to the default case
-                        path = detail.getValue().toString();
-                    default: {
-                        Object valueObj = detail.getValue();
-                        // This shouldn't happen, log its key to help us diagnose the problem.
-                        if (valueObj == null) {
-                            Utils.fail("%s's value is Null",
-                                    DetailsHelper.getDetailsName(context, detail.getKey()));
-                        }
-                        value = valueObj.toString();
-                    }
-                }
-                int key = detail.getKey();
-                if (details.hasUnit(key)) {
-                    value = String.format("%s: %s %s", DetailsHelper.getDetailsName(
-                            context, key), value, context.getString(details.getUnit(key)));
-                } else {
-                    value = String.format("%s: %s", DetailsHelper.getDetailsName(
-                            context, key), value);
-                }
-                mItems.add(value);
-                if (!resolutionIsValid) {
-                    DetailsHelper.resolveResolution(path, this);
-                }
-            }
-        }
-
-        @Override
-        public boolean areAllItemsEnabled() {
-            return false;
-        }
-
-        @Override
-        public boolean isEnabled(int position) {
-            return false;
-        }
-
-        @Override
-        public int getCount() {
-            return mItems.size();
-        }
-
-        @Override
-        public Object getItem(int position) {
-            return mDetails.getDetail(position);
-        }
-
-        @Override
-        public long getItemId(int position) {
-            return position;
-        }
-
-        @Override
-        public View getView(int position, View convertView, ViewGroup parent) {
-            TextView tv;
-            if (convertView == null) {
-                tv = (TextView) LayoutInflater.from(mActivity.getAndroidContext()).inflate(
-                        R.layout.details, parent, false);
-            } else {
-                tv = (TextView) convertView;
-            }
-            tv.setText(mItems.get(position));
-            return tv;
-        }
-
-        @Override
-        public void onAddressAvailable(String address) {
-            mItems.set(mLocationIndex, address);
-            notifyDataSetChanged();
-        }
-
-        @Override
-        public void onResolutionAvailable(int width, int height) {
-            if (width == 0 || height == 0) return;
-            // Update the resolution with the new width and height
-            Context context = mActivity.getAndroidContext();
-            String widthString = String.format("%s: %d", DetailsHelper.getDetailsName(
-                    context, MediaDetails.INDEX_WIDTH), width);
-            String heightString = String.format("%s: %d", DetailsHelper.getDetailsName(
-                    context, MediaDetails.INDEX_HEIGHT), height);
-            mItems.set(mWidthIndex, String.valueOf(widthString));
-            mItems.set(mHeightIndex, String.valueOf(heightString));
-            notifyDataSetChanged();
-        }
-    }
-
-    @Override
-    public void setCloseListener(CloseListener listener) {
-        mListener = listener;
-    }
-}
diff --git a/src/com/android/gallery3d/ui/DownUpDetector.java b/src/com/android/gallery3d/ui/DownUpDetector.java
deleted file mode 100644
index 19db772..0000000
--- a/src/com/android/gallery3d/ui/DownUpDetector.java
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Copyright (C) 2010 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.gallery3d.ui;
-
-import android.view.MotionEvent;
-
-public class DownUpDetector {
-    public interface DownUpListener {
-        void onDown(MotionEvent e);
-        void onUp(MotionEvent e);
-    }
-
-    private boolean mStillDown;
-    private DownUpListener mListener;
-
-    public DownUpDetector(DownUpListener listener) {
-        mListener = listener;
-    }
-
-    private void setState(boolean down, MotionEvent e) {
-        if (down == mStillDown) return;
-        mStillDown = down;
-        if (down) {
-            mListener.onDown(e);
-        } else {
-            mListener.onUp(e);
-        }
-    }
-
-    public void onTouchEvent(MotionEvent ev) {
-        switch (ev.getAction() & MotionEvent.ACTION_MASK) {
-        case MotionEvent.ACTION_DOWN:
-            setState(true, ev);
-            break;
-
-        case MotionEvent.ACTION_UP:
-        case MotionEvent.ACTION_CANCEL:
-        case MotionEvent.ACTION_POINTER_DOWN:  // Multitouch event - abort.
-            setState(false, ev);
-            break;
-        }
-    }
-
-    public boolean isDown() {
-        return mStillDown;
-    }
-}
diff --git a/src/com/android/gallery3d/ui/EdgeEffect.java b/src/com/android/gallery3d/ui/EdgeEffect.java
deleted file mode 100644
index 87ff0c5..0000000
--- a/src/com/android/gallery3d/ui/EdgeEffect.java
+++ /dev/null
@@ -1,443 +0,0 @@
-/*
- * Copyright (C) 2011 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.gallery3d.ui;
-
-import android.content.Context;
-import android.graphics.Canvas;
-import android.graphics.Rect;
-import android.view.animation.DecelerateInterpolator;
-import android.view.animation.Interpolator;
-
-import com.android.gallery3d.R;
-import com.android.gallery3d.glrenderer.GLCanvas;
-import com.android.gallery3d.glrenderer.ResourceTexture;
-
-// This is copied from android.widget.EdgeEffect with some small modifications:
-// (1) Copy the images (overscroll_{edge|glow}.png) to local resources.
-// (2) Use "GLCanvas" instead of "Canvas" for draw()'s parameter.
-// (3) Use a private Drawable class (which inherits from ResourceTexture)
-//     instead of android.graphics.drawable.Drawable to hold the images.
-//     The private Drawable class is used to translate original Canvas calls to
-//     corresponding GLCanvas calls.
-
-/**
- * This class performs the graphical effect used at the edges of scrollable widgets
- * when the user scrolls beyond the content bounds in 2D space.
- *
- * <p>EdgeEffect is stateful. Custom widgets using EdgeEffect should create an
- * instance for each edge that should show the effect, feed it input data using
- * the methods {@link #onAbsorb(int)}, {@link #onPull(float)}, and {@link #onRelease()},
- * and draw the effect using {@link #draw(Canvas)} in the widget's overridden
- * {@link android.view.View#draw(Canvas)} method. If {@link #isFinished()} returns
- * false after drawing, the edge effect's animation is not yet complete and the widget
- * should schedule another drawing pass to continue the animation.</p>
- *
- * <p>When drawing, widgets should draw their main content and child views first,
- * usually by invoking <code>super.draw(canvas)</code> from an overridden <code>draw</code>
- * method. (This will invoke onDraw and dispatch drawing to child views as needed.)
- * The edge effect may then be drawn on top of the view's content using the
- * {@link #draw(Canvas)} method.</p>
- */
-public class EdgeEffect {
-    @SuppressWarnings("unused")
-    private static final String TAG = "EdgeEffect";
-
-    // Time it will take the effect to fully recede in ms
-    private static final int RECEDE_TIME = 1000;
-
-    // Time it will take before a pulled glow begins receding in ms
-    private static final int PULL_TIME = 167;
-
-    // Time it will take in ms for a pulled glow to decay to partial strength before release
-    private static final int PULL_DECAY_TIME = 1000;
-
-    private static final float MAX_ALPHA = 0.8f;
-    private static final float HELD_EDGE_ALPHA = 0.7f;
-    private static final float HELD_EDGE_SCALE_Y = 0.5f;
-    private static final float HELD_GLOW_ALPHA = 0.5f;
-    private static final float HELD_GLOW_SCALE_Y = 0.5f;
-
-    private static final float MAX_GLOW_HEIGHT = 4.f;
-
-    private static final float PULL_GLOW_BEGIN = 1.f;
-    private static final float PULL_EDGE_BEGIN = 0.6f;
-
-    // Minimum velocity that will be absorbed
-    private static final int MIN_VELOCITY = 100;
-
-    private static final float EPSILON = 0.001f;
-
-    private final Drawable mEdge;
-    private final Drawable mGlow;
-    private int mWidth;
-    private int mHeight;
-    private final int MIN_WIDTH = 300;
-    private final int mMinWidth;
-
-    private float mEdgeAlpha;
-    private float mEdgeScaleY;
-    private float mGlowAlpha;
-    private float mGlowScaleY;
-
-    private float mEdgeAlphaStart;
-    private float mEdgeAlphaFinish;
-    private float mEdgeScaleYStart;
-    private float mEdgeScaleYFinish;
-    private float mGlowAlphaStart;
-    private float mGlowAlphaFinish;
-    private float mGlowScaleYStart;
-    private float mGlowScaleYFinish;
-
-    private long mStartTime;
-    private float mDuration;
-
-    private final Interpolator mInterpolator;
-
-    private static final int STATE_IDLE = 0;
-    private static final int STATE_PULL = 1;
-    private static final int STATE_ABSORB = 2;
-    private static final int STATE_RECEDE = 3;
-    private static final int STATE_PULL_DECAY = 4;
-
-    // How much dragging should effect the height of the edge image.
-    // Number determined by user testing.
-    private static final int PULL_DISTANCE_EDGE_FACTOR = 7;
-
-    // How much dragging should effect the height of the glow image.
-    // Number determined by user testing.
-    private static final int PULL_DISTANCE_GLOW_FACTOR = 7;
-    private static final float PULL_DISTANCE_ALPHA_GLOW_FACTOR = 1.1f;
-
-    private static final int VELOCITY_EDGE_FACTOR = 8;
-    private static final int VELOCITY_GLOW_FACTOR = 16;
-
-    private int mState = STATE_IDLE;
-
-    private float mPullDistance;
-
-    /**
-     * Construct a new EdgeEffect with a theme appropriate for the provided context.
-     * @param context Context used to provide theming and resource information for the EdgeEffect
-     */
-    public EdgeEffect(Context context) {
-        mEdge = new Drawable(context, R.drawable.overscroll_edge);
-        mGlow = new Drawable(context, R.drawable.overscroll_glow);
-
-        mMinWidth = (int) (context.getResources().getDisplayMetrics().density * MIN_WIDTH + 0.5f);
-        mInterpolator = new DecelerateInterpolator();
-    }
-
-    /**
-     * Set the size of this edge effect in pixels.
-     *
-     * @param width Effect width in pixels
-     * @param height Effect height in pixels
-     */
-    public void setSize(int width, int height) {
-        mWidth = width;
-        mHeight = height;
-    }
-
-    /**
-     * Reports if this EdgeEffect's animation is finished. If this method returns false
-     * after a call to {@link #draw(Canvas)} the host widget should schedule another
-     * drawing pass to continue the animation.
-     *
-     * @return true if animation is finished, false if drawing should continue on the next frame.
-     */
-    public boolean isFinished() {
-        return mState == STATE_IDLE;
-    }
-
-    /**
-     * Immediately finish the current animation.
-     * After this call {@link #isFinished()} will return true.
-     */
-    public void finish() {
-        mState = STATE_IDLE;
-    }
-
-    /**
-     * A view should call this when content is pulled away from an edge by the user.
-     * This will update the state of the current visual effect and its associated animation.
-     * The host view should always {@link android.view.View#invalidate()} after this
-     * and draw the results accordingly.
-     *
-     * @param deltaDistance Change in distance since the last call. Values may be 0 (no change) to
-     *                      1.f (full length of the view) or negative values to express change
-     *                      back toward the edge reached to initiate the effect.
-     */
-    public void onPull(float deltaDistance) {
-        final long now = AnimationTime.get();
-        if (mState == STATE_PULL_DECAY && now - mStartTime < mDuration) {
-            return;
-        }
-        if (mState != STATE_PULL) {
-            mGlowScaleY = PULL_GLOW_BEGIN;
-        }
-        mState = STATE_PULL;
-
-        mStartTime = now;
-        mDuration = PULL_TIME;
-
-        mPullDistance += deltaDistance;
-        float distance = Math.abs(mPullDistance);
-
-        mEdgeAlpha = mEdgeAlphaStart = Math.max(PULL_EDGE_BEGIN, Math.min(distance, MAX_ALPHA));
-        mEdgeScaleY = mEdgeScaleYStart = Math.max(
-                HELD_EDGE_SCALE_Y, Math.min(distance * PULL_DISTANCE_EDGE_FACTOR, 1.f));
-
-        mGlowAlpha = mGlowAlphaStart = Math.min(MAX_ALPHA,
-                mGlowAlpha +
-                (Math.abs(deltaDistance) * PULL_DISTANCE_ALPHA_GLOW_FACTOR));
-
-        float glowChange = Math.abs(deltaDistance);
-        if (deltaDistance > 0 && mPullDistance < 0) {
-            glowChange = -glowChange;
-        }
-        if (mPullDistance == 0) {
-            mGlowScaleY = 0;
-        }
-
-        // Do not allow glow to get larger than MAX_GLOW_HEIGHT.
-        mGlowScaleY = mGlowScaleYStart = Math.min(MAX_GLOW_HEIGHT, Math.max(
-                0, mGlowScaleY + glowChange * PULL_DISTANCE_GLOW_FACTOR));
-
-        mEdgeAlphaFinish = mEdgeAlpha;
-        mEdgeScaleYFinish = mEdgeScaleY;
-        mGlowAlphaFinish = mGlowAlpha;
-        mGlowScaleYFinish = mGlowScaleY;
-    }
-
-    /**
-     * Call when the object is released after being pulled.
-     * This will begin the "decay" phase of the effect. After calling this method
-     * the host view should {@link android.view.View#invalidate()} and thereby
-     * draw the results accordingly.
-     */
-    public void onRelease() {
-        mPullDistance = 0;
-
-        if (mState != STATE_PULL && mState != STATE_PULL_DECAY) {
-            return;
-        }
-
-        mState = STATE_RECEDE;
-        mEdgeAlphaStart = mEdgeAlpha;
-        mEdgeScaleYStart = mEdgeScaleY;
-        mGlowAlphaStart = mGlowAlpha;
-        mGlowScaleYStart = mGlowScaleY;
-
-        mEdgeAlphaFinish = 0.f;
-        mEdgeScaleYFinish = 0.f;
-        mGlowAlphaFinish = 0.f;
-        mGlowScaleYFinish = 0.f;
-
-        mStartTime = AnimationTime.get();
-        mDuration = RECEDE_TIME;
-    }
-
-    /**
-     * Call when the effect absorbs an impact at the given velocity.
-     * Used when a fling reaches the scroll boundary.
-     *
-     * <p>When using a {@link android.widget.Scroller} or {@link android.widget.OverScroller},
-     * the method <code>getCurrVelocity</code> will provide a reasonable approximation
-     * to use here.</p>
-     *
-     * @param velocity Velocity at impact in pixels per second.
-     */
-    public void onAbsorb(int velocity) {
-        mState = STATE_ABSORB;
-        velocity = Math.max(MIN_VELOCITY, Math.abs(velocity));
-
-        mStartTime = AnimationTime.get();
-        mDuration = 0.1f + (velocity * 0.03f);
-
-        // The edge should always be at least partially visible, regardless
-        // of velocity.
-        mEdgeAlphaStart = 0.f;
-        mEdgeScaleY = mEdgeScaleYStart = 0.f;
-        // The glow depends more on the velocity, and therefore starts out
-        // nearly invisible.
-        mGlowAlphaStart = 0.5f;
-        mGlowScaleYStart = 0.f;
-
-        // Factor the velocity by 8. Testing on device shows this works best to
-        // reflect the strength of the user's scrolling.
-        mEdgeAlphaFinish = Math.max(0, Math.min(velocity * VELOCITY_EDGE_FACTOR, 1));
-        // Edge should never get larger than the size of its asset.
-        mEdgeScaleYFinish = Math.max(
-                HELD_EDGE_SCALE_Y, Math.min(velocity * VELOCITY_EDGE_FACTOR, 1.f));
-
-        // Growth for the size of the glow should be quadratic to properly
-        // respond
-        // to a user's scrolling speed. The faster the scrolling speed, the more
-        // intense the effect should be for both the size and the saturation.
-        mGlowScaleYFinish = Math.min(0.025f + (velocity * (velocity / 100) * 0.00015f), 1.75f);
-        // Alpha should change for the glow as well as size.
-        mGlowAlphaFinish = Math.max(
-                mGlowAlphaStart, Math.min(velocity * VELOCITY_GLOW_FACTOR * .00001f, MAX_ALPHA));
-    }
-
-
-    /**
-     * Draw into the provided canvas. Assumes that the canvas has been rotated
-     * accordingly and the size has been set. The effect will be drawn the full
-     * width of X=0 to X=width, beginning from Y=0 and extending to some factor <
-     * 1.f of height.
-     *
-     * @param canvas Canvas to draw into
-     * @return true if drawing should continue beyond this frame to continue the
-     *         animation
-     */
-    public boolean draw(GLCanvas canvas) {
-        update();
-
-        final int edgeHeight = mEdge.getIntrinsicHeight();
-        final int edgeWidth = mEdge.getIntrinsicWidth();
-        final int glowHeight = mGlow.getIntrinsicHeight();
-        final int glowWidth = mGlow.getIntrinsicWidth();
-
-        mGlow.setAlpha((int) (Math.max(0, Math.min(mGlowAlpha, 1)) * 255));
-
-        int glowBottom = (int) Math.min(
-                glowHeight * mGlowScaleY * glowHeight/ glowWidth * 0.6f,
-                glowHeight * MAX_GLOW_HEIGHT);
-        if (mWidth < mMinWidth) {
-            // Center the glow and clip it.
-            int glowLeft = (mWidth - mMinWidth)/2;
-            mGlow.setBounds(glowLeft, 0, mWidth - glowLeft, glowBottom);
-        } else {
-            // Stretch the glow to fit.
-            mGlow.setBounds(0, 0, mWidth, glowBottom);
-        }
-
-        mGlow.draw(canvas);
-
-        mEdge.setAlpha((int) (Math.max(0, Math.min(mEdgeAlpha, 1)) * 255));
-
-        int edgeBottom = (int) (edgeHeight * mEdgeScaleY);
-        if (mWidth < mMinWidth) {
-            // Center the edge and clip it.
-            int edgeLeft = (mWidth - mMinWidth)/2;
-            mEdge.setBounds(edgeLeft, 0, mWidth - edgeLeft, edgeBottom);
-        } else {
-            // Stretch the edge to fit.
-            mEdge.setBounds(0, 0, mWidth, edgeBottom);
-        }
-        mEdge.draw(canvas);
-
-        return mState != STATE_IDLE;
-    }
-
-    private void update() {
-        final long time = AnimationTime.get();
-        final float t = Math.min((time - mStartTime) / mDuration, 1.f);
-
-        final float interp = mInterpolator.getInterpolation(t);
-
-        mEdgeAlpha = mEdgeAlphaStart + (mEdgeAlphaFinish - mEdgeAlphaStart) * interp;
-        mEdgeScaleY = mEdgeScaleYStart + (mEdgeScaleYFinish - mEdgeScaleYStart) * interp;
-        mGlowAlpha = mGlowAlphaStart + (mGlowAlphaFinish - mGlowAlphaStart) * interp;
-        mGlowScaleY = mGlowScaleYStart + (mGlowScaleYFinish - mGlowScaleYStart) * interp;
-
-        if (t >= 1.f - EPSILON) {
-            switch (mState) {
-                case STATE_ABSORB:
-                    mState = STATE_RECEDE;
-                    mStartTime = AnimationTime.get();
-                    mDuration = RECEDE_TIME;
-
-                    mEdgeAlphaStart = mEdgeAlpha;
-                    mEdgeScaleYStart = mEdgeScaleY;
-                    mGlowAlphaStart = mGlowAlpha;
-                    mGlowScaleYStart = mGlowScaleY;
-
-                    // After absorb, the glow and edge should fade to nothing.
-                    mEdgeAlphaFinish = 0.f;
-                    mEdgeScaleYFinish = 0.f;
-                    mGlowAlphaFinish = 0.f;
-                    mGlowScaleYFinish = 0.f;
-                    break;
-                case STATE_PULL:
-                    mState = STATE_PULL_DECAY;
-                    mStartTime = AnimationTime.get();
-                    mDuration = PULL_DECAY_TIME;
-
-                    mEdgeAlphaStart = mEdgeAlpha;
-                    mEdgeScaleYStart = mEdgeScaleY;
-                    mGlowAlphaStart = mGlowAlpha;
-                    mGlowScaleYStart = mGlowScaleY;
-
-                    // After pull, the glow and edge should fade to nothing.
-                    mEdgeAlphaFinish = 0.f;
-                    mEdgeScaleYFinish = 0.f;
-                    mGlowAlphaFinish = 0.f;
-                    mGlowScaleYFinish = 0.f;
-                    break;
-                case STATE_PULL_DECAY:
-                    // When receding, we want edge to decrease more slowly
-                    // than the glow.
-                    float factor = mGlowScaleYFinish != 0 ? 1
-                            / (mGlowScaleYFinish * mGlowScaleYFinish)
-                            : Float.MAX_VALUE;
-                    mEdgeScaleY = mEdgeScaleYStart +
-                        (mEdgeScaleYFinish - mEdgeScaleYStart) *
-                            interp * factor;
-                    mState = STATE_RECEDE;
-                    break;
-                case STATE_RECEDE:
-                    mState = STATE_IDLE;
-                    break;
-            }
-        }
-    }
-
-    private static class Drawable extends ResourceTexture {
-        private Rect mBounds = new Rect();
-        private int mAlpha = 255;
-
-        public Drawable(Context context, int resId) {
-            super(context, resId);
-        }
-
-        public int getIntrinsicWidth() {
-            return getWidth();
-        }
-
-        public int getIntrinsicHeight() {
-            return getHeight();
-        }
-
-        public void setBounds(int left, int top, int right, int bottom) {
-            mBounds.set(left, top, right, bottom);
-        }
-
-        public void setAlpha(int alpha) {
-            mAlpha = alpha;
-        }
-
-        public void draw(GLCanvas canvas) {
-            canvas.save(GLCanvas.SAVE_FLAG_ALPHA);
-            canvas.multiplyAlpha(mAlpha / 255.0f);
-            Rect b = mBounds;
-            draw(canvas, b.left, b.top, b.width(), b.height());
-            canvas.restore();
-        }
-    }
-}
diff --git a/src/com/android/gallery3d/ui/EdgeView.java b/src/com/android/gallery3d/ui/EdgeView.java
deleted file mode 100644
index 051de18..0000000
--- a/src/com/android/gallery3d/ui/EdgeView.java
+++ /dev/null
@@ -1,132 +0,0 @@
-/*
- * Copyright (C) 2011 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.gallery3d.ui;
-
-import android.content.Context;
-import android.opengl.Matrix;
-
-import com.android.gallery3d.glrenderer.GLCanvas;
-
-// EdgeView draws EdgeEffect (blue glow) at four sides of the view.
-public class EdgeView extends GLView {
-    @SuppressWarnings("unused")
-    private static final String TAG = "EdgeView";
-
-    public static final int INVALID_DIRECTION = -1;
-    public static final int TOP = 0;
-    public static final int LEFT = 1;
-    public static final int BOTTOM = 2;
-    public static final int RIGHT = 3;
-
-    // Each edge effect has a transform matrix, and each matrix has 16 elements.
-    // We put all the elements in one array. These constants specify the
-    // starting index of each matrix.
-    private static final int TOP_M = TOP * 16;
-    private static final int LEFT_M = LEFT * 16;
-    private static final int BOTTOM_M = BOTTOM * 16;
-    private static final int RIGHT_M = RIGHT * 16;
-
-    private EdgeEffect[] mEffect = new EdgeEffect[4];
-    private float[] mMatrix = new float[4 * 16];
-
-    public EdgeView(Context context) {
-        for (int i = 0; i < 4; i++) {
-            mEffect[i] = new EdgeEffect(context);
-        }
-    }
-
-    @Override
-    protected void onLayout(
-            boolean changeSize, int left, int top, int right, int bottom) {
-        if (!changeSize) return;
-
-        int w = right - left;
-        int h = bottom - top;
-        for (int i = 0; i < 4; i++) {
-            if ((i & 1) == 0) {  // top or bottom
-                mEffect[i].setSize(w, h);
-            } else {  // left or right
-                mEffect[i].setSize(h, w);
-            }
-        }
-
-        // Set up transforms for the four edges. Without transforms an
-        // EdgeEffect draws the TOP edge from (0, 0) to (w, Y * h) where Y
-        // is some factor < 1. For other edges we need to move, rotate, and
-        // flip the effects into proper places.
-        Matrix.setIdentityM(mMatrix, TOP_M);
-        Matrix.setIdentityM(mMatrix, LEFT_M);
-        Matrix.setIdentityM(mMatrix, BOTTOM_M);
-        Matrix.setIdentityM(mMatrix, RIGHT_M);
-
-        Matrix.rotateM(mMatrix, LEFT_M, 90, 0, 0, 1);
-        Matrix.scaleM(mMatrix, LEFT_M, 1, -1, 1);
-
-        Matrix.translateM(mMatrix, BOTTOM_M, 0, h, 0);
-        Matrix.scaleM(mMatrix, BOTTOM_M, 1, -1, 1);
-
-        Matrix.translateM(mMatrix, RIGHT_M, w, 0, 0);
-        Matrix.rotateM(mMatrix, RIGHT_M, 90, 0, 0, 1);
-    }
-
-    @Override
-    protected void render(GLCanvas canvas) {
-        super.render(canvas);
-        boolean more = false;
-        for (int i = 0; i < 4; i++) {
-            canvas.save(GLCanvas.SAVE_FLAG_MATRIX);
-            canvas.multiplyMatrix(mMatrix, i * 16);
-            more |= mEffect[i].draw(canvas);
-            canvas.restore();
-        }
-        if (more) {
-            invalidate();
-        }
-    }
-
-    // Called when the content is pulled away from the edge.
-    // offset is in pixels. direction is one of {TOP, LEFT, BOTTOM, RIGHT}.
-    public void onPull(int offset, int direction) {
-        int fullLength = ((direction & 1) == 0) ? getWidth() : getHeight();
-        mEffect[direction].onPull((float)offset / fullLength);
-        if (!mEffect[direction].isFinished()) {
-            invalidate();
-        }
-    }
-
-    // Call when the object is released after being pulled.
-    public void onRelease() {
-        boolean more = false;
-        for (int i = 0; i < 4; i++) {
-            mEffect[i].onRelease();
-            more |= !mEffect[i].isFinished();
-        }
-        if (more) {
-            invalidate();
-        }
-    }
-
-    // Call when the effect absorbs an impact at the given velocity.
-    // Used when a fling reaches the scroll boundary. velocity is in pixels
-    // per second. direction is one of {TOP, LEFT, BOTTOM, RIGHT}.
-    public void onAbsorb(int velocity, int direction) {
-        mEffect[direction].onAbsorb(velocity);
-        if (!mEffect[direction].isFinished()) {
-            invalidate();
-        }
-    }
-}
diff --git a/src/com/android/gallery3d/ui/FlingScroller.java b/src/com/android/gallery3d/ui/FlingScroller.java
deleted file mode 100644
index 6f98c64..0000000
--- a/src/com/android/gallery3d/ui/FlingScroller.java
+++ /dev/null
@@ -1,141 +0,0 @@
-/*
- * Copyright (C) 2011 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.gallery3d.ui;
-
-
-// This is a customized version of Scroller, with a interface similar to
-// android.widget.Scroller. It does fling only, not scroll.
-//
-// The differences between the this Scroller and the system one are:
-//
-// (1) The velocity does not change because of min/max limit.
-// (2) The duration is different.
-// (3) The deceleration curve is different.
-class FlingScroller {
-    @SuppressWarnings("unused")
-    private static final String TAG = "FlingController";
-
-    // The fling duration (in milliseconds) when velocity is 1 pixel/second
-    private static final float FLING_DURATION_PARAM = 50f;
-    private static final int DECELERATED_FACTOR = 4;
-
-    private int mStartX, mStartY;
-    private int mMinX, mMinY, mMaxX, mMaxY;
-    private double mSinAngle;
-    private double mCosAngle;
-    private int mDuration;
-    private int mDistance;
-    private int mFinalX, mFinalY;
-
-    private int mCurrX, mCurrY;
-    private double mCurrV;
-
-    public int getFinalX() {
-        return mFinalX;
-    }
-
-    public int getFinalY() {
-        return mFinalY;
-    }
-
-    public int getDuration() {
-        return mDuration;
-    }
-
-    public int getCurrX() {
-        return mCurrX;
-
-    }
-
-    public int getCurrY() {
-        return mCurrY;
-    }
-
-    public int getCurrVelocityX() {
-        return (int)Math.round(mCurrV * mCosAngle);
-    }
-
-    public int getCurrVelocityY() {
-        return (int)Math.round(mCurrV * mSinAngle);
-    }
-
-    public void fling(int startX, int startY, int velocityX, int velocityY,
-            int minX, int maxX, int minY, int maxY) {
-        mStartX = startX;
-        mStartY = startY;
-        mMinX = minX;
-        mMinY = minY;
-        mMaxX = maxX;
-        mMaxY = maxY;
-
-        double velocity = Math.hypot(velocityX, velocityY);
-        mSinAngle = velocityY / velocity;
-        mCosAngle = velocityX / velocity;
-        //
-        // The position formula: x(t) = s + (e - s) * (1 - (1 - t / T) ^ d)
-        //     velocity formula: v(t) = d * (e - s) * (1 - t / T) ^ (d - 1) / T
-        // Thus,
-        //     v0 = d * (e - s) / T => (e - s) = v0 * T / d
-        //
-
-        // Ta = T_ref * (Va / V_ref) ^ (1 / (d - 1)); V_ref = 1 pixel/second;
-        mDuration = (int)Math.round(FLING_DURATION_PARAM
-                * Math.pow(Math.abs(velocity), 1.0 / (DECELERATED_FACTOR - 1)));
-
-        // (e - s) = v0 * T / d
-        mDistance = (int)Math.round(
-                velocity * mDuration / DECELERATED_FACTOR / 1000);
-
-        mFinalX = getX(1.0f);
-        mFinalY = getY(1.0f);
-    }
-
-    public void computeScrollOffset(float progress) {
-        progress = Math.min(progress, 1);
-        float f = 1 - progress;
-        f = 1 - (float) Math.pow(f, DECELERATED_FACTOR);
-        mCurrX = getX(f);
-        mCurrY = getY(f);
-        mCurrV = getV(progress);
-    }
-
-    private int getX(float f) {
-        int r = (int) Math.round(mStartX + f * mDistance * mCosAngle);
-        if (mCosAngle > 0 && mStartX <= mMaxX) {
-            r = Math.min(r, mMaxX);
-        } else if (mCosAngle < 0 && mStartX >= mMinX) {
-            r = Math.max(r, mMinX);
-        }
-        return r;
-    }
-
-    private int getY(float f) {
-        int r = (int) Math.round(mStartY + f * mDistance * mSinAngle);
-        if (mSinAngle > 0 && mStartY <= mMaxY) {
-            r = Math.min(r, mMaxY);
-        } else if (mSinAngle < 0 && mStartY >= mMinY) {
-            r = Math.max(r, mMinY);
-        }
-        return r;
-    }
-
-    private double getV(float progress) {
-        // velocity formula: v(t) = d * (e - s) * (1 - t / T) ^ (d - 1) / T
-        return DECELERATED_FACTOR * mDistance * 1000 *
-                Math.pow(1 - progress, DECELERATED_FACTOR - 1) / mDuration;
-    }
-}
diff --git a/src/com/android/gallery3d/ui/GLRoot.java b/src/com/android/gallery3d/ui/GLRoot.java
deleted file mode 100644
index 33a82ea..0000000
--- a/src/com/android/gallery3d/ui/GLRoot.java
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Copyright (C) 2010 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.gallery3d.ui;
-
-import android.content.Context;
-import android.graphics.Matrix;
-
-import com.android.gallery3d.anim.CanvasAnimation;
-import com.android.gallery3d.glrenderer.GLCanvas;
-
-public interface GLRoot {
-
-    // Listener will be called when GL is idle AND before each frame.
-    // Mainly used for uploading textures.
-    public static interface OnGLIdleListener {
-        public boolean onGLIdle(
-                GLCanvas canvas, boolean renderRequested);
-    }
-
-    public void addOnGLIdleListener(OnGLIdleListener listener);
-    public void registerLaunchedAnimation(CanvasAnimation animation);
-    public void requestRenderForced();
-    public void requestRender();
-    public void requestLayoutContentPane();
-
-    public void lockRenderThread();
-    public void unlockRenderThread();
-
-    public void setContentPane(GLView content);
-    public void setOrientationSource(OrientationSource source);
-    public int getDisplayRotation();
-    public int getCompensation();
-    public Matrix getCompensationMatrix();
-    public void freeze();
-    public void unfreeze();
-    public void setLightsOutMode(boolean enabled);
-
-    public Context getContext();
-}
diff --git a/src/com/android/gallery3d/ui/GLRootView.java b/src/com/android/gallery3d/ui/GLRootView.java
deleted file mode 100644
index dc898d8..0000000
--- a/src/com/android/gallery3d/ui/GLRootView.java
+++ /dev/null
@@ -1,630 +0,0 @@
-/*
- * Copyright (C) 2010 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.gallery3d.ui;
-
-import android.annotation.TargetApi;
-import android.content.Context;
-import android.graphics.Matrix;
-import android.graphics.PixelFormat;
-import android.opengl.GLSurfaceView;
-import android.os.Build;
-import android.os.Process;
-import android.os.SystemClock;
-import android.util.AttributeSet;
-import android.view.MotionEvent;
-import android.view.SurfaceHolder;
-import android.view.View;
-
-import com.android.gallery3d.R;
-import com.android.gallery3d.anim.CanvasAnimation;
-import com.android.gallery3d.common.ApiHelper;
-import com.android.gallery3d.common.Utils;
-import com.android.gallery3d.glrenderer.BasicTexture;
-import com.android.gallery3d.glrenderer.GLCanvas;
-import com.android.gallery3d.glrenderer.GLES11Canvas;
-import com.android.gallery3d.glrenderer.GLES20Canvas;
-import com.android.gallery3d.glrenderer.UploadedTexture;
-import com.android.gallery3d.util.GalleryUtils;
-import com.android.gallery3d.util.MotionEventHelper;
-import com.android.gallery3d.util.Profile;
-
-import java.util.ArrayDeque;
-import java.util.ArrayList;
-import java.util.concurrent.locks.Condition;
-import java.util.concurrent.locks.ReentrantLock;
-
-import javax.microedition.khronos.egl.EGLConfig;
-import javax.microedition.khronos.opengles.GL10;
-import javax.microedition.khronos.opengles.GL11;
-
-// The root component of all <code>GLView</code>s. The rendering is done in GL
-// thread while the event handling is done in the main thread.  To synchronize
-// the two threads, the entry points of this package need to synchronize on the
-// <code>GLRootView</code> instance unless it can be proved that the rendering
-// thread won't access the same thing as the method. The entry points include:
-// (1) The public methods of HeadUpDisplay
-// (2) The public methods of CameraHeadUpDisplay
-// (3) The overridden methods in GLRootView.
-public class GLRootView extends GLSurfaceView
-        implements GLSurfaceView.Renderer, GLRoot {
-    private static final String TAG = "GLRootView";
-
-    private static final boolean DEBUG_FPS = false;
-    private int mFrameCount = 0;
-    private long mFrameCountingStart = 0;
-
-    private static final boolean DEBUG_INVALIDATE = false;
-    private int mInvalidateColor = 0;
-
-    private static final boolean DEBUG_DRAWING_STAT = false;
-
-    private static final boolean DEBUG_PROFILE = false;
-    private static final boolean DEBUG_PROFILE_SLOW_ONLY = false;
-
-    private static final int FLAG_INITIALIZED = 1;
-    private static final int FLAG_NEED_LAYOUT = 2;
-
-    private GL11 mGL;
-    private GLCanvas mCanvas;
-    private GLView mContentView;
-
-    private OrientationSource mOrientationSource;
-    // mCompensation is the difference between the UI orientation on GLCanvas
-    // and the framework orientation. See OrientationManager for details.
-    private int mCompensation;
-    // mCompensationMatrix maps the coordinates of touch events. It is kept sync
-    // with mCompensation.
-    private Matrix mCompensationMatrix = new Matrix();
-    private int mDisplayRotation;
-
-    private int mFlags = FLAG_NEED_LAYOUT;
-    private volatile boolean mRenderRequested = false;
-
-    private final ArrayList<CanvasAnimation> mAnimations =
-            new ArrayList<CanvasAnimation>();
-
-    private final ArrayDeque<OnGLIdleListener> mIdleListeners =
-            new ArrayDeque<OnGLIdleListener>();
-
-    private final IdleRunner mIdleRunner = new IdleRunner();
-
-    private final ReentrantLock mRenderLock = new ReentrantLock();
-    private final Condition mFreezeCondition =
-            mRenderLock.newCondition();
-    private boolean mFreeze;
-
-    private long mLastDrawFinishTime;
-    private boolean mInDownState = false;
-    private boolean mFirstDraw = true;
-
-    public GLRootView(Context context) {
-        this(context, null);
-    }
-
-    public GLRootView(Context context, AttributeSet attrs) {
-        super(context, attrs);
-        mFlags |= FLAG_INITIALIZED;
-        setBackgroundDrawable(null);
-        setEGLContextClientVersion(ApiHelper.HAS_GLES20_REQUIRED ? 2 : 1);
-        if (ApiHelper.USE_888_PIXEL_FORMAT) {
-            setEGLConfigChooser(8, 8, 8, 0, 0, 0);
-        } else {
-            setEGLConfigChooser(5, 6, 5, 0, 0, 0);
-        }
-        setRenderer(this);
-        if (ApiHelper.USE_888_PIXEL_FORMAT) {
-            getHolder().setFormat(PixelFormat.RGB_888);
-        } else {
-            getHolder().setFormat(PixelFormat.RGB_565);
-        }
-
-        // Uncomment this to enable gl error check.
-        // setDebugFlags(DEBUG_CHECK_GL_ERROR);
-    }
-
-    @Override
-    public void registerLaunchedAnimation(CanvasAnimation animation) {
-        // Register the newly launched animation so that we can set the start
-        // time more precisely. (Usually, it takes much longer for first
-        // rendering, so we set the animation start time as the time we
-        // complete rendering)
-        mAnimations.add(animation);
-    }
-
-    @Override
-    public void addOnGLIdleListener(OnGLIdleListener listener) {
-        synchronized (mIdleListeners) {
-            mIdleListeners.addLast(listener);
-            mIdleRunner.enable();
-        }
-    }
-
-    @Override
-    public void setContentPane(GLView content) {
-        if (mContentView == content) return;
-        if (mContentView != null) {
-            if (mInDownState) {
-                long now = SystemClock.uptimeMillis();
-                MotionEvent cancelEvent = MotionEvent.obtain(
-                        now, now, MotionEvent.ACTION_CANCEL, 0, 0, 0);
-                mContentView.dispatchTouchEvent(cancelEvent);
-                cancelEvent.recycle();
-                mInDownState = false;
-            }
-            mContentView.detachFromRoot();
-            BasicTexture.yieldAllTextures();
-        }
-        mContentView = content;
-        if (content != null) {
-            content.attachToRoot(this);
-            requestLayoutContentPane();
-        }
-    }
-
-    @Override
-    public void requestRenderForced() {
-        superRequestRender();
-    }
-
-    @Override
-    public void requestRender() {
-        if (DEBUG_INVALIDATE) {
-            StackTraceElement e = Thread.currentThread().getStackTrace()[4];
-            String caller = e.getFileName() + ":" + e.getLineNumber() + " ";
-            Log.d(TAG, "invalidate: " + caller);
-        }
-        if (mRenderRequested) return;
-        mRenderRequested = true;
-        if (ApiHelper.HAS_POST_ON_ANIMATION) {
-            postOnAnimation(mRequestRenderOnAnimationFrame);
-        } else {
-            super.requestRender();
-        }
-    }
-
-    private Runnable mRequestRenderOnAnimationFrame = new Runnable() {
-        @Override
-        public void run() {
-            superRequestRender();
-        }
-    };
-
-    private void superRequestRender() {
-        super.requestRender();
-    }
-
-    @Override
-    public void requestLayoutContentPane() {
-        mRenderLock.lock();
-        try {
-            if (mContentView == null || (mFlags & FLAG_NEED_LAYOUT) != 0) return;
-
-            // "View" system will invoke onLayout() for initialization(bug ?), we
-            // have to ignore it since the GLThread is not ready yet.
-            if ((mFlags & FLAG_INITIALIZED) == 0) return;
-
-            mFlags |= FLAG_NEED_LAYOUT;
-            requestRender();
-        } finally {
-            mRenderLock.unlock();
-        }
-    }
-
-    private void layoutContentPane() {
-        mFlags &= ~FLAG_NEED_LAYOUT;
-
-        int w = getWidth();
-        int h = getHeight();
-        int displayRotation = 0;
-        int compensation = 0;
-
-        // Get the new orientation values
-        if (mOrientationSource != null) {
-            displayRotation = mOrientationSource.getDisplayRotation();
-            compensation = mOrientationSource.getCompensation();
-        } else {
-            displayRotation = 0;
-            compensation = 0;
-        }
-
-        if (mCompensation != compensation) {
-            mCompensation = compensation;
-            if (mCompensation % 180 != 0) {
-                mCompensationMatrix.setRotate(mCompensation);
-                // move center to origin before rotation
-                mCompensationMatrix.preTranslate(-w / 2, -h / 2);
-                // align with the new origin after rotation
-                mCompensationMatrix.postTranslate(h / 2, w / 2);
-            } else {
-                mCompensationMatrix.setRotate(mCompensation, w / 2, h / 2);
-            }
-        }
-        mDisplayRotation = displayRotation;
-
-        // Do the actual layout.
-        if (mCompensation % 180 != 0) {
-            int tmp = w;
-            w = h;
-            h = tmp;
-        }
-        Log.i(TAG, "layout content pane " + w + "x" + h
-                + " (compensation " + mCompensation + ")");
-        if (mContentView != null && w != 0 && h != 0) {
-            mContentView.layout(0, 0, w, h);
-        }
-        // Uncomment this to dump the view hierarchy.
-        //mContentView.dumpTree("");
-    }
-
-    @Override
-    protected void onLayout(
-            boolean changed, int left, int top, int right, int bottom) {
-        if (changed) requestLayoutContentPane();
-    }
-
-    /**
-     * Called when the context is created, possibly after automatic destruction.
-     */
-    // This is a GLSurfaceView.Renderer callback
-    @Override
-    public void onSurfaceCreated(GL10 gl1, EGLConfig config) {
-        GL11 gl = (GL11) gl1;
-        if (mGL != null) {
-            // The GL Object has changed
-            Log.i(TAG, "GLObject has changed from " + mGL + " to " + gl);
-        }
-        mRenderLock.lock();
-        try {
-            mGL = gl;
-            mCanvas = ApiHelper.HAS_GLES20_REQUIRED ? new GLES20Canvas() : new GLES11Canvas(gl);
-            BasicTexture.invalidateAllTextures();
-        } finally {
-            mRenderLock.unlock();
-        }
-
-        if (DEBUG_FPS || DEBUG_PROFILE) {
-            setRenderMode(GLSurfaceView.RENDERMODE_CONTINUOUSLY);
-        } else {
-            setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY);
-        }
-    }
-
-    /**
-     * Called when the OpenGL surface is recreated without destroying the
-     * context.
-     */
-    // This is a GLSurfaceView.Renderer callback
-    @Override
-    public void onSurfaceChanged(GL10 gl1, int width, int height) {
-        Log.i(TAG, "onSurfaceChanged: " + width + "x" + height
-                + ", gl10: " + gl1.toString());
-        Process.setThreadPriority(Process.THREAD_PRIORITY_DISPLAY);
-        GalleryUtils.setRenderThread();
-        if (DEBUG_PROFILE) {
-            Log.d(TAG, "Start profiling");
-            Profile.enable(20);  // take a sample every 20ms
-        }
-        GL11 gl = (GL11) gl1;
-        Utils.assertTrue(mGL == gl);
-
-        mCanvas.setSize(width, height);
-    }
-
-    private void outputFps() {
-        long now = System.nanoTime();
-        if (mFrameCountingStart == 0) {
-            mFrameCountingStart = now;
-        } else if ((now - mFrameCountingStart) > 1000000000) {
-            Log.d(TAG, "fps: " + (double) mFrameCount
-                    * 1000000000 / (now - mFrameCountingStart));
-            mFrameCountingStart = now;
-            mFrameCount = 0;
-        }
-        ++mFrameCount;
-    }
-
-    @Override
-    public void onDrawFrame(GL10 gl) {
-        AnimationTime.update();
-        long t0;
-        if (DEBUG_PROFILE_SLOW_ONLY) {
-            Profile.hold();
-            t0 = System.nanoTime();
-        }
-        mRenderLock.lock();
-
-        while (mFreeze) {
-            mFreezeCondition.awaitUninterruptibly();
-        }
-
-        try {
-            onDrawFrameLocked(gl);
-        } finally {
-            mRenderLock.unlock();
-        }
-
-        // We put a black cover View in front of the SurfaceView and hide it
-        // after the first draw. This prevents the SurfaceView being transparent
-        // before the first draw.
-        if (mFirstDraw) {
-            mFirstDraw = false;
-            post(new Runnable() {
-                    @Override
-                    public void run() {
-                        View root = getRootView();
-                        View cover = root.findViewById(R.id.gl_root_cover);
-                        cover.setVisibility(GONE);
-                    }
-                });
-        }
-
-        if (DEBUG_PROFILE_SLOW_ONLY) {
-            long t = System.nanoTime();
-            long durationInMs = (t - mLastDrawFinishTime) / 1000000;
-            long durationDrawInMs = (t - t0) / 1000000;
-            mLastDrawFinishTime = t;
-
-            if (durationInMs > 34) {  // 34ms -> we skipped at least 2 frames
-                Log.v(TAG, "----- SLOW (" + durationDrawInMs + "/" +
-                        durationInMs + ") -----");
-                Profile.commit();
-            } else {
-                Profile.drop();
-            }
-        }
-    }
-
-    private void onDrawFrameLocked(GL10 gl) {
-        if (DEBUG_FPS) outputFps();
-
-        // release the unbound textures and deleted buffers.
-        mCanvas.deleteRecycledResources();
-
-        // reset texture upload limit
-        UploadedTexture.resetUploadLimit();
-
-        mRenderRequested = false;
-
-        if ((mOrientationSource != null
-                && mDisplayRotation != mOrientationSource.getDisplayRotation())
-                || (mFlags & FLAG_NEED_LAYOUT) != 0) {
-            layoutContentPane();
-        }
-
-        mCanvas.save(GLCanvas.SAVE_FLAG_ALL);
-        rotateCanvas(-mCompensation);
-        if (mContentView != null) {
-           mContentView.render(mCanvas);
-        } else {
-            // Make sure we always draw something to prevent displaying garbage
-            mCanvas.clearBuffer();
-        }
-        mCanvas.restore();
-
-        if (!mAnimations.isEmpty()) {
-            long now = AnimationTime.get();
-            for (int i = 0, n = mAnimations.size(); i < n; i++) {
-                mAnimations.get(i).setStartTime(now);
-            }
-            mAnimations.clear();
-        }
-
-        if (UploadedTexture.uploadLimitReached()) {
-            requestRender();
-        }
-
-        synchronized (mIdleListeners) {
-            if (!mIdleListeners.isEmpty()) mIdleRunner.enable();
-        }
-
-        if (DEBUG_INVALIDATE) {
-            mCanvas.fillRect(10, 10, 5, 5, mInvalidateColor);
-            mInvalidateColor = ~mInvalidateColor;
-        }
-
-        if (DEBUG_DRAWING_STAT) {
-            mCanvas.dumpStatisticsAndClear();
-        }
-    }
-
-    private void rotateCanvas(int degrees) {
-        if (degrees == 0) return;
-        int w = getWidth();
-        int h = getHeight();
-        int cx = w / 2;
-        int cy = h / 2;
-        mCanvas.translate(cx, cy);
-        mCanvas.rotate(degrees, 0, 0, 1);
-        if (degrees % 180 != 0) {
-            mCanvas.translate(-cy, -cx);
-        } else {
-            mCanvas.translate(-cx, -cy);
-        }
-    }
-
-    @Override
-    public boolean dispatchTouchEvent(MotionEvent event) {
-        if (!isEnabled()) return false;
-
-        int action = event.getAction();
-        if (action == MotionEvent.ACTION_CANCEL
-                || action == MotionEvent.ACTION_UP) {
-            mInDownState = false;
-        } else if (!mInDownState && action != MotionEvent.ACTION_DOWN) {
-            return false;
-        }
-
-        if (mCompensation != 0) {
-            event = MotionEventHelper.transformEvent(event, mCompensationMatrix);
-        }
-
-        mRenderLock.lock();
-        try {
-            // If this has been detached from root, we don't need to handle event
-            boolean handled = mContentView != null
-                    && mContentView.dispatchTouchEvent(event);
-            if (action == MotionEvent.ACTION_DOWN && handled) {
-                mInDownState = true;
-            }
-            return handled;
-        } finally {
-            mRenderLock.unlock();
-        }
-    }
-
-    private class IdleRunner implements Runnable {
-        // true if the idle runner is in the queue
-        private boolean mActive = false;
-
-        @Override
-        public void run() {
-            OnGLIdleListener listener;
-            synchronized (mIdleListeners) {
-                mActive = false;
-                if (mIdleListeners.isEmpty()) return;
-                listener = mIdleListeners.removeFirst();
-            }
-            mRenderLock.lock();
-            boolean keepInQueue;
-            try {
-                keepInQueue = listener.onGLIdle(mCanvas, mRenderRequested);
-            } finally {
-                mRenderLock.unlock();
-            }
-            synchronized (mIdleListeners) {
-                if (keepInQueue) mIdleListeners.addLast(listener);
-                if (!mRenderRequested && !mIdleListeners.isEmpty()) enable();
-            }
-        }
-
-        public void enable() {
-            // Who gets the flag can add it to the queue
-            if (mActive) return;
-            mActive = true;
-            queueEvent(this);
-        }
-    }
-
-    @Override
-    public void lockRenderThread() {
-        mRenderLock.lock();
-    }
-
-    @Override
-    public void unlockRenderThread() {
-        mRenderLock.unlock();
-    }
-
-    @Override
-    public void onPause() {
-        unfreeze();
-        super.onPause();
-        if (DEBUG_PROFILE) {
-            Log.d(TAG, "Stop profiling");
-            Profile.disableAll();
-            Profile.dumpToFile("/sdcard/gallery.prof");
-            Profile.reset();
-        }
-    }
-
-    @Override
-    public void setOrientationSource(OrientationSource source) {
-        mOrientationSource = source;
-    }
-
-    @Override
-    public int getDisplayRotation() {
-        return mDisplayRotation;
-    }
-
-    @Override
-    public int getCompensation() {
-        return mCompensation;
-    }
-
-    @Override
-    public Matrix getCompensationMatrix() {
-        return mCompensationMatrix;
-    }
-
-    @Override
-    public void freeze() {
-        mRenderLock.lock();
-        mFreeze = true;
-        mRenderLock.unlock();
-    }
-
-    @Override
-    public void unfreeze() {
-        mRenderLock.lock();
-        mFreeze = false;
-        mFreezeCondition.signalAll();
-        mRenderLock.unlock();
-    }
-
-    @Override
-    @TargetApi(Build.VERSION_CODES.JELLY_BEAN)
-    public void setLightsOutMode(boolean enabled) {
-        if (!ApiHelper.HAS_SET_SYSTEM_UI_VISIBILITY) return;
-
-        int flags = 0;
-        if (enabled) {
-            flags = STATUS_BAR_HIDDEN;
-            if (ApiHelper.HAS_VIEW_SYSTEM_UI_FLAG_LAYOUT_STABLE) {
-                flags |= (SYSTEM_UI_FLAG_FULLSCREEN | SYSTEM_UI_FLAG_LAYOUT_STABLE);
-            }
-        }
-        setSystemUiVisibility(flags);
-    }
-
-    // We need to unfreeze in the following methods and in onPause().
-    // These methods will wait on GLThread. If we have freezed the GLRootView,
-    // the GLThread will wait on main thread to call unfreeze and cause dead
-    // lock.
-    @Override
-    public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
-        unfreeze();
-        super.surfaceChanged(holder, format, w, h);
-    }
-
-    @Override
-    public void surfaceCreated(SurfaceHolder holder) {
-        unfreeze();
-        super.surfaceCreated(holder);
-    }
-
-    @Override
-    public void surfaceDestroyed(SurfaceHolder holder) {
-        unfreeze();
-        super.surfaceDestroyed(holder);
-    }
-
-    @Override
-    protected void onDetachedFromWindow() {
-        unfreeze();
-        super.onDetachedFromWindow();
-    }
-
-    @Override
-    protected void finalize() throws Throwable {
-        try {
-            unfreeze();
-        } finally {
-            super.finalize();
-        }
-    }
-}
diff --git a/src/com/android/gallery3d/ui/GLView.java b/src/com/android/gallery3d/ui/GLView.java
deleted file mode 100644
index 83de19f..0000000
--- a/src/com/android/gallery3d/ui/GLView.java
+++ /dev/null
@@ -1,465 +0,0 @@
-/*
- * Copyright (C) 2010 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.gallery3d.ui;
-
-import android.graphics.Rect;
-import android.os.SystemClock;
-import android.view.MotionEvent;
-
-import com.android.gallery3d.anim.CanvasAnimation;
-import com.android.gallery3d.anim.StateTransitionAnimation;
-import com.android.gallery3d.common.Utils;
-import com.android.gallery3d.glrenderer.GLCanvas;
-
-import java.util.ArrayList;
-
-// GLView is a UI component. It can render to a GLCanvas and accept touch
-// events. A GLView may have zero or more child GLView and they form a tree
-// structure. The rendering and event handling will pass through the tree
-// structure.
-//
-// A GLView tree should be attached to a GLRoot before event dispatching and
-// rendering happens. GLView asks GLRoot to re-render or re-layout the
-// GLView hierarchy using requestRender() and requestLayoutContentPane().
-//
-// The render() method is called in a separate thread. Before calling
-// dispatchTouchEvent() and layout(), GLRoot acquires a lock to avoid the
-// rendering thread running at the same time. If there are other entry points
-// from main thread (like a Handler) in your GLView, you need to call
-// lockRendering() if the rendering thread should not run at the same time.
-//
-public class GLView {
-    private static final String TAG = "GLView";
-
-    public static final int VISIBLE = 0;
-    public static final int INVISIBLE = 1;
-
-    private static final int FLAG_INVISIBLE = 1;
-    private static final int FLAG_SET_MEASURED_SIZE = 2;
-    private static final int FLAG_LAYOUT_REQUESTED = 4;
-
-    public interface OnClickListener {
-        void onClick(GLView v);
-    }
-
-    protected final Rect mBounds = new Rect();
-    protected final Rect mPaddings = new Rect();
-
-    private GLRoot mRoot;
-    protected GLView mParent;
-    private ArrayList<GLView> mComponents;
-    private GLView mMotionTarget;
-
-    private CanvasAnimation mAnimation;
-
-    private int mViewFlags = 0;
-
-    protected int mMeasuredWidth = 0;
-    protected int mMeasuredHeight = 0;
-
-    private int mLastWidthSpec = -1;
-    private int mLastHeightSpec = -1;
-
-    protected int mScrollY = 0;
-    protected int mScrollX = 0;
-    protected int mScrollHeight = 0;
-    protected int mScrollWidth = 0;
-
-    private float [] mBackgroundColor;
-    private StateTransitionAnimation mTransition;
-
-    public void startAnimation(CanvasAnimation animation) {
-        GLRoot root = getGLRoot();
-        if (root == null) throw new IllegalStateException();
-        mAnimation = animation;
-        if (mAnimation != null) {
-            mAnimation.start();
-            root.registerLaunchedAnimation(mAnimation);
-        }
-        invalidate();
-    }
-
-    // Sets the visiblity of this GLView (either GLView.VISIBLE or
-    // GLView.INVISIBLE).
-    public void setVisibility(int visibility) {
-        if (visibility == getVisibility()) return;
-        if (visibility == VISIBLE) {
-            mViewFlags &= ~FLAG_INVISIBLE;
-        } else {
-            mViewFlags |= FLAG_INVISIBLE;
-        }
-        onVisibilityChanged(visibility);
-        invalidate();
-    }
-
-    // Returns GLView.VISIBLE or GLView.INVISIBLE
-    public int getVisibility() {
-        return (mViewFlags & FLAG_INVISIBLE) == 0 ? VISIBLE : INVISIBLE;
-    }
-
-    // This should only be called on the content pane (the topmost GLView).
-    public void attachToRoot(GLRoot root) {
-        Utils.assertTrue(mParent == null && mRoot == null);
-        onAttachToRoot(root);
-    }
-
-    // This should only be called on the content pane (the topmost GLView).
-    public void detachFromRoot() {
-        Utils.assertTrue(mParent == null && mRoot != null);
-        onDetachFromRoot();
-    }
-
-    // Returns the number of children of the GLView.
-    public int getComponentCount() {
-        return mComponents == null ? 0 : mComponents.size();
-    }
-
-    // Returns the children for the given index.
-    public GLView getComponent(int index) {
-        if (mComponents == null) {
-            throw new ArrayIndexOutOfBoundsException(index);
-        }
-        return mComponents.get(index);
-    }
-
-    // Adds a child to this GLView.
-    public void addComponent(GLView component) {
-        // Make sure the component doesn't have a parent currently.
-        if (component.mParent != null) throw new IllegalStateException();
-
-        // Build parent-child links
-        if (mComponents == null) {
-            mComponents = new ArrayList<GLView>();
-        }
-        mComponents.add(component);
-        component.mParent = this;
-
-        // If this is added after we have a root, tell the component.
-        if (mRoot != null) {
-            component.onAttachToRoot(mRoot);
-        }
-    }
-
-    // Removes a child from this GLView.
-    public boolean removeComponent(GLView component) {
-        if (mComponents == null) return false;
-        if (mComponents.remove(component)) {
-            removeOneComponent(component);
-            return true;
-        }
-        return false;
-    }
-
-    // Removes all children of this GLView.
-    public void removeAllComponents() {
-        for (int i = 0, n = mComponents.size(); i < n; ++i) {
-            removeOneComponent(mComponents.get(i));
-        }
-        mComponents.clear();
-    }
-
-    private void removeOneComponent(GLView component) {
-        if (mMotionTarget == component) {
-            long now = SystemClock.uptimeMillis();
-            MotionEvent cancelEvent = MotionEvent.obtain(
-                    now, now, MotionEvent.ACTION_CANCEL, 0, 0, 0);
-            dispatchTouchEvent(cancelEvent);
-            cancelEvent.recycle();
-        }
-        component.onDetachFromRoot();
-        component.mParent = null;
-    }
-
-    public Rect bounds() {
-        return mBounds;
-    }
-
-    public int getWidth() {
-        return mBounds.right - mBounds.left;
-    }
-
-    public int getHeight() {
-        return mBounds.bottom - mBounds.top;
-    }
-
-    public GLRoot getGLRoot() {
-        return mRoot;
-    }
-
-    // Request re-rendering of the view hierarchy.
-    // This is used for animation or when the contents changed.
-    public void invalidate() {
-        GLRoot root = getGLRoot();
-        if (root != null) root.requestRender();
-    }
-
-    // Request re-layout of the view hierarchy.
-    public void requestLayout() {
-        mViewFlags |= FLAG_LAYOUT_REQUESTED;
-        mLastHeightSpec = -1;
-        mLastWidthSpec = -1;
-        if (mParent != null) {
-            mParent.requestLayout();
-        } else {
-            // Is this a content pane ?
-            GLRoot root = getGLRoot();
-            if (root != null) root.requestLayoutContentPane();
-        }
-    }
-
-    protected void render(GLCanvas canvas) {
-        boolean transitionActive = false;
-        if (mTransition != null && mTransition.calculate(AnimationTime.get())) {
-            invalidate();
-            transitionActive = mTransition.isActive();
-        }
-        renderBackground(canvas);
-        canvas.save();
-        if (transitionActive) {
-            mTransition.applyContentTransform(this, canvas);
-        }
-        for (int i = 0, n = getComponentCount(); i < n; ++i) {
-            renderChild(canvas, getComponent(i));
-        }
-        canvas.restore();
-        if (transitionActive) {
-            mTransition.applyOverlay(this, canvas);
-        }
-    }
-
-    public void setIntroAnimation(StateTransitionAnimation intro) {
-        mTransition = intro;
-        if (mTransition != null) mTransition.start();
-    }
-
-    public float [] getBackgroundColor() {
-        return mBackgroundColor;
-    }
-
-    public void setBackgroundColor(float [] color) {
-        mBackgroundColor = color;
-    }
-
-    protected void renderBackground(GLCanvas view) {
-        if (mBackgroundColor != null) {
-            view.clearBuffer(mBackgroundColor);
-        }
-        if (mTransition != null && mTransition.isActive()) {
-            mTransition.applyBackground(this, view);
-            return;
-        }
-    }
-
-    protected void renderChild(GLCanvas canvas, GLView component) {
-        if (component.getVisibility() != GLView.VISIBLE
-                && component.mAnimation == null) return;
-
-        int xoffset = component.mBounds.left - mScrollX;
-        int yoffset = component.mBounds.top - mScrollY;
-
-        canvas.translate(xoffset, yoffset);
-
-        CanvasAnimation anim = component.mAnimation;
-        if (anim != null) {
-            canvas.save(anim.getCanvasSaveFlags());
-            if (anim.calculate(AnimationTime.get())) {
-                invalidate();
-            } else {
-                component.mAnimation = null;
-            }
-            anim.apply(canvas);
-        }
-        component.render(canvas);
-        if (anim != null) canvas.restore();
-        canvas.translate(-xoffset, -yoffset);
-    }
-
-    protected boolean onTouch(MotionEvent event) {
-        return false;
-    }
-
-    protected boolean dispatchTouchEvent(MotionEvent event,
-            int x, int y, GLView component, boolean checkBounds) {
-        Rect rect = component.mBounds;
-        int left = rect.left;
-        int top = rect.top;
-        if (!checkBounds || rect.contains(x, y)) {
-            event.offsetLocation(-left, -top);
-            if (component.dispatchTouchEvent(event)) {
-                event.offsetLocation(left, top);
-                return true;
-            }
-            event.offsetLocation(left, top);
-        }
-        return false;
-    }
-
-    protected boolean dispatchTouchEvent(MotionEvent event) {
-        int x = (int) event.getX();
-        int y = (int) event.getY();
-        int action = event.getAction();
-        if (mMotionTarget != null) {
-            if (action == MotionEvent.ACTION_DOWN) {
-                MotionEvent cancel = MotionEvent.obtain(event);
-                cancel.setAction(MotionEvent.ACTION_CANCEL);
-                dispatchTouchEvent(cancel, x, y, mMotionTarget, false);
-                mMotionTarget = null;
-            } else {
-                dispatchTouchEvent(event, x, y, mMotionTarget, false);
-                if (action == MotionEvent.ACTION_CANCEL
-                        || action == MotionEvent.ACTION_UP) {
-                    mMotionTarget = null;
-                }
-                return true;
-            }
-        }
-        if (action == MotionEvent.ACTION_DOWN) {
-            // in the reverse rendering order
-            for (int i = getComponentCount() - 1; i >= 0; --i) {
-                GLView component = getComponent(i);
-                if (component.getVisibility() != GLView.VISIBLE) continue;
-                if (dispatchTouchEvent(event, x, y, component, true)) {
-                    mMotionTarget = component;
-                    return true;
-                }
-            }
-        }
-        return onTouch(event);
-    }
-
-    public Rect getPaddings() {
-        return mPaddings;
-    }
-
-    public void layout(int left, int top, int right, int bottom) {
-        boolean sizeChanged = setBounds(left, top, right, bottom);
-        mViewFlags &= ~FLAG_LAYOUT_REQUESTED;
-        // We call onLayout no matter sizeChanged is true or not because the
-        // orientation may change without changing the size of the View (for
-        // example, rotate the device by 180 degrees), and we want to handle
-        // orientation change in onLayout.
-        onLayout(sizeChanged, left, top, right, bottom);
-    }
-
-    private boolean setBounds(int left, int top, int right, int bottom) {
-        boolean sizeChanged = (right - left) != (mBounds.right - mBounds.left)
-                || (bottom - top) != (mBounds.bottom - mBounds.top);
-        mBounds.set(left, top, right, bottom);
-        return sizeChanged;
-    }
-
-    public void measure(int widthSpec, int heightSpec) {
-        if (widthSpec == mLastWidthSpec && heightSpec == mLastHeightSpec
-                && (mViewFlags & FLAG_LAYOUT_REQUESTED) == 0) {
-            return;
-        }
-
-        mLastWidthSpec = widthSpec;
-        mLastHeightSpec = heightSpec;
-
-        mViewFlags &= ~FLAG_SET_MEASURED_SIZE;
-        onMeasure(widthSpec, heightSpec);
-        if ((mViewFlags & FLAG_SET_MEASURED_SIZE) == 0) {
-            throw new IllegalStateException(getClass().getName()
-                    + " should call setMeasuredSize() in onMeasure()");
-        }
-    }
-
-    protected void onMeasure(int widthSpec, int heightSpec) {
-    }
-
-    protected void setMeasuredSize(int width, int height) {
-        mViewFlags |= FLAG_SET_MEASURED_SIZE;
-        mMeasuredWidth = width;
-        mMeasuredHeight = height;
-    }
-
-    public int getMeasuredWidth() {
-        return mMeasuredWidth;
-    }
-
-    public int getMeasuredHeight() {
-        return mMeasuredHeight;
-    }
-
-    protected void onLayout(
-            boolean changeSize, int left, int top, int right, int bottom) {
-    }
-
-    /**
-     * Gets the bounds of the given descendant that relative to this view.
-     */
-    public boolean getBoundsOf(GLView descendant, Rect out) {
-        int xoffset = 0;
-        int yoffset = 0;
-        GLView view = descendant;
-        while (view != this) {
-            if (view == null) return false;
-            Rect bounds = view.mBounds;
-            xoffset += bounds.left;
-            yoffset += bounds.top;
-            view = view.mParent;
-        }
-        out.set(xoffset, yoffset, xoffset + descendant.getWidth(),
-                yoffset + descendant.getHeight());
-        return true;
-    }
-
-    protected void onVisibilityChanged(int visibility) {
-        for (int i = 0, n = getComponentCount(); i < n; ++i) {
-            GLView child = getComponent(i);
-            if (child.getVisibility() == GLView.VISIBLE) {
-                child.onVisibilityChanged(visibility);
-            }
-        }
-    }
-
-    protected void onAttachToRoot(GLRoot root) {
-        mRoot = root;
-        for (int i = 0, n = getComponentCount(); i < n; ++i) {
-            getComponent(i).onAttachToRoot(root);
-        }
-    }
-
-    protected void onDetachFromRoot() {
-        for (int i = 0, n = getComponentCount(); i < n; ++i) {
-            getComponent(i).onDetachFromRoot();
-        }
-        mRoot = null;
-    }
-
-    public void lockRendering() {
-        if (mRoot != null) {
-            mRoot.lockRenderThread();
-        }
-    }
-
-    public void unlockRendering() {
-        if (mRoot != null) {
-            mRoot.unlockRenderThread();
-        }
-    }
-
-    // This is for debugging only.
-    // Dump the view hierarchy into log.
-    void dumpTree(String prefix) {
-        Log.d(TAG, prefix + getClass().getSimpleName());
-        for (int i = 0, n = getComponentCount(); i < n; ++i) {
-            getComponent(i).dumpTree(prefix + "....");
-        }
-    }
-}
diff --git a/src/com/android/gallery3d/ui/GestureRecognizer.java b/src/com/android/gallery3d/ui/GestureRecognizer.java
deleted file mode 100644
index 1e5250b..0000000
--- a/src/com/android/gallery3d/ui/GestureRecognizer.java
+++ /dev/null
@@ -1,132 +0,0 @@
-/*
- * 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.gallery3d.ui;
-
-import android.content.Context;
-import android.os.SystemClock;
-import android.view.GestureDetector;
-import android.view.MotionEvent;
-import android.view.ScaleGestureDetector;
-
-// This class aggregates three gesture detectors: GestureDetector,
-// ScaleGestureDetector, and DownUpDetector.
-public class GestureRecognizer {
-    @SuppressWarnings("unused")
-    private static final String TAG = "GestureRecognizer";
-
-    public interface Listener {
-        boolean onSingleTapUp(float x, float y);
-        boolean onDoubleTap(float x, float y);
-        boolean onScroll(float dx, float dy, float totalX, float totalY);
-        boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY);
-        boolean onScaleBegin(float focusX, float focusY);
-        boolean onScale(float focusX, float focusY, float scale);
-        void onScaleEnd();
-        void onDown(float x, float y);
-        void onUp();
-    }
-
-    private final GestureDetector mGestureDetector;
-    private final ScaleGestureDetector mScaleDetector;
-    private final DownUpDetector mDownUpDetector;
-    private final Listener mListener;
-
-    public GestureRecognizer(Context context, Listener listener) {
-        mListener = listener;
-        mGestureDetector = new GestureDetector(context, new MyGestureListener(),
-                null, true /* ignoreMultitouch */);
-        mScaleDetector = new ScaleGestureDetector(
-                context, new MyScaleListener());
-        mDownUpDetector = new DownUpDetector(new MyDownUpListener());
-    }
-
-    public void onTouchEvent(MotionEvent event) {
-        mGestureDetector.onTouchEvent(event);
-        mScaleDetector.onTouchEvent(event);
-        mDownUpDetector.onTouchEvent(event);
-    }
-
-    public boolean isDown() {
-        return mDownUpDetector.isDown();
-    }
-
-    public void cancelScale() {
-        long now = SystemClock.uptimeMillis();
-        MotionEvent cancelEvent = MotionEvent.obtain(
-                now, now, MotionEvent.ACTION_CANCEL, 0, 0, 0);
-        mScaleDetector.onTouchEvent(cancelEvent);
-        cancelEvent.recycle();
-    }
-
-    private class MyGestureListener
-                extends GestureDetector.SimpleOnGestureListener {
-        @Override
-        public boolean onSingleTapUp(MotionEvent e) {
-            return mListener.onSingleTapUp(e.getX(), e.getY());
-        }
-
-        @Override
-        public boolean onDoubleTap(MotionEvent e) {
-            return mListener.onDoubleTap(e.getX(), e.getY());
-        }
-
-        @Override
-        public boolean onScroll(
-                MotionEvent e1, MotionEvent e2, float dx, float dy) {
-            return mListener.onScroll(
-                    dx, dy, e2.getX() - e1.getX(), e2.getY() - e1.getY());
-        }
-
-        @Override
-        public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
-                float velocityY) {
-            return mListener.onFling(e1, e2, velocityX, velocityY);
-        }
-    }
-
-    private class MyScaleListener
-            extends ScaleGestureDetector.SimpleOnScaleGestureListener {
-        @Override
-        public boolean onScaleBegin(ScaleGestureDetector detector) {
-            return mListener.onScaleBegin(
-                    detector.getFocusX(), detector.getFocusY());
-        }
-
-        @Override
-        public boolean onScale(ScaleGestureDetector detector) {
-            return mListener.onScale(detector.getFocusX(),
-                    detector.getFocusY(), detector.getScaleFactor());
-        }
-
-        @Override
-        public void onScaleEnd(ScaleGestureDetector detector) {
-            mListener.onScaleEnd();
-        }
-    }
-
-    private class MyDownUpListener implements DownUpDetector.DownUpListener {
-        @Override
-        public void onDown(MotionEvent e) {
-            mListener.onDown(e.getX(), e.getY());
-        }
-
-        @Override
-        public void onUp(MotionEvent e) {
-            mListener.onUp();
-        }
-    }
-}
diff --git a/src/com/android/gallery3d/ui/Log.java b/src/com/android/gallery3d/ui/Log.java
deleted file mode 100644
index 5570763..0000000
--- a/src/com/android/gallery3d/ui/Log.java
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Copyright (C) 2010 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.gallery3d.ui;
-
-// TODO: Delete this
-public class Log {
-    public static int v(String tag, String msg) {
-        return android.util.Log.v(tag, msg);
-    }
-    public static int v(String tag, String msg, Throwable tr) {
-        return android.util.Log.v(tag, msg, tr);
-    }
-    public static int d(String tag, String msg) {
-        return android.util.Log.d(tag, msg);
-    }
-    public static int d(String tag, String msg, Throwable tr) {
-        return android.util.Log.d(tag, msg, tr);
-    }
-    public static int i(String tag, String msg) {
-        return android.util.Log.i(tag, msg);
-    }
-    public static int i(String tag, String msg, Throwable tr) {
-        return android.util.Log.i(tag, msg, tr);
-    }
-    public static int w(String tag, String msg) {
-        return android.util.Log.w(tag, msg);
-    }
-    public static int w(String tag, String msg, Throwable tr) {
-        return android.util.Log.w(tag, msg, tr);
-    }
-    public static int w(String tag, Throwable tr) {
-        return android.util.Log.w(tag, tr);
-    }
-    public static int e(String tag, String msg) {
-        return android.util.Log.e(tag, msg);
-    }
-    public static int e(String tag, String msg, Throwable tr) {
-        return android.util.Log.e(tag, msg, tr);
-    }
-}
diff --git a/src/com/android/gallery3d/ui/ManageCacheDrawer.java b/src/com/android/gallery3d/ui/ManageCacheDrawer.java
deleted file mode 100644
index d210bd1..0000000
--- a/src/com/android/gallery3d/ui/ManageCacheDrawer.java
+++ /dev/null
@@ -1,116 +0,0 @@
-/*
- * Copyright (C) 2010 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.gallery3d.ui;
-
-import android.content.Context;
-
-import com.android.gallery3d.R;
-import com.android.gallery3d.app.AbstractGalleryActivity;
-import com.android.gallery3d.data.DataSourceType;
-import com.android.gallery3d.data.MediaSet;
-import com.android.gallery3d.data.Path;
-import com.android.gallery3d.glrenderer.GLCanvas;
-import com.android.gallery3d.glrenderer.ResourceTexture;
-import com.android.gallery3d.glrenderer.StringTexture;
-import com.android.gallery3d.ui.AlbumSetSlidingWindow.AlbumSetEntry;
-
-public class ManageCacheDrawer extends AlbumSetSlotRenderer {
-    private final ResourceTexture mCheckedItem;
-    private final ResourceTexture mUnCheckedItem;
-    private final SelectionManager mSelectionManager;
-
-    private final ResourceTexture mLocalAlbumIcon;
-    private final StringTexture mCachingText;
-
-    private final int mCachePinSize;
-    private final int mCachePinMargin;
-
-    public ManageCacheDrawer(AbstractGalleryActivity activity, SelectionManager selectionManager,
-            SlotView slotView, LabelSpec labelSpec, int cachePinSize, int cachePinMargin) {
-        super(activity, selectionManager, slotView, labelSpec,
-                activity.getResources().getColor(R.color.cache_placeholder));
-        Context context = activity;
-        mCheckedItem = new ResourceTexture(
-                context, R.drawable.btn_make_offline_normal_on_holo_dark);
-        mUnCheckedItem = new ResourceTexture(
-                context, R.drawable.btn_make_offline_normal_off_holo_dark);
-        mLocalAlbumIcon = new ResourceTexture(
-                context, R.drawable.btn_make_offline_disabled_on_holo_dark);
-        String cachingLabel = context.getString(R.string.caching_label);
-        mCachingText = StringTexture.newInstance(cachingLabel, 12, 0xffffffff);
-        mSelectionManager = selectionManager;
-        mCachePinSize = cachePinSize;
-        mCachePinMargin = cachePinMargin;
-    }
-
-    private static boolean isLocal(int dataSourceType) {
-        return dataSourceType != DataSourceType.TYPE_PICASA;
-    }
-
-    @Override
-    public int renderSlot(GLCanvas canvas, int index, int pass, int width, int height) {
-        AlbumSetEntry entry = mDataWindow.get(index);
-
-        boolean wantCache = entry.cacheFlag == MediaSet.CACHE_FLAG_FULL;
-        boolean isCaching = wantCache && (
-                entry.cacheStatus != MediaSet.CACHE_STATUS_CACHED_FULL);
-        boolean selected = mSelectionManager.isItemSelected(entry.setPath);
-        boolean chooseToCache = wantCache ^ selected;
-        boolean available = isLocal(entry.sourceType) || chooseToCache;
-
-        int renderRequestFlags = 0;
-
-        if (!available) {
-            canvas.save(GLCanvas.SAVE_FLAG_ALPHA);
-            canvas.multiplyAlpha(0.6f);
-        }
-        renderRequestFlags |= renderContent(canvas, entry, width, height);
-        if (!available) canvas.restore();
-
-        renderRequestFlags |= renderLabel(canvas, entry, width, height);
-
-        drawCachingPin(canvas, entry.setPath,
-                entry.sourceType, isCaching, chooseToCache, width, height);
-
-        renderRequestFlags |= renderOverlay(canvas, index, entry, width, height);
-        return renderRequestFlags;
-    }
-
-    private void drawCachingPin(GLCanvas canvas, Path path, int dataSourceType,
-            boolean isCaching, boolean chooseToCache, int width, int height) {
-        ResourceTexture icon;
-        if (isLocal(dataSourceType)) {
-            icon = mLocalAlbumIcon;
-        } else if (chooseToCache) {
-            icon = mCheckedItem;
-        } else {
-            icon = mUnCheckedItem;
-        }
-
-        // show the icon in right bottom
-        int s = mCachePinSize;
-        int m = mCachePinMargin;
-        icon.draw(canvas, width - m - s, height - s, s, s);
-
-        if (isCaching) {
-            int w = mCachingText.getWidth();
-            int h = mCachingText.getHeight();
-            // Show the caching text in bottom center
-            mCachingText.draw(canvas, (width - w) / 2, height - h);
-        }
-    }
-}
diff --git a/src/com/android/gallery3d/ui/MeasureHelper.java b/src/com/android/gallery3d/ui/MeasureHelper.java
deleted file mode 100644
index f65dc10..0000000
--- a/src/com/android/gallery3d/ui/MeasureHelper.java
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * Copyright (C) 2010 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.gallery3d.ui;
-
-import android.graphics.Rect;
-import android.view.View.MeasureSpec;
-
-class MeasureHelper {
-
-    private static MeasureHelper sInstance = new MeasureHelper(null);
-
-    private GLView mComponent;
-    private int mPreferredWidth;
-    private int mPreferredHeight;
-
-    private MeasureHelper(GLView component) {
-        mComponent = component;
-    }
-
-    public static MeasureHelper getInstance(GLView component) {
-        sInstance.mComponent = component;
-        return sInstance;
-    }
-
-    public MeasureHelper setPreferredContentSize(int width, int height) {
-        mPreferredWidth = width;
-        mPreferredHeight = height;
-        return this;
-    }
-
-    public void measure(int widthSpec, int heightSpec) {
-        Rect p = mComponent.getPaddings();
-        setMeasuredSize(
-                getLength(widthSpec, mPreferredWidth + p.left + p.right),
-                getLength(heightSpec, mPreferredHeight + p.top + p.bottom));
-    }
-
-    private static int getLength(int measureSpec, int prefered) {
-        int specLength = MeasureSpec.getSize(measureSpec);
-        switch(MeasureSpec.getMode(measureSpec)) {
-            case MeasureSpec.EXACTLY: return specLength;
-            case MeasureSpec.AT_MOST: return Math.min(prefered, specLength);
-            default: return prefered;
-        }
-    }
-
-    protected void setMeasuredSize(int width, int height) {
-        mComponent.setMeasuredSize(width, height);
-    }
-
-}
diff --git a/src/com/android/gallery3d/ui/MenuExecutor.java b/src/com/android/gallery3d/ui/MenuExecutor.java
deleted file mode 100644
index 29def05..0000000
--- a/src/com/android/gallery3d/ui/MenuExecutor.java
+++ /dev/null
@@ -1,448 +0,0 @@
-/*
- * Copyright (C) 2010 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.gallery3d.ui;
-
-import android.app.Activity;
-import android.app.AlertDialog;
-import android.app.ProgressDialog;
-import android.content.Context;
-import android.content.DialogInterface;
-import android.content.DialogInterface.OnCancelListener;
-import android.content.DialogInterface.OnClickListener;
-import android.content.Intent;
-import android.os.Handler;
-import android.os.Message;
-import android.view.Menu;
-import android.view.MenuItem;
-
-import com.android.gallery3d.R;
-import com.android.gallery3d.app.AbstractGalleryActivity;
-import com.android.gallery3d.common.Utils;
-import com.android.gallery3d.data.DataManager;
-import com.android.gallery3d.data.MediaItem;
-import com.android.gallery3d.data.MediaObject;
-import com.android.gallery3d.data.Path;
-import com.android.gallery3d.filtershow.crop.CropActivity;
-import com.android.gallery3d.util.Future;
-import com.android.gallery3d.util.GalleryUtils;
-import com.android.gallery3d.util.ThreadPool.Job;
-import com.android.gallery3d.util.ThreadPool.JobContext;
-
-import java.util.ArrayList;
-
-public class MenuExecutor {
-    @SuppressWarnings("unused")
-    private static final String TAG = "MenuExecutor";
-
-    private static final int MSG_TASK_COMPLETE = 1;
-    private static final int MSG_TASK_UPDATE = 2;
-    private static final int MSG_TASK_START = 3;
-    private static final int MSG_DO_SHARE = 4;
-
-    public static final int EXECUTION_RESULT_SUCCESS = 1;
-    public static final int EXECUTION_RESULT_FAIL = 2;
-    public static final int EXECUTION_RESULT_CANCEL = 3;
-
-    private ProgressDialog mDialog;
-    private Future<?> mTask;
-    // wait the operation to finish when we want to stop it.
-    private boolean mWaitOnStop;
-    private boolean mPaused;
-
-    private final AbstractGalleryActivity mActivity;
-    private final SelectionManager mSelectionManager;
-    private final Handler mHandler;
-
-    private static ProgressDialog createProgressDialog(
-            Context context, int titleId, int progressMax) {
-        ProgressDialog dialog = new ProgressDialog(context);
-        dialog.setTitle(titleId);
-        dialog.setMax(progressMax);
-        dialog.setCancelable(false);
-        dialog.setIndeterminate(false);
-        if (progressMax > 1) {
-            dialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
-        }
-        return dialog;
-    }
-
-    public interface ProgressListener {
-        public void onConfirmDialogShown();
-        public void onConfirmDialogDismissed(boolean confirmed);
-        public void onProgressStart();
-        public void onProgressUpdate(int index);
-        public void onProgressComplete(int result);
-    }
-
-    public MenuExecutor(
-            AbstractGalleryActivity activity, SelectionManager selectionManager) {
-        mActivity = Utils.checkNotNull(activity);
-        mSelectionManager = Utils.checkNotNull(selectionManager);
-        mHandler = new SynchronizedHandler(mActivity.getGLRoot()) {
-            @Override
-            public void handleMessage(Message message) {
-                switch (message.what) {
-                    case MSG_TASK_START: {
-                        if (message.obj != null) {
-                            ProgressListener listener = (ProgressListener) message.obj;
-                            listener.onProgressStart();
-                        }
-                        break;
-                    }
-                    case MSG_TASK_COMPLETE: {
-                        stopTaskAndDismissDialog();
-                        if (message.obj != null) {
-                            ProgressListener listener = (ProgressListener) message.obj;
-                            listener.onProgressComplete(message.arg1);
-                        }
-                        mSelectionManager.leaveSelectionMode();
-                        break;
-                    }
-                    case MSG_TASK_UPDATE: {
-                        if (mDialog != null && !mPaused) mDialog.setProgress(message.arg1);
-                        if (message.obj != null) {
-                            ProgressListener listener = (ProgressListener) message.obj;
-                            listener.onProgressUpdate(message.arg1);
-                        }
-                        break;
-                    }
-                    case MSG_DO_SHARE: {
-                        ((Activity) mActivity).startActivity((Intent) message.obj);
-                        break;
-                    }
-                }
-            }
-        };
-    }
-
-    private void stopTaskAndDismissDialog() {
-        if (mTask != null) {
-            if (!mWaitOnStop) mTask.cancel();
-            if (mDialog != null && mDialog.isShowing()) mDialog.dismiss();
-            mDialog = null;
-            mTask = null;
-        }
-    }
-
-    public void resume() {
-        mPaused = false;
-        if (mDialog != null) mDialog.show();
-    }
-
-    public void pause() {
-        mPaused = true;
-        if (mDialog != null && mDialog.isShowing()) mDialog.hide();
-    }
-
-    public void destroy() {
-        stopTaskAndDismissDialog();
-    }
-
-    private void onProgressUpdate(int index, ProgressListener listener) {
-        mHandler.sendMessage(
-                mHandler.obtainMessage(MSG_TASK_UPDATE, index, 0, listener));
-    }
-
-    private void onProgressStart(ProgressListener listener) {
-        mHandler.sendMessage(mHandler.obtainMessage(MSG_TASK_START, listener));
-    }
-
-    private void onProgressComplete(int result, ProgressListener listener) {
-        mHandler.sendMessage(mHandler.obtainMessage(MSG_TASK_COMPLETE, result, 0, listener));
-    }
-
-    public static void updateMenuOperation(Menu menu, int supported) {
-        boolean supportDelete = (supported & MediaObject.SUPPORT_DELETE) != 0;
-        boolean supportRotate = (supported & MediaObject.SUPPORT_ROTATE) != 0;
-        boolean supportCrop = (supported & MediaObject.SUPPORT_CROP) != 0;
-        boolean supportTrim = (supported & MediaObject.SUPPORT_TRIM) != 0;
-        boolean supportMute = (supported & MediaObject.SUPPORT_MUTE) != 0;
-        boolean supportShare = (supported & MediaObject.SUPPORT_SHARE) != 0;
-        boolean supportSetAs = (supported & MediaObject.SUPPORT_SETAS) != 0;
-        boolean supportShowOnMap = (supported & MediaObject.SUPPORT_SHOW_ON_MAP) != 0;
-        boolean supportCache = (supported & MediaObject.SUPPORT_CACHE) != 0;
-        boolean supportEdit = (supported & MediaObject.SUPPORT_EDIT) != 0;
-        boolean supportInfo = (supported & MediaObject.SUPPORT_INFO) != 0;
-
-        setMenuItemVisible(menu, R.id.action_delete, supportDelete);
-        setMenuItemVisible(menu, R.id.action_rotate_ccw, supportRotate);
-        setMenuItemVisible(menu, R.id.action_rotate_cw, supportRotate);
-        setMenuItemVisible(menu, R.id.action_crop, supportCrop);
-        setMenuItemVisible(menu, R.id.action_trim, supportTrim);
-        setMenuItemVisible(menu, R.id.action_mute, supportMute);
-        // Hide panorama until call to updateMenuForPanorama corrects it
-        setMenuItemVisible(menu, R.id.action_share_panorama, false);
-        setMenuItemVisible(menu, R.id.action_share, supportShare);
-        setMenuItemVisible(menu, R.id.action_setas, supportSetAs);
-        setMenuItemVisible(menu, R.id.action_show_on_map, supportShowOnMap);
-        setMenuItemVisible(menu, R.id.action_edit, supportEdit);
-        setMenuItemVisible(menu, R.id.action_simple_edit, supportEdit);
-        setMenuItemVisible(menu, R.id.action_details, supportInfo);
-    }
-
-    public static void updateMenuForPanorama(Menu menu, boolean shareAsPanorama360,
-            boolean disablePanorama360Options) {
-        setMenuItemVisible(menu, R.id.action_share_panorama, shareAsPanorama360);
-        if (disablePanorama360Options) {
-            setMenuItemVisible(menu, R.id.action_rotate_ccw, false);
-            setMenuItemVisible(menu, R.id.action_rotate_cw, false);
-        }
-    }
-
-    private static void setMenuItemVisible(Menu menu, int itemId, boolean visible) {
-        MenuItem item = menu.findItem(itemId);
-        if (item != null) item.setVisible(visible);
-    }
-
-    private Path getSingleSelectedPath() {
-        ArrayList<Path> ids = mSelectionManager.getSelected(true);
-        Utils.assertTrue(ids.size() == 1);
-        return ids.get(0);
-    }
-
-    private Intent getIntentBySingleSelectedPath(String action) {
-        DataManager manager = mActivity.getDataManager();
-        Path path = getSingleSelectedPath();
-        String mimeType = getMimeType(manager.getMediaType(path));
-        return new Intent(action).setDataAndType(manager.getContentUri(path), mimeType);
-    }
-
-    private void onMenuClicked(int action, ProgressListener listener) {
-        onMenuClicked(action, listener, false, true);
-    }
-
-    public void onMenuClicked(int action, ProgressListener listener,
-            boolean waitOnStop, boolean showDialog) {
-        int title;
-        switch (action) {
-            case R.id.action_select_all:
-                if (mSelectionManager.inSelectAllMode()) {
-                    mSelectionManager.deSelectAll();
-                } else {
-                    mSelectionManager.selectAll();
-                }
-                return;
-            case R.id.action_crop: {
-                Intent intent = getIntentBySingleSelectedPath(CropActivity.CROP_ACTION);
-                ((Activity) mActivity).startActivity(intent);
-                return;
-            }
-            case R.id.action_edit: {
-                Intent intent = getIntentBySingleSelectedPath(Intent.ACTION_EDIT)
-                        .setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
-                ((Activity) mActivity).startActivity(Intent.createChooser(intent, null));
-                return;
-            }
-            case R.id.action_setas: {
-                Intent intent = getIntentBySingleSelectedPath(Intent.ACTION_ATTACH_DATA)
-                        .addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
-                intent.putExtra("mimeType", intent.getType());
-                Activity activity = mActivity;
-                activity.startActivity(Intent.createChooser(
-                        intent, activity.getString(R.string.set_as)));
-                return;
-            }
-            case R.id.action_delete:
-                title = R.string.delete;
-                break;
-            case R.id.action_rotate_cw:
-                title = R.string.rotate_right;
-                break;
-            case R.id.action_rotate_ccw:
-                title = R.string.rotate_left;
-                break;
-            case R.id.action_show_on_map:
-                title = R.string.show_on_map;
-                break;
-            default:
-                return;
-        }
-        startAction(action, title, listener, waitOnStop, showDialog);
-    }
-
-    private class ConfirmDialogListener implements OnClickListener, OnCancelListener {
-        private final int mActionId;
-        private final ProgressListener mListener;
-
-        public ConfirmDialogListener(int actionId, ProgressListener listener) {
-            mActionId = actionId;
-            mListener = listener;
-        }
-
-        @Override
-        public void onClick(DialogInterface dialog, int which) {
-            if (which == DialogInterface.BUTTON_POSITIVE) {
-                if (mListener != null) {
-                    mListener.onConfirmDialogDismissed(true);
-                }
-                onMenuClicked(mActionId, mListener);
-            } else {
-                if (mListener != null) {
-                    mListener.onConfirmDialogDismissed(false);
-                }
-            }
-        }
-
-        @Override
-        public void onCancel(DialogInterface dialog) {
-            if (mListener != null) {
-                mListener.onConfirmDialogDismissed(false);
-            }
-        }
-    }
-
-    public void onMenuClicked(MenuItem menuItem, String confirmMsg,
-            final ProgressListener listener) {
-        final int action = menuItem.getItemId();
-
-        if (confirmMsg != null) {
-            if (listener != null) listener.onConfirmDialogShown();
-            ConfirmDialogListener cdl = new ConfirmDialogListener(action, listener);
-            new AlertDialog.Builder(mActivity.getAndroidContext())
-                    .setMessage(confirmMsg)
-                    .setOnCancelListener(cdl)
-                    .setPositiveButton(R.string.ok, cdl)
-                    .setNegativeButton(R.string.cancel, cdl)
-                    .create().show();
-        } else {
-            onMenuClicked(action, listener);
-        }
-    }
-
-    public void startAction(int action, int title, ProgressListener listener) {
-        startAction(action, title, listener, false, true);
-    }
-
-    public void startAction(int action, int title, ProgressListener listener,
-            boolean waitOnStop, boolean showDialog) {
-        ArrayList<Path> ids = mSelectionManager.getSelected(false);
-        stopTaskAndDismissDialog();
-
-        Activity activity = mActivity;
-        if (showDialog) {
-            mDialog = createProgressDialog(activity, title, ids.size());
-            mDialog.show();
-        } else {
-            mDialog = null;
-        }
-        MediaOperation operation = new MediaOperation(action, ids, listener);
-        mTask = mActivity.getBatchServiceThreadPoolIfAvailable().submit(operation, null);
-        mWaitOnStop = waitOnStop;
-    }
-
-    public void startSingleItemAction(int action, Path targetPath) {
-        ArrayList<Path> ids = new ArrayList<Path>(1);
-        ids.add(targetPath);
-        mDialog = null;
-        MediaOperation operation = new MediaOperation(action, ids, null);
-        mTask = mActivity.getBatchServiceThreadPoolIfAvailable().submit(operation, null);
-        mWaitOnStop = false;
-    }
-
-    public static String getMimeType(int type) {
-        switch (type) {
-            case MediaObject.MEDIA_TYPE_IMAGE :
-                return GalleryUtils.MIME_TYPE_IMAGE;
-            case MediaObject.MEDIA_TYPE_VIDEO :
-                return GalleryUtils.MIME_TYPE_VIDEO;
-            default: return GalleryUtils.MIME_TYPE_ALL;
-        }
-    }
-
-    private boolean execute(
-            DataManager manager, JobContext jc, int cmd, Path path) {
-        boolean result = true;
-        Log.v(TAG, "Execute cmd: " + cmd + " for " + path);
-        long startTime = System.currentTimeMillis();
-
-        switch (cmd) {
-            case R.id.action_delete:
-                manager.delete(path);
-                break;
-            case R.id.action_rotate_cw:
-                manager.rotate(path, 90);
-                break;
-            case R.id.action_rotate_ccw:
-                manager.rotate(path, -90);
-                break;
-            case R.id.action_toggle_full_caching: {
-                MediaObject obj = manager.getMediaObject(path);
-                int cacheFlag = obj.getCacheFlag();
-                if (cacheFlag == MediaObject.CACHE_FLAG_FULL) {
-                    cacheFlag = MediaObject.CACHE_FLAG_SCREENNAIL;
-                } else {
-                    cacheFlag = MediaObject.CACHE_FLAG_FULL;
-                }
-                obj.cache(cacheFlag);
-                break;
-            }
-            case R.id.action_show_on_map: {
-                MediaItem item = (MediaItem) manager.getMediaObject(path);
-                double latlng[] = new double[2];
-                item.getLatLong(latlng);
-                if (GalleryUtils.isValidLocation(latlng[0], latlng[1])) {
-                    GalleryUtils.showOnMap(mActivity, latlng[0], latlng[1]);
-                }
-                break;
-            }
-            default:
-                throw new AssertionError();
-        }
-        Log.v(TAG, "It takes " + (System.currentTimeMillis() - startTime) +
-                " ms to execute cmd for " + path);
-        return result;
-    }
-
-    private class MediaOperation implements Job<Void> {
-        private final ArrayList<Path> mItems;
-        private final int mOperation;
-        private final ProgressListener mListener;
-
-        public MediaOperation(int operation, ArrayList<Path> items,
-                ProgressListener listener) {
-            mOperation = operation;
-            mItems = items;
-            mListener = listener;
-        }
-
-        @Override
-        public Void run(JobContext jc) {
-            int index = 0;
-            DataManager manager = mActivity.getDataManager();
-            int result = EXECUTION_RESULT_SUCCESS;
-            try {
-                onProgressStart(mListener);
-                for (Path id : mItems) {
-                    if (jc.isCancelled()) {
-                        result = EXECUTION_RESULT_CANCEL;
-                        break;
-                    }
-                    if (!execute(manager, jc, mOperation, id)) {
-                        result = EXECUTION_RESULT_FAIL;
-                    }
-                    onProgressUpdate(index++, mListener);
-                }
-            } catch (Throwable th) {
-                Log.e(TAG, "failed to execute operation " + mOperation
-                        + " : " + th);
-            } finally {
-               onProgressComplete(result, mListener);
-            }
-            return null;
-        }
-    }
-}
diff --git a/src/com/android/gallery3d/ui/OrientationSource.java b/src/com/android/gallery3d/ui/OrientationSource.java
deleted file mode 100644
index e13ce1c..0000000
--- a/src/com/android/gallery3d/ui/OrientationSource.java
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * 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.gallery3d.ui;
-
-public interface OrientationSource {
-    public int getDisplayRotation();
-    public int getCompensation();
-}
diff --git a/src/com/android/gallery3d/ui/Paper.java b/src/com/android/gallery3d/ui/Paper.java
deleted file mode 100644
index b36f5c3..0000000
--- a/src/com/android/gallery3d/ui/Paper.java
+++ /dev/null
@@ -1,183 +0,0 @@
-/*
- * Copyright (C) 2010 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.gallery3d.ui;
-
-import android.graphics.Rect;
-import android.opengl.Matrix;
-import android.view.animation.DecelerateInterpolator;
-import android.view.animation.Interpolator;
-
-import com.android.gallery3d.common.Utils;
-
-// This class does the overscroll effect.
-class Paper {
-    @SuppressWarnings("unused")
-    private static final String TAG = "Paper";
-    private static final int ROTATE_FACTOR = 4;
-    private EdgeAnimation mAnimationLeft = new EdgeAnimation();
-    private EdgeAnimation mAnimationRight = new EdgeAnimation();
-    private int mWidth;
-    private float[] mMatrix = new float[16];
-
-    public void overScroll(float distance) {
-        distance /= mWidth;  // make it relative to width
-        if (distance < 0) {
-            mAnimationLeft.onPull(-distance);
-        } else {
-            mAnimationRight.onPull(distance);
-        }
-    }
-
-    public void edgeReached(float velocity) {
-        velocity /= mWidth;  // make it relative to width
-        if (velocity < 0) {
-            mAnimationRight.onAbsorb(-velocity);
-        } else {
-            mAnimationLeft.onAbsorb(velocity);
-        }
-    }
-
-    public void onRelease() {
-        mAnimationLeft.onRelease();
-        mAnimationRight.onRelease();
-    }
-
-    public boolean advanceAnimation() {
-        // Note that we use "|" because we want both animations get updated.
-        return mAnimationLeft.update() | mAnimationRight.update();
-    }
-
-    public void setSize(int width, int height) {
-        mWidth = width;
-    }
-
-    public float[] getTransform(Rect rect, float scrollX) {
-        float left = mAnimationLeft.getValue();
-        float right = mAnimationRight.getValue();
-        float screenX = rect.centerX() - scrollX;
-        // We linearly interpolate the value [left, right] for the screenX
-        // range int [-1/4, 5/4]*mWidth. So if part of the thumbnail is outside
-        // the screen, we still get some transform.
-        float x = screenX + mWidth / 4;
-        int range = 3 * mWidth / 2;
-        float t = ((range - x) * left - x * right) / range;
-        // compress t to the range (-1, 1) by the function
-        // f(t) = (1 / (1 + e^-t) - 0.5) * 2
-        // then multiply by 90 to make the range (-45, 45)
-        float degrees =
-                (1 / (1 + (float) Math.exp(-t * ROTATE_FACTOR)) - 0.5f) * 2 * -45;
-        Matrix.setIdentityM(mMatrix, 0);
-        Matrix.translateM(mMatrix, 0, mMatrix, 0, rect.centerX(), rect.centerY(), 0);
-        Matrix.rotateM(mMatrix, 0, degrees, 0, 1, 0);
-        Matrix.translateM(mMatrix, 0, mMatrix, 0, -rect.width() / 2, -rect.height() / 2, 0);
-        return mMatrix;
-    }
-}
-
-// This class follows the structure of frameworks's EdgeEffect class.
-class EdgeAnimation {
-    @SuppressWarnings("unused")
-    private static final String TAG = "EdgeAnimation";
-
-    private static final int STATE_IDLE = 0;
-    private static final int STATE_PULL = 1;
-    private static final int STATE_ABSORB = 2;
-    private static final int STATE_RELEASE = 3;
-
-    // Time it will take the effect to fully done in ms
-    private static final int ABSORB_TIME = 200;
-    private static final int RELEASE_TIME = 500;
-
-    private static final float VELOCITY_FACTOR = 0.1f;
-
-    private final Interpolator mInterpolator;
-
-    private int mState;
-    private float mValue;
-
-    private float mValueStart;
-    private float mValueFinish;
-    private long mStartTime;
-    private long mDuration;
-
-    public EdgeAnimation() {
-        mInterpolator = new DecelerateInterpolator();
-        mState = STATE_IDLE;
-    }
-
-    private void startAnimation(float start, float finish, long duration,
-            int newState) {
-        mValueStart = start;
-        mValueFinish = finish;
-        mDuration = duration;
-        mStartTime = now();
-        mState = newState;
-    }
-
-    // The deltaDistance's magnitude is in the range of -1 (no change) to 1.
-    // The value 1 is the full length of the view. Negative values means the
-    // movement is in the opposite direction.
-    public void onPull(float deltaDistance) {
-        if (mState == STATE_ABSORB) return;
-        mValue = Utils.clamp(mValue + deltaDistance, -1.0f, 1.0f);
-        mState = STATE_PULL;
-    }
-
-    public void onRelease() {
-        if (mState == STATE_IDLE || mState == STATE_ABSORB) return;
-        startAnimation(mValue, 0, RELEASE_TIME, STATE_RELEASE);
-    }
-
-    public void onAbsorb(float velocity) {
-        float finish = Utils.clamp(mValue + velocity * VELOCITY_FACTOR,
-                -1.0f, 1.0f);
-        startAnimation(mValue, finish, ABSORB_TIME, STATE_ABSORB);
-    }
-
-    public boolean update() {
-        if (mState == STATE_IDLE) return false;
-        if (mState == STATE_PULL) return true;
-
-        float t = Utils.clamp((float)(now() - mStartTime) / mDuration, 0.0f, 1.0f);
-        /* Use linear interpolation for absorb, quadratic for others */
-        float interp = (mState == STATE_ABSORB)
-                ? t : mInterpolator.getInterpolation(t);
-
-        mValue = mValueStart + (mValueFinish - mValueStart) * interp;
-
-        if (t >= 1.0f) {
-            switch (mState) {
-                case STATE_ABSORB:
-                    startAnimation(mValue, 0, RELEASE_TIME, STATE_RELEASE);
-                    break;
-                case STATE_RELEASE:
-                    mState = STATE_IDLE;
-                    break;
-            }
-        }
-
-        return true;
-    }
-
-    public float getValue() {
-        return mValue;
-    }
-
-    private long now() {
-        return AnimationTime.get();
-    }
-}
diff --git a/src/com/android/gallery3d/ui/PhotoFallbackEffect.java b/src/com/android/gallery3d/ui/PhotoFallbackEffect.java
deleted file mode 100644
index 4603285..0000000
--- a/src/com/android/gallery3d/ui/PhotoFallbackEffect.java
+++ /dev/null
@@ -1,179 +0,0 @@
-/*
- * Copyright (C) 2010 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.gallery3d.ui;
-
-import android.graphics.Rect;
-import android.graphics.RectF;
-import android.view.animation.DecelerateInterpolator;
-import android.view.animation.Interpolator;
-
-import com.android.gallery3d.anim.Animation;
-import com.android.gallery3d.data.Path;
-import com.android.gallery3d.glrenderer.GLCanvas;
-import com.android.gallery3d.glrenderer.RawTexture;
-import com.android.gallery3d.ui.AlbumSlotRenderer.SlotFilter;
-
-import java.util.ArrayList;
-
-public class PhotoFallbackEffect extends Animation implements SlotFilter {
-
-    private static final int ANIM_DURATION = 300;
-    private static final Interpolator ANIM_INTERPOLATE = new DecelerateInterpolator(1.5f);
-
-    public static class Entry {
-        public int index;
-        public Path path;
-        public Rect source;
-        public Rect dest;
-        public RawTexture texture;
-
-        public Entry(Path path, Rect source, RawTexture texture) {
-            this.path = path;
-            this.source = source;
-            this.texture = texture;
-        }
-    }
-
-    public interface PositionProvider {
-        public Rect getPosition(int index);
-        public int getItemIndex(Path path);
-    }
-
-    private RectF mSource = new RectF();
-    private RectF mTarget = new RectF();
-    private float mProgress;
-    private PositionProvider mPositionProvider;
-
-    private ArrayList<Entry> mList = new ArrayList<Entry>();
-
-    public PhotoFallbackEffect() {
-        setDuration(ANIM_DURATION);
-        setInterpolator(ANIM_INTERPOLATE);
-    }
-
-    public void addEntry(Path path, Rect rect, RawTexture texture) {
-        mList.add(new Entry(path, rect, texture));
-    }
-
-    public Entry getEntry(Path path) {
-        for (int i = 0, n = mList.size(); i < n; ++i) {
-            Entry entry = mList.get(i);
-            if (entry.path == path) return entry;
-        }
-        return null;
-    }
-
-    public boolean draw(GLCanvas canvas) {
-        boolean more = calculate(AnimationTime.get());
-        for (int i = 0, n = mList.size(); i < n; ++i) {
-            Entry entry = mList.get(i);
-            if (entry.index < 0) continue;
-            entry.dest = mPositionProvider.getPosition(entry.index);
-            drawEntry(canvas, entry);
-        }
-        return more;
-    }
-
-    private void drawEntry(GLCanvas canvas, Entry entry) {
-        if (!entry.texture.isLoaded()) return;
-
-        int w = entry.texture.getWidth();
-        int h = entry.texture.getHeight();
-
-        Rect s = entry.source;
-        Rect d = entry.dest;
-
-        // the following calculation is based on d.width() == d.height()
-
-        float p = mProgress;
-
-        float fullScale = (float) d.height() / Math.min(s.width(), s.height());
-        float scale = fullScale * p + 1 * (1 - p);
-
-        float cx = d.centerX() * p + s.centerX() * (1 - p);
-        float cy = d.centerY() * p + s.centerY() * (1 - p);
-
-        float ch = s.height() * scale;
-        float cw = s.width() * scale;
-
-        if (w > h) {
-            // draw the center part
-            mTarget.set(cx - ch / 2, cy - ch / 2, cx + ch / 2, cy + ch / 2);
-            mSource.set((w - h) / 2, 0, (w + h) / 2, h);
-            canvas.drawTexture(entry.texture, mSource, mTarget);
-
-            canvas.save(GLCanvas.SAVE_FLAG_ALPHA);
-            canvas.multiplyAlpha(1 - p);
-
-            // draw the left part
-            mTarget.set(cx - cw / 2, cy - ch / 2, cx - ch / 2, cy + ch / 2);
-            mSource.set(0, 0, (w - h) / 2, h);
-            canvas.drawTexture(entry.texture, mSource, mTarget);
-
-            // draw the right part
-            mTarget.set(cx + ch / 2, cy - ch / 2, cx + cw / 2, cy + ch / 2);
-            mSource.set((w + h) / 2, 0, w, h);
-            canvas.drawTexture(entry.texture, mSource, mTarget);
-
-            canvas.restore();
-        } else {
-            // draw the center part
-            mTarget.set(cx - cw / 2, cy - cw / 2, cx + cw / 2, cy + cw / 2);
-            mSource.set(0, (h - w) / 2, w, (h + w) / 2);
-            canvas.drawTexture(entry.texture, mSource, mTarget);
-
-            canvas.save(GLCanvas.SAVE_FLAG_ALPHA);
-            canvas.multiplyAlpha(1 - p);
-
-            // draw the upper part
-            mTarget.set(cx - cw / 2, cy - ch / 2, cx + cw / 2, cy - cw / 2);
-            mSource.set(0, 0, w, (h - w) / 2);
-            canvas.drawTexture(entry.texture, mSource, mTarget);
-
-            // draw the bottom part
-            mTarget.set(cx - cw / 2, cy + cw / 2, cx + cw / 2, cy + ch / 2);
-            mSource.set(0, (w + h) / 2, w, h);
-            canvas.drawTexture(entry.texture, mSource, mTarget);
-
-            canvas.restore();
-        }
-    }
-
-    @Override
-    protected void onCalculate(float progress) {
-        mProgress = progress;
-    }
-
-    public void setPositionProvider(PositionProvider provider) {
-        mPositionProvider = provider;
-        if (mPositionProvider != null) {
-            for (int i = 0, n = mList.size(); i < n; ++i) {
-                Entry entry = mList.get(i);
-                entry.index = mPositionProvider.getItemIndex(entry.path);
-            }
-        }
-    }
-
-    @Override
-    public boolean acceptSlot(int index) {
-        for (int i = 0, n = mList.size(); i < n; ++i) {
-            Entry entry = mList.get(i);
-            if (entry.index == index) return false;
-        }
-        return true;
-    }
-}
diff --git a/src/com/android/gallery3d/ui/PhotoView.java b/src/com/android/gallery3d/ui/PhotoView.java
deleted file mode 100644
index 7afa203..0000000
--- a/src/com/android/gallery3d/ui/PhotoView.java
+++ /dev/null
@@ -1,1858 +0,0 @@
-/*
- * Copyright (C) 2010 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.gallery3d.ui;
-
-import android.content.Context;
-import android.content.res.Configuration;
-import android.graphics.Color;
-import android.graphics.Matrix;
-import android.graphics.Rect;
-import android.os.Build;
-import android.os.Message;
-import android.util.FloatMath;
-import android.view.MotionEvent;
-import android.view.View.MeasureSpec;
-import android.view.animation.AccelerateInterpolator;
-
-import com.android.gallery3d.R;
-import com.android.gallery3d.app.AbstractGalleryActivity;
-import com.android.gallery3d.common.ApiHelper;
-import com.android.gallery3d.common.Utils;
-import com.android.gallery3d.data.MediaItem;
-import com.android.gallery3d.data.MediaObject;
-import com.android.gallery3d.data.Path;
-import com.android.gallery3d.glrenderer.GLCanvas;
-import com.android.gallery3d.glrenderer.RawTexture;
-import com.android.gallery3d.glrenderer.ResourceTexture;
-import com.android.gallery3d.glrenderer.StringTexture;
-import com.android.gallery3d.glrenderer.Texture;
-import com.android.gallery3d.util.GalleryUtils;
-import com.android.gallery3d.util.RangeArray;
-import com.android.gallery3d.util.UsageStatistics;
-
-public class PhotoView extends GLView {
-    @SuppressWarnings("unused")
-    private static final String TAG = "PhotoView";
-    private final int mPlaceholderColor;
-
-    public static final int INVALID_SIZE = -1;
-    public static final long INVALID_DATA_VERSION =
-            MediaObject.INVALID_DATA_VERSION;
-
-    public static class Size {
-        public int width;
-        public int height;
-    }
-
-    public interface Model extends TileImageView.TileSource {
-        public int getCurrentIndex();
-        public void moveTo(int index);
-
-        // Returns the size for the specified picture. If the size information is
-        // not avaiable, width = height = 0.
-        public void getImageSize(int offset, Size size);
-
-        // Returns the media item for the specified picture.
-        public MediaItem getMediaItem(int offset);
-
-        // Returns the rotation for the specified picture.
-        public int getImageRotation(int offset);
-
-        // This amends the getScreenNail() method of TileImageView.Model to get
-        // ScreenNail at previous (negative offset) or next (positive offset)
-        // positions. Returns null if the specified ScreenNail is unavailable.
-        public ScreenNail getScreenNail(int offset);
-
-        // Set this to true if we need the model to provide full images.
-        public void setNeedFullImage(boolean enabled);
-
-        // Returns true if the item is the Camera preview.
-        public boolean isCamera(int offset);
-
-        // Returns true if the item is the Panorama.
-        public boolean isPanorama(int offset);
-
-        // Returns true if the item is a static image that represents camera
-        // preview.
-        public boolean isStaticCamera(int offset);
-
-        // Returns true if the item is a Video.
-        public boolean isVideo(int offset);
-
-        // Returns true if the item can be deleted.
-        public boolean isDeletable(int offset);
-
-        public static final int LOADING_INIT = 0;
-        public static final int LOADING_COMPLETE = 1;
-        public static final int LOADING_FAIL = 2;
-
-        public int getLoadingState(int offset);
-
-        // When data change happens, we need to decide which MediaItem to focus
-        // on.
-        //
-        // 1. If focus hint path != null, we try to focus on it if we can find
-        // it.  This is used for undo a deletion, so we can focus on the
-        // undeleted item.
-        //
-        // 2. Otherwise try to focus on the MediaItem that is currently focused,
-        // if we can find it.
-        //
-        // 3. Otherwise try to focus on the previous MediaItem or the next
-        // MediaItem, depending on the value of focus hint direction.
-        public static final int FOCUS_HINT_NEXT = 0;
-        public static final int FOCUS_HINT_PREVIOUS = 1;
-        public void setFocusHintDirection(int direction);
-        public void setFocusHintPath(Path path);
-    }
-
-    public interface Listener {
-        public void onSingleTapUp(int x, int y);
-        public void onFullScreenChanged(boolean full);
-        public void onActionBarAllowed(boolean allowed);
-        public void onActionBarWanted();
-        public void onCurrentImageUpdated();
-        public void onDeleteImage(Path path, int offset);
-        public void onUndoDeleteImage();
-        public void onCommitDeleteImage();
-        public void onFilmModeChanged(boolean enabled);
-        public void onPictureCenter(boolean isCamera);
-        public void onUndoBarVisibilityChanged(boolean visible);
-    }
-
-    // The rules about orientation locking:
-    //
-    // (1) We need to lock the orientation if we are in page mode camera
-    // preview, so there is no (unwanted) rotation animation when the user
-    // rotates the device.
-    //
-    // (2) We need to unlock the orientation if we want to show the action bar
-    // because the action bar follows the system orientation.
-    //
-    // The rules about action bar:
-    //
-    // (1) If we are in film mode, we don't show action bar.
-    //
-    // (2) If we go from camera to gallery with capture animation, we show
-    // action bar.
-    private static final int MSG_CANCEL_EXTRA_SCALING = 2;
-    private static final int MSG_SWITCH_FOCUS = 3;
-    private static final int MSG_CAPTURE_ANIMATION_DONE = 4;
-    private static final int MSG_DELETE_ANIMATION_DONE = 5;
-    private static final int MSG_DELETE_DONE = 6;
-    private static final int MSG_UNDO_BAR_TIMEOUT = 7;
-    private static final int MSG_UNDO_BAR_FULL_CAMERA = 8;
-
-    private static final float SWIPE_THRESHOLD = 300f;
-
-    private static final float DEFAULT_TEXT_SIZE = 20;
-    private static float TRANSITION_SCALE_FACTOR = 0.74f;
-    private static final int ICON_RATIO = 6;
-
-    // whether we want to apply card deck effect in page mode.
-    private static final boolean CARD_EFFECT = true;
-
-    // whether we want to apply offset effect in film mode.
-    private static final boolean OFFSET_EFFECT = true;
-
-    // Used to calculate the scaling factor for the card deck effect.
-    private ZInterpolator mScaleInterpolator = new ZInterpolator(0.5f);
-
-    // Used to calculate the alpha factor for the fading animation.
-    private AccelerateInterpolator mAlphaInterpolator =
-            new AccelerateInterpolator(0.9f);
-
-    // We keep this many previous ScreenNails. (also this many next ScreenNails)
-    public static final int SCREEN_NAIL_MAX = 3;
-
-    // These are constants for the delete gesture.
-    private static final int SWIPE_ESCAPE_VELOCITY = 500; // dp/sec
-    private static final int MAX_DISMISS_VELOCITY = 2500; // dp/sec
-    private static final int SWIPE_ESCAPE_DISTANCE = 150; // dp
-
-    // The picture entries, the valid index is from -SCREEN_NAIL_MAX to
-    // SCREEN_NAIL_MAX.
-    private final RangeArray<Picture> mPictures =
-            new RangeArray<Picture>(-SCREEN_NAIL_MAX, SCREEN_NAIL_MAX);
-    private Size[] mSizes = new Size[2 * SCREEN_NAIL_MAX + 1];
-
-    private final MyGestureListener mGestureListener;
-    private final GestureRecognizer mGestureRecognizer;
-    private final PositionController mPositionController;
-
-    private Listener mListener;
-    private Model mModel;
-    private StringTexture mNoThumbnailText;
-    private TileImageView mTileView;
-    private EdgeView mEdgeView;
-    private UndoBarView mUndoBar;
-    private Texture mVideoPlayIcon;
-
-    private SynchronizedHandler mHandler;
-
-    private boolean mCancelExtraScalingPending;
-    private boolean mFilmMode = false;
-    private boolean mWantPictureCenterCallbacks = false;
-    private int mDisplayRotation = 0;
-    private int mCompensation = 0;
-    private boolean mFullScreenCamera;
-    private Rect mCameraRelativeFrame = new Rect();
-    private Rect mCameraRect = new Rect();
-    private boolean mFirst = true;
-
-    // [mPrevBound, mNextBound] is the range of index for all pictures in the
-    // model, if we assume the index of current focused picture is 0.  So if
-    // there are some previous pictures, mPrevBound < 0, and if there are some
-    // next pictures, mNextBound > 0.
-    private int mPrevBound;
-    private int mNextBound;
-
-    // This variable prevents us doing snapback until its values goes to 0. This
-    // happens if the user gesture is still in progress or we are in a capture
-    // animation.
-    private int mHolding;
-    private static final int HOLD_TOUCH_DOWN = 1;
-    private static final int HOLD_CAPTURE_ANIMATION = 2;
-    private static final int HOLD_DELETE = 4;
-
-    // mTouchBoxIndex is the index of the box that is touched by the down
-    // gesture in film mode. The value Integer.MAX_VALUE means no box was
-    // touched.
-    private int mTouchBoxIndex = Integer.MAX_VALUE;
-    // Whether the box indicated by mTouchBoxIndex is deletable. Only meaningful
-    // if mTouchBoxIndex is not Integer.MAX_VALUE.
-    private boolean mTouchBoxDeletable;
-    // This is the index of the last deleted item. This is only used as a hint
-    // to hide the undo button when we are too far away from the deleted
-    // item. The value Integer.MAX_VALUE means there is no such hint.
-    private int mUndoIndexHint = Integer.MAX_VALUE;
-
-    private Context mContext;
-
-    public PhotoView(AbstractGalleryActivity activity) {
-        mTileView = new TileImageView(activity);
-        addComponent(mTileView);
-        mContext = activity.getAndroidContext();
-        mPlaceholderColor = mContext.getResources().getColor(
-                R.color.photo_placeholder);
-        mEdgeView = new EdgeView(mContext);
-        addComponent(mEdgeView);
-        mUndoBar = new UndoBarView(mContext);
-        addComponent(mUndoBar);
-        mUndoBar.setVisibility(GLView.INVISIBLE);
-        mUndoBar.setOnClickListener(new OnClickListener() {
-                @Override
-                public void onClick(GLView v) {
-                    mListener.onUndoDeleteImage();
-                    hideUndoBar();
-                }
-            });
-        mNoThumbnailText = StringTexture.newInstance(
-                mContext.getString(R.string.no_thumbnail),
-                DEFAULT_TEXT_SIZE, Color.WHITE);
-
-        mHandler = new MyHandler(activity.getGLRoot());
-
-        mGestureListener = new MyGestureListener();
-        mGestureRecognizer = new GestureRecognizer(mContext, mGestureListener);
-
-        mPositionController = new PositionController(mContext,
-                new PositionController.Listener() {
-
-            @Override
-            public void invalidate() {
-                PhotoView.this.invalidate();
-            }
-
-            @Override
-            public boolean isHoldingDown() {
-                return (mHolding & HOLD_TOUCH_DOWN) != 0;
-            }
-
-            @Override
-            public boolean isHoldingDelete() {
-                return (mHolding & HOLD_DELETE) != 0;
-            }
-
-            @Override
-            public void onPull(int offset, int direction) {
-                mEdgeView.onPull(offset, direction);
-            }
-
-            @Override
-            public void onRelease() {
-                mEdgeView.onRelease();
-            }
-
-            @Override
-            public void onAbsorb(int velocity, int direction) {
-                mEdgeView.onAbsorb(velocity, direction);
-            }
-        });
-        mVideoPlayIcon = new ResourceTexture(mContext, R.drawable.ic_control_play);
-        for (int i = -SCREEN_NAIL_MAX; i <= SCREEN_NAIL_MAX; i++) {
-            if (i == 0) {
-                mPictures.put(i, new FullPicture());
-            } else {
-                mPictures.put(i, new ScreenNailPicture(i));
-            }
-        }
-    }
-
-    public void stopScrolling() {
-        mPositionController.stopScrolling();
-    }
-
-    public void setModel(Model model) {
-        mModel = model;
-        mTileView.setModel(mModel);
-    }
-
-    class MyHandler extends SynchronizedHandler {
-        public MyHandler(GLRoot root) {
-            super(root);
-        }
-
-        @Override
-        public void handleMessage(Message message) {
-            switch (message.what) {
-                case MSG_CANCEL_EXTRA_SCALING: {
-                    mGestureRecognizer.cancelScale();
-                    mPositionController.setExtraScalingRange(false);
-                    mCancelExtraScalingPending = false;
-                    break;
-                }
-                case MSG_SWITCH_FOCUS: {
-                    switchFocus();
-                    break;
-                }
-                case MSG_CAPTURE_ANIMATION_DONE: {
-                    // message.arg1 is the offset parameter passed to
-                    // switchWithCaptureAnimation().
-                    captureAnimationDone(message.arg1);
-                    break;
-                }
-                case MSG_DELETE_ANIMATION_DONE: {
-                    // message.obj is the Path of the MediaItem which should be
-                    // deleted. message.arg1 is the offset of the image.
-                    mListener.onDeleteImage((Path) message.obj, message.arg1);
-                    // Normally a box which finishes delete animation will hold
-                    // position until the underlying MediaItem is actually
-                    // deleted, and HOLD_DELETE will be cancelled that time. In
-                    // case the MediaItem didn't actually get deleted in 2
-                    // seconds, we will cancel HOLD_DELETE and make it bounce
-                    // back.
-
-                    // We make sure there is at most one MSG_DELETE_DONE
-                    // in the handler.
-                    mHandler.removeMessages(MSG_DELETE_DONE);
-                    Message m = mHandler.obtainMessage(MSG_DELETE_DONE);
-                    mHandler.sendMessageDelayed(m, 2000);
-
-                    int numberOfPictures = mNextBound - mPrevBound + 1;
-                    if (numberOfPictures == 2) {
-                        if (mModel.isCamera(mNextBound)
-                                || mModel.isCamera(mPrevBound)) {
-                            numberOfPictures--;
-                        }
-                    }
-                    showUndoBar(numberOfPictures <= 1);
-                    break;
-                }
-                case MSG_DELETE_DONE: {
-                    if (!mHandler.hasMessages(MSG_DELETE_ANIMATION_DONE)) {
-                        mHolding &= ~HOLD_DELETE;
-                        snapback();
-                    }
-                    break;
-                }
-                case MSG_UNDO_BAR_TIMEOUT: {
-                    checkHideUndoBar(UNDO_BAR_TIMEOUT);
-                    break;
-                }
-                case MSG_UNDO_BAR_FULL_CAMERA: {
-                    checkHideUndoBar(UNDO_BAR_FULL_CAMERA);
-                    break;
-                }
-                default: throw new AssertionError(message.what);
-            }
-        }
-    }
-
-    public void setWantPictureCenterCallbacks(boolean wanted) {
-        mWantPictureCenterCallbacks = wanted;
-    }
-
-    ////////////////////////////////////////////////////////////////////////////
-    //  Data/Image change notifications
-    ////////////////////////////////////////////////////////////////////////////
-
-    public void notifyDataChange(int[] fromIndex, int prevBound, int nextBound) {
-        mPrevBound = prevBound;
-        mNextBound = nextBound;
-
-        // Update mTouchBoxIndex
-        if (mTouchBoxIndex != Integer.MAX_VALUE) {
-            int k = mTouchBoxIndex;
-            mTouchBoxIndex = Integer.MAX_VALUE;
-            for (int i = 0; i < 2 * SCREEN_NAIL_MAX + 1; i++) {
-                if (fromIndex[i] == k) {
-                    mTouchBoxIndex = i - SCREEN_NAIL_MAX;
-                    break;
-                }
-            }
-        }
-
-        // Hide undo button if we are too far away
-        if (mUndoIndexHint != Integer.MAX_VALUE) {
-            if (Math.abs(mUndoIndexHint - mModel.getCurrentIndex()) >= 3) {
-                hideUndoBar();
-            }
-        }
-
-        // Update the ScreenNails.
-        for (int i = -SCREEN_NAIL_MAX; i <= SCREEN_NAIL_MAX; i++) {
-            Picture p =  mPictures.get(i);
-            p.reload();
-            mSizes[i + SCREEN_NAIL_MAX] = p.getSize();
-        }
-
-        boolean wasDeleting = mPositionController.hasDeletingBox();
-
-        // Move the boxes
-        mPositionController.moveBox(fromIndex, mPrevBound < 0, mNextBound > 0,
-                mModel.isCamera(0), mSizes);
-
-        for (int i = -SCREEN_NAIL_MAX; i <= SCREEN_NAIL_MAX; i++) {
-            setPictureSize(i);
-        }
-
-        boolean isDeleting = mPositionController.hasDeletingBox();
-
-        // If the deletion is done, make HOLD_DELETE persist for only the time
-        // needed for a snapback animation.
-        if (wasDeleting && !isDeleting) {
-            mHandler.removeMessages(MSG_DELETE_DONE);
-            Message m = mHandler.obtainMessage(MSG_DELETE_DONE);
-            mHandler.sendMessageDelayed(
-                    m, PositionController.SNAPBACK_ANIMATION_TIME);
-        }
-
-        invalidate();
-    }
-
-    public boolean isDeleting() {
-        return (mHolding & HOLD_DELETE) != 0
-                && mPositionController.hasDeletingBox();
-    }
-
-    public void notifyImageChange(int index) {
-        if (index == 0) {
-            mListener.onCurrentImageUpdated();
-        }
-        mPictures.get(index).reload();
-        setPictureSize(index);
-        invalidate();
-    }
-
-    private void setPictureSize(int index) {
-        Picture p = mPictures.get(index);
-        mPositionController.setImageSize(index, p.getSize(),
-                index == 0 && p.isCamera() ? mCameraRect : null);
-    }
-
-    @Override
-    protected void onLayout(
-            boolean changeSize, int left, int top, int right, int bottom) {
-        int w = right - left;
-        int h = bottom - top;
-        mTileView.layout(0, 0, w, h);
-        mEdgeView.layout(0, 0, w, h);
-        mUndoBar.measure(MeasureSpec.UNSPECIFIED, MeasureSpec.UNSPECIFIED);
-        mUndoBar.layout(0, h - mUndoBar.getMeasuredHeight(), w, h);
-
-        GLRoot root = getGLRoot();
-        int displayRotation = root.getDisplayRotation();
-        int compensation = root.getCompensation();
-        if (mDisplayRotation != displayRotation
-                || mCompensation != compensation) {
-            mDisplayRotation = displayRotation;
-            mCompensation = compensation;
-
-            // We need to change the size and rotation of the Camera ScreenNail,
-            // but we don't want it to animate because the size doen't actually
-            // change in the eye of the user.
-            for (int i = -SCREEN_NAIL_MAX; i <= SCREEN_NAIL_MAX; i++) {
-                Picture p = mPictures.get(i);
-                if (p.isCamera()) {
-                    p.forceSize();
-                }
-            }
-        }
-
-        updateCameraRect();
-        mPositionController.setConstrainedFrame(mCameraRect);
-        if (changeSize) {
-            mPositionController.setViewSize(getWidth(), getHeight());
-        }
-    }
-
-    // Update the camera rectangle due to layout change or camera relative frame
-    // change.
-    private void updateCameraRect() {
-        // Get the width and height in framework orientation because the given
-        // mCameraRelativeFrame is in that coordinates.
-        int w = getWidth();
-        int h = getHeight();
-        if (mCompensation % 180 != 0) {
-            int tmp = w;
-            w = h;
-            h = tmp;
-        }
-        int l = mCameraRelativeFrame.left;
-        int t = mCameraRelativeFrame.top;
-        int r = mCameraRelativeFrame.right;
-        int b = mCameraRelativeFrame.bottom;
-
-        // Now convert it to the coordinates we are using.
-        switch (mCompensation) {
-            case 0: mCameraRect.set(l, t, r, b); break;
-            case 90: mCameraRect.set(h - b, l, h - t, r); break;
-            case 180: mCameraRect.set(w - r, h - b, w - l, h - t); break;
-            case 270: mCameraRect.set(t, w - r, b, w - l); break;
-        }
-
-        Log.d(TAG, "compensation = " + mCompensation
-                + ", CameraRelativeFrame = " + mCameraRelativeFrame
-                + ", mCameraRect = " + mCameraRect);
-    }
-
-    public void setCameraRelativeFrame(Rect frame) {
-        mCameraRelativeFrame.set(frame);
-        updateCameraRect();
-        // Originally we do
-        //     mPositionController.setConstrainedFrame(mCameraRect);
-        // here, but it is moved to a parameter of the setImageSize() call, so
-        // it can be updated atomically with the CameraScreenNail's size change.
-    }
-
-    // Returns the rotation we need to do to the camera texture before drawing
-    // it to the canvas, assuming the camera texture is correct when the device
-    // is in its natural orientation.
-    private int getCameraRotation() {
-        return (mCompensation - mDisplayRotation + 360) % 360;
-    }
-
-    private int getPanoramaRotation() {
-        // This function is magic
-        // The issue here is that Pano makes bad assumptions about rotation and
-        // orientation. The first is it assumes only two rotations are possible,
-        // 0 and 90. Thus, if display rotation is >= 180, we invert the output.
-        // The second is that it assumes landscape is a 90 rotation from portrait,
-        // however on landscape devices this is not true. Thus, if we are in portrait
-        // on a landscape device, we need to invert the output
-        int orientation = mContext.getResources().getConfiguration().orientation;
-        boolean invertPortrait = (orientation == Configuration.ORIENTATION_PORTRAIT
-                && (mDisplayRotation == 90 || mDisplayRotation == 270));
-        boolean invert = (mDisplayRotation >= 180);
-        if (invert != invertPortrait) {
-            return (mCompensation + 180) % 360;
-        }
-        return mCompensation;
-    }
-
-    ////////////////////////////////////////////////////////////////////////////
-    //  Pictures
-    ////////////////////////////////////////////////////////////////////////////
-
-    private interface Picture {
-        void reload();
-        void draw(GLCanvas canvas, Rect r);
-        void setScreenNail(ScreenNail s);
-        boolean isCamera();  // whether the picture is a camera preview
-        boolean isDeletable();  // whether the picture can be deleted
-        void forceSize();  // called when mCompensation changes
-        Size getSize();
-    }
-
-    class FullPicture implements Picture {
-        private int mRotation;
-        private boolean mIsCamera;
-        private boolean mIsPanorama;
-        private boolean mIsStaticCamera;
-        private boolean mIsVideo;
-        private boolean mIsDeletable;
-        private int mLoadingState = Model.LOADING_INIT;
-        private Size mSize = new Size();
-
-        @Override
-        public void reload() {
-            // mImageWidth and mImageHeight will get updated
-            mTileView.notifyModelInvalidated();
-
-            mIsCamera = mModel.isCamera(0);
-            mIsPanorama = mModel.isPanorama(0);
-            mIsStaticCamera = mModel.isStaticCamera(0);
-            mIsVideo = mModel.isVideo(0);
-            mIsDeletable = mModel.isDeletable(0);
-            mLoadingState = mModel.getLoadingState(0);
-            setScreenNail(mModel.getScreenNail(0));
-            updateSize();
-        }
-
-        @Override
-        public Size getSize() {
-            return mSize;
-        }
-
-        @Override
-        public void forceSize() {
-            updateSize();
-            mPositionController.forceImageSize(0, mSize);
-        }
-
-        private void updateSize() {
-            if (mIsPanorama) {
-                mRotation = getPanoramaRotation();
-            } else if (mIsCamera && !mIsStaticCamera) {
-                mRotation = getCameraRotation();
-            } else {
-                mRotation = mModel.getImageRotation(0);
-            }
-
-            int w = mTileView.mImageWidth;
-            int h = mTileView.mImageHeight;
-            mSize.width = getRotated(mRotation, w, h);
-            mSize.height = getRotated(mRotation, h, w);
-        }
-
-        @Override
-        public void draw(GLCanvas canvas, Rect r) {
-            drawTileView(canvas, r);
-
-            // We want to have the following transitions:
-            // (1) Move camera preview out of its place: switch to film mode
-            // (2) Move camera preview into its place: switch to page mode
-            // The extra mWasCenter check makes sure (1) does not apply if in
-            // page mode, we move _to_ the camera preview from another picture.
-
-            // Holdings except touch-down prevent the transitions.
-            if ((mHolding & ~HOLD_TOUCH_DOWN) != 0) return;
-
-            if (mWantPictureCenterCallbacks && mPositionController.isCenter()) {
-                mListener.onPictureCenter(mIsCamera);
-            }
-        }
-
-        @Override
-        public void setScreenNail(ScreenNail s) {
-            mTileView.setScreenNail(s);
-        }
-
-        @Override
-        public boolean isCamera() {
-            return mIsCamera;
-        }
-
-        @Override
-        public boolean isDeletable() {
-            return mIsDeletable;
-        }
-
-        private void drawTileView(GLCanvas canvas, Rect r) {
-            float imageScale = mPositionController.getImageScale();
-            int viewW = getWidth();
-            int viewH = getHeight();
-            float cx = r.exactCenterX();
-            float cy = r.exactCenterY();
-            float scale = 1f;  // the scaling factor due to card effect
-
-            canvas.save(GLCanvas.SAVE_FLAG_MATRIX | GLCanvas.SAVE_FLAG_ALPHA);
-            float filmRatio = mPositionController.getFilmRatio();
-            boolean wantsCardEffect = CARD_EFFECT && !mIsCamera
-                    && filmRatio != 1f && !mPictures.get(-1).isCamera()
-                    && !mPositionController.inOpeningAnimation();
-            boolean wantsOffsetEffect = OFFSET_EFFECT && mIsDeletable
-                    && filmRatio == 1f && r.centerY() != viewH / 2;
-            if (wantsCardEffect) {
-                // Calculate the move-out progress value.
-                int left = r.left;
-                int right = r.right;
-                float progress = calculateMoveOutProgress(left, right, viewW);
-                progress = Utils.clamp(progress, -1f, 1f);
-
-                // We only want to apply the fading animation if the scrolling
-                // movement is to the right.
-                if (progress < 0) {
-                    scale = getScrollScale(progress);
-                    float alpha = getScrollAlpha(progress);
-                    scale = interpolate(filmRatio, scale, 1f);
-                    alpha = interpolate(filmRatio, alpha, 1f);
-
-                    imageScale *= scale;
-                    canvas.multiplyAlpha(alpha);
-
-                    float cxPage;  // the cx value in page mode
-                    if (right - left <= viewW) {
-                        // If the picture is narrower than the view, keep it at
-                        // the center of the view.
-                        cxPage = viewW / 2f;
-                    } else {
-                        // If the picture is wider than the view (it's
-                        // zoomed-in), keep the left edge of the object align
-                        // the the left edge of the view.
-                        cxPage = (right - left) * scale / 2f;
-                    }
-                    cx = interpolate(filmRatio, cxPage, cx);
-                }
-            } else if (wantsOffsetEffect) {
-                float offset = (float) (r.centerY() - viewH / 2) / viewH;
-                float alpha = getOffsetAlpha(offset);
-                canvas.multiplyAlpha(alpha);
-            }
-
-            // Draw the tile view.
-            setTileViewPosition(cx, cy, viewW, viewH, imageScale);
-            renderChild(canvas, mTileView);
-
-            // Draw the play video icon and the message.
-            canvas.translate((int) (cx + 0.5f), (int) (cy + 0.5f));
-            int s = (int) (scale * Math.min(r.width(), r.height()) + 0.5f);
-            if (mIsVideo) drawVideoPlayIcon(canvas, s);
-            if (mLoadingState == Model.LOADING_FAIL) {
-                drawLoadingFailMessage(canvas);
-            }
-
-            // Draw a debug indicator showing which picture has focus (index ==
-            // 0).
-            //canvas.fillRect(-10, -10, 20, 20, 0x80FF00FF);
-
-            canvas.restore();
-        }
-
-        // Set the position of the tile view
-        private void setTileViewPosition(float cx, float cy,
-                int viewW, int viewH, float scale) {
-            // Find out the bitmap coordinates of the center of the view
-            int imageW = mPositionController.getImageWidth();
-            int imageH = mPositionController.getImageHeight();
-            int centerX = (int) (imageW / 2f + (viewW / 2f - cx) / scale + 0.5f);
-            int centerY = (int) (imageH / 2f + (viewH / 2f - cy) / scale + 0.5f);
-
-            int inverseX = imageW - centerX;
-            int inverseY = imageH - centerY;
-            int x, y;
-            switch (mRotation) {
-                case 0: x = centerX; y = centerY; break;
-                case 90: x = centerY; y = inverseX; break;
-                case 180: x = inverseX; y = inverseY; break;
-                case 270: x = inverseY; y = centerX; break;
-                default:
-                    throw new RuntimeException(String.valueOf(mRotation));
-            }
-            mTileView.setPosition(x, y, scale, mRotation);
-        }
-    }
-
-    private class ScreenNailPicture implements Picture {
-        private int mIndex;
-        private int mRotation;
-        private ScreenNail mScreenNail;
-        private boolean mIsCamera;
-        private boolean mIsPanorama;
-        private boolean mIsStaticCamera;
-        private boolean mIsVideo;
-        private boolean mIsDeletable;
-        private int mLoadingState = Model.LOADING_INIT;
-        private Size mSize = new Size();
-
-        public ScreenNailPicture(int index) {
-            mIndex = index;
-        }
-
-        @Override
-        public void reload() {
-            mIsCamera = mModel.isCamera(mIndex);
-            mIsPanorama = mModel.isPanorama(mIndex);
-            mIsStaticCamera = mModel.isStaticCamera(mIndex);
-            mIsVideo = mModel.isVideo(mIndex);
-            mIsDeletable = mModel.isDeletable(mIndex);
-            mLoadingState = mModel.getLoadingState(mIndex);
-            setScreenNail(mModel.getScreenNail(mIndex));
-            updateSize();
-        }
-
-        @Override
-        public Size getSize() {
-            return mSize;
-        }
-
-        @Override
-        public void draw(GLCanvas canvas, Rect r) {
-            if (mScreenNail == null) {
-                // Draw a placeholder rectange if there should be a picture in
-                // this position (but somehow there isn't).
-                if (mIndex >= mPrevBound && mIndex <= mNextBound) {
-                    drawPlaceHolder(canvas, r);
-                }
-                return;
-            }
-            int w = getWidth();
-            int h = getHeight();
-            if (r.left >= w || r.right <= 0 || r.top >= h || r.bottom <= 0) {
-                mScreenNail.noDraw();
-                return;
-            }
-
-            float filmRatio = mPositionController.getFilmRatio();
-            boolean wantsCardEffect = CARD_EFFECT && mIndex > 0
-                    && filmRatio != 1f && !mPictures.get(0).isCamera();
-            boolean wantsOffsetEffect = OFFSET_EFFECT && mIsDeletable
-                    && filmRatio == 1f && r.centerY() != h / 2;
-            int cx = wantsCardEffect
-                    ? (int) (interpolate(filmRatio, w / 2, r.centerX()) + 0.5f)
-                    : r.centerX();
-            int cy = r.centerY();
-            canvas.save(GLCanvas.SAVE_FLAG_MATRIX | GLCanvas.SAVE_FLAG_ALPHA);
-            canvas.translate(cx, cy);
-            if (wantsCardEffect) {
-                float progress = (float) (w / 2 - r.centerX()) / w;
-                progress = Utils.clamp(progress, -1, 1);
-                float alpha = getScrollAlpha(progress);
-                float scale = getScrollScale(progress);
-                alpha = interpolate(filmRatio, alpha, 1f);
-                scale = interpolate(filmRatio, scale, 1f);
-                canvas.multiplyAlpha(alpha);
-                canvas.scale(scale, scale, 1);
-            } else if (wantsOffsetEffect) {
-                float offset = (float) (r.centerY() - h / 2) / h;
-                float alpha = getOffsetAlpha(offset);
-                canvas.multiplyAlpha(alpha);
-            }
-            if (mRotation != 0) {
-                canvas.rotate(mRotation, 0, 0, 1);
-            }
-            int drawW = getRotated(mRotation, r.width(), r.height());
-            int drawH = getRotated(mRotation, r.height(), r.width());
-            mScreenNail.draw(canvas, -drawW / 2, -drawH / 2, drawW, drawH);
-            if (isScreenNailAnimating()) {
-                invalidate();
-            }
-            int s = Math.min(drawW, drawH);
-            if (mIsVideo) drawVideoPlayIcon(canvas, s);
-            if (mLoadingState == Model.LOADING_FAIL) {
-                drawLoadingFailMessage(canvas);
-            }
-            canvas.restore();
-        }
-
-        private boolean isScreenNailAnimating() {
-            return (mScreenNail instanceof TiledScreenNail)
-                    && ((TiledScreenNail) mScreenNail).isAnimating();
-        }
-
-        @Override
-        public void setScreenNail(ScreenNail s) {
-            mScreenNail = s;
-        }
-
-        @Override
-        public void forceSize() {
-            updateSize();
-            mPositionController.forceImageSize(mIndex, mSize);
-        }
-
-        private void updateSize() {
-            if (mIsPanorama) {
-                mRotation = getPanoramaRotation();
-            } else if (mIsCamera && !mIsStaticCamera) {
-                mRotation = getCameraRotation();
-            } else {
-                mRotation = mModel.getImageRotation(mIndex);
-            }
-
-            if (mScreenNail != null) {
-                mSize.width = mScreenNail.getWidth();
-                mSize.height = mScreenNail.getHeight();
-            } else {
-                // If we don't have ScreenNail available, we can still try to
-                // get the size information of it.
-                mModel.getImageSize(mIndex, mSize);
-            }
-
-            int w = mSize.width;
-            int h = mSize.height;
-            mSize.width = getRotated(mRotation, w, h);
-            mSize.height = getRotated(mRotation, h, w);
-        }
-
-        @Override
-        public boolean isCamera() {
-            return mIsCamera;
-        }
-
-        @Override
-        public boolean isDeletable() {
-            return mIsDeletable;
-        }
-    }
-
-    // Draw a gray placeholder in the specified rectangle.
-    private void drawPlaceHolder(GLCanvas canvas, Rect r) {
-        canvas.fillRect(r.left, r.top, r.width(), r.height(), mPlaceholderColor);
-    }
-
-    // Draw the video play icon (in the place where the spinner was)
-    private void drawVideoPlayIcon(GLCanvas canvas, int side) {
-        int s = side / ICON_RATIO;
-        // Draw the video play icon at the center
-        mVideoPlayIcon.draw(canvas, -s / 2, -s / 2, s, s);
-    }
-
-    // Draw the "no thumbnail" message
-    private void drawLoadingFailMessage(GLCanvas canvas) {
-        StringTexture m = mNoThumbnailText;
-        m.draw(canvas, -m.getWidth() / 2, -m.getHeight() / 2);
-    }
-
-    private static int getRotated(int degree, int original, int theother) {
-        return (degree % 180 == 0) ? original : theother;
-    }
-
-    ////////////////////////////////////////////////////////////////////////////
-    //  Gestures Handling
-    ////////////////////////////////////////////////////////////////////////////
-
-    @Override
-    protected boolean onTouch(MotionEvent event) {
-        mGestureRecognizer.onTouchEvent(event);
-        return true;
-    }
-
-    private class MyGestureListener implements GestureRecognizer.Listener {
-        private boolean mIgnoreUpEvent = false;
-        // If we can change mode for this scale gesture.
-        private boolean mCanChangeMode;
-        // If we have changed the film mode in this scaling gesture.
-        private boolean mModeChanged;
-        // If this scaling gesture should be ignored.
-        private boolean mIgnoreScalingGesture;
-        // whether the down action happened while the view is scrolling.
-        private boolean mDownInScrolling;
-        // If we should ignore all gestures other than onSingleTapUp.
-        private boolean mIgnoreSwipingGesture;
-        // If a scrolling has happened after a down gesture.
-        private boolean mScrolledAfterDown;
-        // If the first scrolling move is in X direction. In the film mode, X
-        // direction scrolling is normal scrolling. but Y direction scrolling is
-        // a delete gesture.
-        private boolean mFirstScrollX;
-        // The accumulated Y delta that has been sent to mPositionController.
-        private int mDeltaY;
-        // The accumulated scaling change from a scaling gesture.
-        private float mAccScale;
-        // If an onFling happened after the last onDown
-        private boolean mHadFling;
-
-        @Override
-        public boolean onSingleTapUp(float x, float y) {
-            // On crespo running Android 2.3.6 (gingerbread), a pinch out gesture results in the
-            // following call sequence: onDown(), onUp() and then onSingleTapUp(). The correct
-            // sequence for a single-tap-up gesture should be: onDown(), onSingleTapUp() and onUp().
-            // The call sequence for a pinch out gesture in JB is: onDown(), then onUp() and there's
-            // no onSingleTapUp(). Base on these observations, the following condition is added to
-            // filter out the false alarm where onSingleTapUp() is called within a pinch out
-            // gesture. The framework fix went into ICS. Refer to b/4588114.
-            if (Build.VERSION.SDK_INT < ApiHelper.VERSION_CODES.ICE_CREAM_SANDWICH) {
-                if ((mHolding & HOLD_TOUCH_DOWN) == 0) {
-                    return true;
-                }
-            }
-
-            // We do this in addition to onUp() because we want the snapback of
-            // setFilmMode to happen.
-            mHolding &= ~HOLD_TOUCH_DOWN;
-
-            if (mFilmMode && !mDownInScrolling) {
-                switchToHitPicture((int) (x + 0.5f), (int) (y + 0.5f));
-
-                // If this is a lock screen photo, let the listener handle the
-                // event. Tapping on lock screen photo should take the user
-                // directly to the lock screen.
-                MediaItem item = mModel.getMediaItem(0);
-                int supported = 0;
-                if (item != null) supported = item.getSupportedOperations();
-                if ((supported & MediaItem.SUPPORT_ACTION) == 0) {
-                    setFilmMode(false);
-                    mIgnoreUpEvent = true;
-                    return true;
-                }
-            }
-
-            if (mListener != null) {
-                // Do the inverse transform of the touch coordinates.
-                Matrix m = getGLRoot().getCompensationMatrix();
-                Matrix inv = new Matrix();
-                m.invert(inv);
-                float[] pts = new float[] {x, y};
-                inv.mapPoints(pts);
-                mListener.onSingleTapUp((int) (pts[0] + 0.5f), (int) (pts[1] + 0.5f));
-            }
-            return true;
-        }
-
-        @Override
-        public boolean onDoubleTap(float x, float y) {
-            if (mIgnoreSwipingGesture) return true;
-            if (mPictures.get(0).isCamera()) return false;
-            PositionController controller = mPositionController;
-            float scale = controller.getImageScale();
-            // onDoubleTap happened on the second ACTION_DOWN.
-            // We need to ignore the next UP event.
-            mIgnoreUpEvent = true;
-            if (scale <= .75f || controller.isAtMinimalScale()) {
-                controller.zoomIn(x, y, Math.max(1.0f, scale * 1.5f));
-            } else {
-                controller.resetToFullView();
-            }
-            return true;
-        }
-
-        @Override
-        public boolean onScroll(float dx, float dy, float totalX, float totalY) {
-            if (mIgnoreSwipingGesture) return true;
-            if (!mScrolledAfterDown) {
-                mScrolledAfterDown = true;
-                mFirstScrollX = (Math.abs(dx) > Math.abs(dy));
-            }
-
-            int dxi = (int) (-dx + 0.5f);
-            int dyi = (int) (-dy + 0.5f);
-            if (mFilmMode) {
-                if (mFirstScrollX) {
-                    mPositionController.scrollFilmX(dxi);
-                } else {
-                    if (mTouchBoxIndex == Integer.MAX_VALUE) return true;
-                    int newDeltaY = calculateDeltaY(totalY);
-                    int d = newDeltaY - mDeltaY;
-                    if (d != 0) {
-                        mPositionController.scrollFilmY(mTouchBoxIndex, d);
-                        mDeltaY = newDeltaY;
-                    }
-                }
-            } else {
-                mPositionController.scrollPage(dxi, dyi);
-            }
-            return true;
-        }
-
-        private int calculateDeltaY(float delta) {
-            if (mTouchBoxDeletable) return (int) (delta + 0.5f);
-
-            // don't let items that can't be deleted be dragged more than
-            // maxScrollDistance, and make it harder and harder to drag.
-            int size = getHeight();
-            float maxScrollDistance = 0.15f * size;
-            if (Math.abs(delta) >= size) {
-                delta = delta > 0 ? maxScrollDistance : -maxScrollDistance;
-            } else {
-                delta = maxScrollDistance *
-                        FloatMath.sin((delta / size) * (float) (Math.PI / 2));
-            }
-            return (int) (delta + 0.5f);
-        }
-
-        @Override
-        public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
-            if (mIgnoreSwipingGesture) return true;
-            if (mModeChanged) return true;
-            if (swipeImages(velocityX, velocityY)) {
-                mIgnoreUpEvent = true;
-            } else {
-                flingImages(velocityX, velocityY, Math.abs(e2.getY() - e1.getY()));
-            }
-            mHadFling = true;
-            return true;
-        }
-
-        private boolean flingImages(float velocityX, float velocityY, float dY) {
-            int vx = (int) (velocityX + 0.5f);
-            int vy = (int) (velocityY + 0.5f);
-            if (!mFilmMode) {
-                return mPositionController.flingPage(vx, vy);
-            }
-            if (Math.abs(velocityX) > Math.abs(velocityY)) {
-                return mPositionController.flingFilmX(vx);
-            }
-            // If we scrolled in Y direction fast enough, treat it as a delete
-            // gesture.
-            if (!mFilmMode || mTouchBoxIndex == Integer.MAX_VALUE
-                    || !mTouchBoxDeletable) {
-                return false;
-            }
-            int maxVelocity = GalleryUtils.dpToPixel(MAX_DISMISS_VELOCITY);
-            int escapeVelocity = GalleryUtils.dpToPixel(SWIPE_ESCAPE_VELOCITY);
-            int escapeDistance = GalleryUtils.dpToPixel(SWIPE_ESCAPE_DISTANCE);
-            int centerY = mPositionController.getPosition(mTouchBoxIndex)
-                    .centerY();
-            boolean fastEnough = (Math.abs(vy) > escapeVelocity)
-                    && (Math.abs(vy) > Math.abs(vx))
-                    && ((vy > 0) == (centerY > getHeight() / 2))
-                    && dY >= escapeDistance;
-            if (fastEnough) {
-                vy = Math.min(vy, maxVelocity);
-                int duration = mPositionController.flingFilmY(mTouchBoxIndex, vy);
-                if (duration >= 0) {
-                    mPositionController.setPopFromTop(vy < 0);
-                    deleteAfterAnimation(duration);
-                    // We reset mTouchBoxIndex, so up() won't check if Y
-                    // scrolled far enough to be a delete gesture.
-                    mTouchBoxIndex = Integer.MAX_VALUE;
-                    return true;
-                }
-            }
-            return false;
-        }
-
-        private void deleteAfterAnimation(int duration) {
-            MediaItem item = mModel.getMediaItem(mTouchBoxIndex);
-            if (item == null) return;
-            mListener.onCommitDeleteImage();
-            mUndoIndexHint = mModel.getCurrentIndex() + mTouchBoxIndex;
-            mHolding |= HOLD_DELETE;
-            Message m = mHandler.obtainMessage(MSG_DELETE_ANIMATION_DONE);
-            m.obj = item.getPath();
-            m.arg1 = mTouchBoxIndex;
-            mHandler.sendMessageDelayed(m, duration);
-        }
-
-        @Override
-        public boolean onScaleBegin(float focusX, float focusY) {
-            if (mIgnoreSwipingGesture) return true;
-            // We ignore the scaling gesture if it is a camera preview.
-            mIgnoreScalingGesture = mPictures.get(0).isCamera();
-            if (mIgnoreScalingGesture) {
-                return true;
-            }
-            mPositionController.beginScale(focusX, focusY);
-            // We can change mode if we are in film mode, or we are in page
-            // mode and at minimal scale.
-            mCanChangeMode = mFilmMode
-                    || mPositionController.isAtMinimalScale();
-            mAccScale = 1f;
-            return true;
-        }
-
-        @Override
-        public boolean onScale(float focusX, float focusY, float scale) {
-            if (mIgnoreSwipingGesture) return true;
-            if (mIgnoreScalingGesture) return true;
-            if (mModeChanged) return true;
-            if (Float.isNaN(scale) || Float.isInfinite(scale)) return false;
-
-            int outOfRange = mPositionController.scaleBy(scale, focusX, focusY);
-
-            // We wait for a large enough scale change before changing mode.
-            // Otherwise we may mistakenly treat a zoom-in gesture as zoom-out
-            // or vice versa.
-            mAccScale *= scale;
-            boolean largeEnough = (mAccScale < 0.97f || mAccScale > 1.03f);
-
-            // If mode changes, we treat this scaling gesture has ended.
-            if (mCanChangeMode && largeEnough) {
-                if ((outOfRange < 0 && !mFilmMode) ||
-                        (outOfRange > 0 && mFilmMode)) {
-                    stopExtraScalingIfNeeded();
-
-                    // Removing the touch down flag allows snapback to happen
-                    // for film mode change.
-                    mHolding &= ~HOLD_TOUCH_DOWN;
-                    if (mFilmMode) {
-                        UsageStatistics.setPendingTransitionCause(
-                                UsageStatistics.TRANSITION_PINCH_OUT);
-                    } else {
-                        UsageStatistics.setPendingTransitionCause(
-                                UsageStatistics.TRANSITION_PINCH_IN);
-                    }
-                    setFilmMode(!mFilmMode);
-
-
-                    // We need to call onScaleEnd() before setting mModeChanged
-                    // to true.
-                    onScaleEnd();
-                    mModeChanged = true;
-                    return true;
-                }
-           }
-
-            if (outOfRange != 0) {
-                startExtraScalingIfNeeded();
-            } else {
-                stopExtraScalingIfNeeded();
-            }
-            return true;
-        }
-
-        @Override
-        public void onScaleEnd() {
-            if (mIgnoreSwipingGesture) return;
-            if (mIgnoreScalingGesture) return;
-            if (mModeChanged) return;
-            mPositionController.endScale();
-        }
-
-        private void startExtraScalingIfNeeded() {
-            if (!mCancelExtraScalingPending) {
-                mHandler.sendEmptyMessageDelayed(
-                        MSG_CANCEL_EXTRA_SCALING, 700);
-                mPositionController.setExtraScalingRange(true);
-                mCancelExtraScalingPending = true;
-            }
-        }
-
-        private void stopExtraScalingIfNeeded() {
-            if (mCancelExtraScalingPending) {
-                mHandler.removeMessages(MSG_CANCEL_EXTRA_SCALING);
-                mPositionController.setExtraScalingRange(false);
-                mCancelExtraScalingPending = false;
-            }
-        }
-
-        @Override
-        public void onDown(float x, float y) {
-            checkHideUndoBar(UNDO_BAR_TOUCHED);
-
-            mDeltaY = 0;
-            mModeChanged = false;
-
-            if (mIgnoreSwipingGesture) return;
-
-            mHolding |= HOLD_TOUCH_DOWN;
-
-            if (mFilmMode && mPositionController.isScrolling()) {
-                mDownInScrolling = true;
-                mPositionController.stopScrolling();
-            } else {
-                mDownInScrolling = false;
-            }
-            mHadFling = false;
-            mScrolledAfterDown = false;
-            if (mFilmMode) {
-                int xi = (int) (x + 0.5f);
-                int yi = (int) (y + 0.5f);
-                // We only care about being within the x bounds, necessary for
-                // handling very wide images which are otherwise very hard to fling
-                mTouchBoxIndex = mPositionController.hitTest(xi, getHeight() / 2);
-
-                if (mTouchBoxIndex < mPrevBound || mTouchBoxIndex > mNextBound) {
-                    mTouchBoxIndex = Integer.MAX_VALUE;
-                } else {
-                    mTouchBoxDeletable =
-                            mPictures.get(mTouchBoxIndex).isDeletable();
-                }
-            } else {
-                mTouchBoxIndex = Integer.MAX_VALUE;
-            }
-        }
-
-        @Override
-        public void onUp() {
-            if (mIgnoreSwipingGesture) return;
-
-            mHolding &= ~HOLD_TOUCH_DOWN;
-            mEdgeView.onRelease();
-
-            // If we scrolled in Y direction far enough, treat it as a delete
-            // gesture.
-            if (mFilmMode && mScrolledAfterDown && !mFirstScrollX
-                    && mTouchBoxIndex != Integer.MAX_VALUE) {
-                Rect r = mPositionController.getPosition(mTouchBoxIndex);
-                int h = getHeight();
-                if (Math.abs(r.centerY() - h * 0.5f) > 0.4f * h) {
-                    int duration = mPositionController
-                            .flingFilmY(mTouchBoxIndex, 0);
-                    if (duration >= 0) {
-                        mPositionController.setPopFromTop(r.centerY() < h * 0.5f);
-                        deleteAfterAnimation(duration);
-                    }
-                }
-            }
-
-            if (mIgnoreUpEvent) {
-                mIgnoreUpEvent = false;
-                return;
-            }
-
-            if (!(mFilmMode && !mHadFling && mFirstScrollX
-                    && snapToNeighborImage())) {
-                snapback();
-            }
-        }
-
-        public void setSwipingEnabled(boolean enabled) {
-            mIgnoreSwipingGesture = !enabled;
-        }
-    }
-
-    public void setSwipingEnabled(boolean enabled) {
-        mGestureListener.setSwipingEnabled(enabled);
-    }
-
-    private void updateActionBar() {
-        boolean isCamera = mPictures.get(0).isCamera();
-        if (isCamera && !mFilmMode) {
-            // Move into camera in page mode, lock
-            mListener.onActionBarAllowed(false);
-        } else {
-            mListener.onActionBarAllowed(true);
-            if (mFilmMode) mListener.onActionBarWanted();
-        }
-    }
-
-    public void setFilmMode(boolean enabled) {
-        if (mFilmMode == enabled) return;
-        mFilmMode = enabled;
-        mPositionController.setFilmMode(mFilmMode);
-        mModel.setNeedFullImage(!enabled);
-        mModel.setFocusHintDirection(
-                mFilmMode ? Model.FOCUS_HINT_PREVIOUS : Model.FOCUS_HINT_NEXT);
-        updateActionBar();
-        mListener.onFilmModeChanged(enabled);
-    }
-
-    public boolean getFilmMode() {
-        return mFilmMode;
-    }
-
-    ////////////////////////////////////////////////////////////////////////////
-    //  Framework events
-    ////////////////////////////////////////////////////////////////////////////
-
-    public void pause() {
-        mPositionController.skipAnimation();
-        mTileView.freeTextures();
-        for (int i = -SCREEN_NAIL_MAX; i <= SCREEN_NAIL_MAX; i++) {
-            mPictures.get(i).setScreenNail(null);
-        }
-        hideUndoBar();
-    }
-
-    public void resume() {
-        mTileView.prepareTextures();
-        mPositionController.skipToFinalPosition();
-    }
-
-    // move to the camera preview and show controls after resume
-    public void resetToFirstPicture() {
-        mModel.moveTo(0);
-        setFilmMode(false);
-    }
-
-    ////////////////////////////////////////////////////////////////////////////
-    //  Undo Bar
-    ////////////////////////////////////////////////////////////////////////////
-
-    private int mUndoBarState;
-    private static final int UNDO_BAR_SHOW = 1;
-    private static final int UNDO_BAR_TIMEOUT = 2;
-    private static final int UNDO_BAR_TOUCHED = 4;
-    private static final int UNDO_BAR_FULL_CAMERA = 8;
-    private static final int UNDO_BAR_DELETE_LAST = 16;
-
-    // "deleteLast" means if the deletion is on the last remaining picture in
-    // the album.
-    private void showUndoBar(boolean deleteLast) {
-        mHandler.removeMessages(MSG_UNDO_BAR_TIMEOUT);
-        mUndoBarState = UNDO_BAR_SHOW;
-        if(deleteLast) mUndoBarState |= UNDO_BAR_DELETE_LAST;
-        mUndoBar.animateVisibility(GLView.VISIBLE);
-        mHandler.sendEmptyMessageDelayed(MSG_UNDO_BAR_TIMEOUT, 3000);
-        if (mListener != null) mListener.onUndoBarVisibilityChanged(true);
-    }
-
-    private void hideUndoBar() {
-        mHandler.removeMessages(MSG_UNDO_BAR_TIMEOUT);
-        mListener.onCommitDeleteImage();
-        mUndoBar.animateVisibility(GLView.INVISIBLE);
-        mUndoBarState = 0;
-        mUndoIndexHint = Integer.MAX_VALUE;
-        mListener.onUndoBarVisibilityChanged(false);
-    }
-
-    // Check if the one of the conditions for hiding the undo bar has been
-    // met. The conditions are:
-    //
-    // 1. It has been three seconds since last showing, and (a) the user has
-    // touched, or (b) the deleted picture is the last remaining picture in the
-    // album.
-    //
-    // 2. The camera is shown in full screen.
-    private void checkHideUndoBar(int addition) {
-        mUndoBarState |= addition;
-        if ((mUndoBarState & UNDO_BAR_SHOW) == 0) return;
-        boolean timeout = (mUndoBarState & UNDO_BAR_TIMEOUT) != 0;
-        boolean touched = (mUndoBarState & UNDO_BAR_TOUCHED) != 0;
-        boolean fullCamera = (mUndoBarState & UNDO_BAR_FULL_CAMERA) != 0;
-        boolean deleteLast = (mUndoBarState & UNDO_BAR_DELETE_LAST) != 0;
-        if ((timeout && deleteLast) || fullCamera || touched) {
-            hideUndoBar();
-        }
-    }
-
-    public boolean canUndo() {
-        return (mUndoBarState & UNDO_BAR_SHOW) != 0;
-    }
-
-    ////////////////////////////////////////////////////////////////////////////
-    //  Rendering
-    ////////////////////////////////////////////////////////////////////////////
-
-    @Override
-    protected void render(GLCanvas canvas) {
-        if (mFirst) {
-            // Make sure the fields are properly initialized before checking
-            // whether isCamera()
-            mPictures.get(0).reload();
-        }
-        // Check if the camera preview occupies the full screen.
-        boolean full = !mFilmMode && mPictures.get(0).isCamera()
-                && mPositionController.isCenter()
-                && mPositionController.isAtMinimalScale();
-        if (mFirst || full != mFullScreenCamera) {
-            mFullScreenCamera = full;
-            mFirst = false;
-            mListener.onFullScreenChanged(full);
-            if (full) mHandler.sendEmptyMessage(MSG_UNDO_BAR_FULL_CAMERA);
-        }
-
-        // Determine how many photos we need to draw in addition to the center
-        // one.
-        int neighbors;
-        if (mFullScreenCamera) {
-            neighbors = 0;
-        } else {
-            // In page mode, we draw only one previous/next photo. But if we are
-            // doing capture animation, we want to draw all photos.
-            boolean inPageMode = (mPositionController.getFilmRatio() == 0f);
-            boolean inCaptureAnimation =
-                    ((mHolding & HOLD_CAPTURE_ANIMATION) != 0);
-            if (inPageMode && !inCaptureAnimation) {
-                neighbors = 1;
-            } else {
-                neighbors = SCREEN_NAIL_MAX;
-            }
-        }
-
-        // Draw photos from back to front
-        for (int i = neighbors; i >= -neighbors; i--) {
-            Rect r = mPositionController.getPosition(i);
-            mPictures.get(i).draw(canvas, r);
-        }
-
-        renderChild(canvas, mEdgeView);
-        renderChild(canvas, mUndoBar);
-
-        mPositionController.advanceAnimation();
-        checkFocusSwitching();
-    }
-
-    ////////////////////////////////////////////////////////////////////////////
-    //  Film mode focus switching
-    ////////////////////////////////////////////////////////////////////////////
-
-    // Runs in GL thread.
-    private void checkFocusSwitching() {
-        if (!mFilmMode) return;
-        if (mHandler.hasMessages(MSG_SWITCH_FOCUS)) return;
-        if (switchPosition() != 0) {
-            mHandler.sendEmptyMessage(MSG_SWITCH_FOCUS);
-        }
-    }
-
-    // Runs in main thread.
-    private void switchFocus() {
-        if (mHolding != 0) return;
-        switch (switchPosition()) {
-            case -1:
-                switchToPrevImage();
-                break;
-            case 1:
-                switchToNextImage();
-                break;
-        }
-    }
-
-    // Returns -1 if we should switch focus to the previous picture, +1 if we
-    // should switch to the next, 0 otherwise.
-    private int switchPosition() {
-        Rect curr = mPositionController.getPosition(0);
-        int center = getWidth() / 2;
-
-        if (curr.left > center && mPrevBound < 0) {
-            Rect prev = mPositionController.getPosition(-1);
-            int currDist = curr.left - center;
-            int prevDist = center - prev.right;
-            if (prevDist < currDist) {
-                return -1;
-            }
-        } else if (curr.right < center && mNextBound > 0) {
-            Rect next = mPositionController.getPosition(1);
-            int currDist = center - curr.right;
-            int nextDist = next.left - center;
-            if (nextDist < currDist) {
-                return 1;
-            }
-        }
-
-        return 0;
-    }
-
-    // Switch to the previous or next picture if the hit position is inside
-    // one of their boxes. This runs in main thread.
-    private void switchToHitPicture(int x, int y) {
-        if (mPrevBound < 0) {
-            Rect r = mPositionController.getPosition(-1);
-            if (r.right >= x) {
-                slideToPrevPicture();
-                return;
-            }
-        }
-
-        if (mNextBound > 0) {
-            Rect r = mPositionController.getPosition(1);
-            if (r.left <= x) {
-                slideToNextPicture();
-                return;
-            }
-        }
-    }
-
-    ////////////////////////////////////////////////////////////////////////////
-    //  Page mode focus switching
-    //
-    //  We slide image to the next one or the previous one in two cases: 1: If
-    //  the user did a fling gesture with enough velocity.  2 If the user has
-    //  moved the picture a lot.
-    ////////////////////////////////////////////////////////////////////////////
-
-    private boolean swipeImages(float velocityX, float velocityY) {
-        if (mFilmMode) return false;
-
-        // Avoid swiping images if we're possibly flinging to view the
-        // zoomed in picture vertically.
-        PositionController controller = mPositionController;
-        boolean isMinimal = controller.isAtMinimalScale();
-        int edges = controller.getImageAtEdges();
-        if (!isMinimal && Math.abs(velocityY) > Math.abs(velocityX))
-            if ((edges & PositionController.IMAGE_AT_TOP_EDGE) == 0
-                    || (edges & PositionController.IMAGE_AT_BOTTOM_EDGE) == 0)
-                return false;
-
-        // If we are at the edge of the current photo and the sweeping velocity
-        // exceeds the threshold, slide to the next / previous image.
-        if (velocityX < -SWIPE_THRESHOLD && (isMinimal
-                || (edges & PositionController.IMAGE_AT_RIGHT_EDGE) != 0)) {
-            return slideToNextPicture();
-        } else if (velocityX > SWIPE_THRESHOLD && (isMinimal
-                || (edges & PositionController.IMAGE_AT_LEFT_EDGE) != 0)) {
-            return slideToPrevPicture();
-        }
-
-        return false;
-    }
-
-    private void snapback() {
-        if ((mHolding & ~HOLD_DELETE) != 0) return;
-        if (mFilmMode || !snapToNeighborImage()) {
-            mPositionController.snapback();
-        }
-    }
-
-    private boolean snapToNeighborImage() {
-        Rect r = mPositionController.getPosition(0);
-        int viewW = getWidth();
-        // Setting the move threshold proportional to the width of the view
-        int moveThreshold = viewW / 5 ;
-        int threshold = moveThreshold + gapToSide(r.width(), viewW);
-
-        // If we have moved the picture a lot, switching.
-        if (viewW - r.right > threshold) {
-            return slideToNextPicture();
-        } else if (r.left > threshold) {
-            return slideToPrevPicture();
-        }
-
-        return false;
-    }
-
-    private boolean slideToNextPicture() {
-        if (mNextBound <= 0) return false;
-        switchToNextImage();
-        mPositionController.startHorizontalSlide();
-        return true;
-    }
-
-    private boolean slideToPrevPicture() {
-        if (mPrevBound >= 0) return false;
-        switchToPrevImage();
-        mPositionController.startHorizontalSlide();
-        return true;
-    }
-
-    private static int gapToSide(int imageWidth, int viewWidth) {
-        return Math.max(0, (viewWidth - imageWidth) / 2);
-    }
-
-    ////////////////////////////////////////////////////////////////////////////
-    //  Focus switching
-    ////////////////////////////////////////////////////////////////////////////
-
-    public void switchToImage(int index) {
-        mModel.moveTo(index);
-    }
-
-    private void switchToNextImage() {
-        mModel.moveTo(mModel.getCurrentIndex() + 1);
-    }
-
-    private void switchToPrevImage() {
-        mModel.moveTo(mModel.getCurrentIndex() - 1);
-    }
-
-    private void switchToFirstImage() {
-        mModel.moveTo(0);
-    }
-
-    ////////////////////////////////////////////////////////////////////////////
-    //  Opening Animation
-    ////////////////////////////////////////////////////////////////////////////
-
-    public void setOpenAnimationRect(Rect rect) {
-        mPositionController.setOpenAnimationRect(rect);
-    }
-
-    ////////////////////////////////////////////////////////////////////////////
-    //  Capture Animation
-    ////////////////////////////////////////////////////////////////////////////
-
-    public boolean switchWithCaptureAnimation(int offset) {
-        GLRoot root = getGLRoot();
-        if(root == null) return false;
-        root.lockRenderThread();
-        try {
-            return switchWithCaptureAnimationLocked(offset);
-        } finally {
-            root.unlockRenderThread();
-        }
-    }
-
-    private boolean switchWithCaptureAnimationLocked(int offset) {
-        if (mHolding != 0) return true;
-        if (offset == 1) {
-            if (mNextBound <= 0) return false;
-            // Temporary disable action bar until the capture animation is done.
-            if (!mFilmMode) mListener.onActionBarAllowed(false);
-            switchToNextImage();
-            mPositionController.startCaptureAnimationSlide(-1);
-        } else if (offset == -1) {
-            if (mPrevBound >= 0) return false;
-            if (mFilmMode) setFilmMode(false);
-
-            // If we are too far away from the first image (so that we don't
-            // have all the ScreenNails in-between), we go directly without
-            // animation.
-            if (mModel.getCurrentIndex() > SCREEN_NAIL_MAX) {
-                switchToFirstImage();
-                mPositionController.skipToFinalPosition();
-                return true;
-            }
-
-            switchToFirstImage();
-            mPositionController.startCaptureAnimationSlide(1);
-        } else {
-            return false;
-        }
-        mHolding |= HOLD_CAPTURE_ANIMATION;
-        Message m = mHandler.obtainMessage(MSG_CAPTURE_ANIMATION_DONE, offset, 0);
-        mHandler.sendMessageDelayed(m, PositionController.CAPTURE_ANIMATION_TIME);
-        return true;
-    }
-
-    private void captureAnimationDone(int offset) {
-        mHolding &= ~HOLD_CAPTURE_ANIMATION;
-        if (offset == 1 && !mFilmMode) {
-            // Now the capture animation is done, enable the action bar.
-            mListener.onActionBarAllowed(true);
-            mListener.onActionBarWanted();
-        }
-        snapback();
-    }
-
-    ////////////////////////////////////////////////////////////////////////////
-    //  Card deck effect calculation
-    ////////////////////////////////////////////////////////////////////////////
-
-    // Returns the scrolling progress value for an object moving out of a
-    // view. The progress value measures how much the object has moving out of
-    // the view. The object currently displays in [left, right), and the view is
-    // at [0, viewWidth].
-    //
-    // The returned value is negative when the object is moving right, and
-    // positive when the object is moving left. The value goes to -1 or 1 when
-    // the object just moves out of the view completely. The value is 0 if the
-    // object currently fills the view.
-    private static float calculateMoveOutProgress(int left, int right,
-            int viewWidth) {
-        // w = object width
-        // viewWidth = view width
-        int w = right - left;
-
-        // If the object width is smaller than the view width,
-        //      |....view....|
-        //                   |<-->|      progress = -1 when left = viewWidth
-        //          |<-->|               progress = 0 when left = viewWidth / 2 - w / 2
-        // |<-->|                        progress = 1 when left = -w
-        if (w < viewWidth) {
-            int zx = viewWidth / 2 - w / 2;
-            if (left > zx) {
-                return -(left - zx) / (float) (viewWidth - zx);  // progress = (0, -1]
-            } else {
-                return (left - zx) / (float) (-w - zx);  // progress = [0, 1]
-            }
-        }
-
-        // If the object width is larger than the view width,
-        //             |..view..|
-        //                      |<--------->| progress = -1 when left = viewWidth
-        //             |<--------->|          progress = 0 between left = 0
-        //          |<--------->|                          and right = viewWidth
-        // |<--------->|                      progress = 1 when right = 0
-        if (left > 0) {
-            return -left / (float) viewWidth;
-        }
-
-        if (right < viewWidth) {
-            return (viewWidth - right) / (float) viewWidth;
-        }
-
-        return 0;
-    }
-
-    // Maps a scrolling progress value to the alpha factor in the fading
-    // animation.
-    private float getScrollAlpha(float scrollProgress) {
-        return scrollProgress < 0 ? mAlphaInterpolator.getInterpolation(
-                     1 - Math.abs(scrollProgress)) : 1.0f;
-    }
-
-    // Maps a scrolling progress value to the scaling factor in the fading
-    // animation.
-    private float getScrollScale(float scrollProgress) {
-        float interpolatedProgress = mScaleInterpolator.getInterpolation(
-                Math.abs(scrollProgress));
-        float scale = (1 - interpolatedProgress) +
-                interpolatedProgress * TRANSITION_SCALE_FACTOR;
-        return scale;
-    }
-
-
-    // This interpolator emulates the rate at which the perceived scale of an
-    // object changes as its distance from a camera increases. When this
-    // interpolator is applied to a scale animation on a view, it evokes the
-    // sense that the object is shrinking due to moving away from the camera.
-    private static class ZInterpolator {
-        private float focalLength;
-
-        public ZInterpolator(float foc) {
-            focalLength = foc;
-        }
-
-        public float getInterpolation(float input) {
-            return (1.0f - focalLength / (focalLength + input)) /
-                (1.0f - focalLength / (focalLength + 1.0f));
-        }
-    }
-
-    // Returns an interpolated value for the page/film transition.
-    // When ratio = 0, the result is from.
-    // When ratio = 1, the result is to.
-    private static float interpolate(float ratio, float from, float to) {
-        return from + (to - from) * ratio * ratio;
-    }
-
-    // Returns the alpha factor in film mode if a picture is not in the center.
-    // The 0.03 lower bound is to make the item always visible a bit.
-    private float getOffsetAlpha(float offset) {
-        offset /= 0.5f;
-        float alpha = (offset > 0) ? (1 - offset) : (1 + offset);
-        return Utils.clamp(alpha, 0.03f, 1f);
-    }
-
-    ////////////////////////////////////////////////////////////////////////////
-    //  Simple public utilities
-    ////////////////////////////////////////////////////////////////////////////
-
-    public void setListener(Listener listener) {
-        mListener = listener;
-    }
-
-    public Rect getPhotoRect(int index) {
-        return mPositionController.getPosition(index);
-    }
-
-    public PhotoFallbackEffect buildFallbackEffect(GLView root, GLCanvas canvas) {
-        Rect location = new Rect();
-        Utils.assertTrue(root.getBoundsOf(this, location));
-
-        Rect fullRect = bounds();
-        PhotoFallbackEffect effect = new PhotoFallbackEffect();
-        for (int i = -SCREEN_NAIL_MAX; i <= SCREEN_NAIL_MAX; ++i) {
-            MediaItem item = mModel.getMediaItem(i);
-            if (item == null) continue;
-            ScreenNail sc = mModel.getScreenNail(i);
-            if (!(sc instanceof TiledScreenNail)
-                    || ((TiledScreenNail) sc).isShowingPlaceholder()) continue;
-
-            // Now, sc is BitmapScreenNail and is not showing placeholder
-            Rect rect = new Rect(getPhotoRect(i));
-            if (!Rect.intersects(fullRect, rect)) continue;
-            rect.offset(location.left, location.top);
-
-            int width = sc.getWidth();
-            int height = sc.getHeight();
-
-            int rotation = mModel.getImageRotation(i);
-            RawTexture texture;
-            if ((rotation % 180) == 0) {
-                texture = new RawTexture(width, height, true);
-                canvas.beginRenderTarget(texture);
-                canvas.translate(width / 2f, height / 2f);
-            } else {
-                texture = new RawTexture(height, width, true);
-                canvas.beginRenderTarget(texture);
-                canvas.translate(height / 2f, width / 2f);
-            }
-
-            canvas.rotate(rotation, 0, 0, 1);
-            canvas.translate(-width / 2f, -height / 2f);
-            sc.draw(canvas, 0, 0, width, height);
-            canvas.endRenderTarget();
-            effect.addEntry(item.getPath(), rect, texture);
-        }
-        return effect;
-    }
-}
diff --git a/src/com/android/gallery3d/ui/PopupList.java b/src/com/android/gallery3d/ui/PopupList.java
deleted file mode 100644
index 248f50b..0000000
--- a/src/com/android/gallery3d/ui/PopupList.java
+++ /dev/null
@@ -1,206 +0,0 @@
-/*
- * 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.gallery3d.ui;
-
-import android.content.Context;
-import android.graphics.Rect;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.View.MeasureSpec;
-import android.view.ViewGroup;
-import android.view.ViewTreeObserver;
-import android.view.ViewTreeObserver.OnGlobalLayoutListener;
-import android.widget.AdapterView;
-import android.widget.AdapterView.OnItemClickListener;
-import android.widget.BaseAdapter;
-import android.widget.ListView;
-import android.widget.PopupWindow;
-import android.widget.TextView;
-
-import com.android.gallery3d.R;
-
-import java.util.ArrayList;
-
-public class PopupList {
-
-    public static interface OnPopupItemClickListener {
-        public boolean onPopupItemClick(int itemId);
-    }
-
-    public static class Item {
-        public final int id;
-        public String title;
-
-        public Item(int id, String title) {
-            this.id = id;
-            this.title = title;
-        }
-
-        public void setTitle(String title) {
-            this.title = title;
-        }
-    }
-
-    private final Context mContext;
-    private final View mAnchorView;
-    private final ArrayList<Item> mItems = new ArrayList<Item>();
-    private PopupWindow mPopupWindow;
-    private ListView mContentList;
-    private OnPopupItemClickListener mOnPopupItemClickListener;
-    private int mPopupOffsetX;
-    private int mPopupOffsetY;
-    private int mPopupWidth;
-    private int mPopupHeight;
-
-    public PopupList(Context context, View anchorView) {
-        mContext = context;
-        mAnchorView = anchorView;
-    }
-
-    public void setOnPopupItemClickListener(OnPopupItemClickListener listener) {
-        mOnPopupItemClickListener = listener;
-    }
-
-    public void addItem(int id, String title) {
-        mItems.add(new Item(id, title));
-    }
-
-    public void clearItems() {
-        mItems.clear();
-    }
-
-    private final PopupWindow.OnDismissListener mOnDismissListener =
-            new PopupWindow.OnDismissListener() {
-        @SuppressWarnings("deprecation")
-        @Override
-        public void onDismiss() {
-            if (mPopupWindow == null) return;
-            mPopupWindow = null;
-            ViewTreeObserver observer = mAnchorView.getViewTreeObserver();
-            if (observer.isAlive()) {
-                // We used the deprecated function for backward compatibility
-                // The new "removeOnGlobalLayoutListener" is introduced in API level 16
-                observer.removeGlobalOnLayoutListener(mOnGLobalLayoutListener);
-            }
-        }
-    };
-
-    private final OnItemClickListener mOnItemClickListener =
-            new OnItemClickListener() {
-        @Override
-        public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
-            if (mPopupWindow == null) return;
-            mPopupWindow.dismiss();
-            if (mOnPopupItemClickListener != null) {
-                mOnPopupItemClickListener.onPopupItemClick((int) id);
-            }
-        }
-    };
-
-    private final OnGlobalLayoutListener mOnGLobalLayoutListener =
-            new OnGlobalLayoutListener() {
-        @Override
-        public void onGlobalLayout() {
-            if (mPopupWindow == null) return;
-            updatePopupLayoutParams();
-            // Need to update the position of the popup window
-            mPopupWindow.update(mAnchorView,
-                    mPopupOffsetX, mPopupOffsetY, mPopupWidth, mPopupHeight);
-        }
-    };
-
-    public void show() {
-        if (mPopupWindow != null) return;
-        mAnchorView.getViewTreeObserver()
-                .addOnGlobalLayoutListener(mOnGLobalLayoutListener);
-        mPopupWindow = createPopupWindow();
-        updatePopupLayoutParams();
-        mPopupWindow.setWidth(mPopupWidth);
-        mPopupWindow.setHeight(mPopupHeight);
-        mPopupWindow.showAsDropDown(mAnchorView, mPopupOffsetX, mPopupOffsetY);
-    }
-
-    private void updatePopupLayoutParams() {
-        ListView content = mContentList;
-        PopupWindow popup = mPopupWindow;
-
-        Rect p = new Rect();
-        popup.getBackground().getPadding(p);
-
-        int maxHeight = mPopupWindow.getMaxAvailableHeight(mAnchorView) - p.top - p.bottom;
-        mContentList.measure(
-                MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED),
-                MeasureSpec.makeMeasureSpec(maxHeight, MeasureSpec.AT_MOST));
-        mPopupWidth = content.getMeasuredWidth() + p.top + p.bottom;
-        mPopupHeight = Math.min(maxHeight, content.getMeasuredHeight() + p.left + p.right);
-        mPopupOffsetX = -p.left;
-        mPopupOffsetY = -p.top;
-    }
-
-    private PopupWindow createPopupWindow() {
-        PopupWindow popup = new PopupWindow(mContext);
-        popup.setOnDismissListener(mOnDismissListener);
-
-        popup.setBackgroundDrawable(mContext.getResources().getDrawable(
-                R.drawable.menu_dropdown_panel_holo_dark));
-
-        mContentList = new ListView(mContext, null,
-                android.R.attr.dropDownListViewStyle);
-        mContentList.setAdapter(new ItemDataAdapter());
-        mContentList.setOnItemClickListener(mOnItemClickListener);
-        popup.setContentView(mContentList);
-        popup.setFocusable(true);
-        popup.setOutsideTouchable(true);
-
-        return popup;
-    }
-
-    public Item findItem(int id) {
-        for (Item item : mItems) {
-            if (item.id == id) return item;
-        }
-        return null;
-    }
-
-    private class ItemDataAdapter extends BaseAdapter {
-        @Override
-        public int getCount() {
-            return mItems.size();
-        }
-
-        @Override
-        public Object getItem(int position) {
-            return mItems.get(position);
-        }
-
-        @Override
-        public long getItemId(int position) {
-            return mItems.get(position).id;
-        }
-
-        @Override
-        public View getView(int position, View convertView, ViewGroup parent) {
-            if (convertView == null) {
-                convertView = LayoutInflater.from(mContext)
-                        .inflate(R.layout.popup_list_item, null);
-            }
-            TextView text = (TextView) convertView.findViewById(android.R.id.text1);
-            text.setText(mItems.get(position).title);
-            return convertView;
-        }
-    }
-}
diff --git a/src/com/android/gallery3d/ui/PositionController.java b/src/com/android/gallery3d/ui/PositionController.java
deleted file mode 100644
index 6a4bcea..0000000
--- a/src/com/android/gallery3d/ui/PositionController.java
+++ /dev/null
@@ -1,1821 +0,0 @@
-/*
- * Copyright (C) 2011 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.gallery3d.ui;
-
-import android.content.Context;
-import android.graphics.Rect;
-import android.util.Log;
-import android.widget.Scroller;
-
-import com.android.gallery3d.app.PhotoPage;
-import com.android.gallery3d.common.Utils;
-import com.android.gallery3d.ui.PhotoView.Size;
-import com.android.gallery3d.util.GalleryUtils;
-import com.android.gallery3d.util.RangeArray;
-import com.android.gallery3d.util.RangeIntArray;
-
-class PositionController {
-    private static final String TAG = "PositionController";
-
-    public static final int IMAGE_AT_LEFT_EDGE = 1;
-    public static final int IMAGE_AT_RIGHT_EDGE = 2;
-    public static final int IMAGE_AT_TOP_EDGE = 4;
-    public static final int IMAGE_AT_BOTTOM_EDGE = 8;
-
-    public static final int CAPTURE_ANIMATION_TIME = 700;
-    public static final int SNAPBACK_ANIMATION_TIME = 600;
-
-    // Special values for animation time.
-    private static final long NO_ANIMATION = -1;
-    private static final long LAST_ANIMATION = -2;
-
-    private static final int ANIM_KIND_NONE = -1;
-    private static final int ANIM_KIND_SCROLL = 0;
-    private static final int ANIM_KIND_SCALE = 1;
-    private static final int ANIM_KIND_SNAPBACK = 2;
-    private static final int ANIM_KIND_SLIDE = 3;
-    private static final int ANIM_KIND_ZOOM = 4;
-    private static final int ANIM_KIND_OPENING = 5;
-    private static final int ANIM_KIND_FLING = 6;
-    private static final int ANIM_KIND_FLING_X = 7;
-    private static final int ANIM_KIND_DELETE = 8;
-    private static final int ANIM_KIND_CAPTURE = 9;
-
-    // Animation time in milliseconds. The order must match ANIM_KIND_* above.
-    //
-    // The values for ANIM_KIND_FLING_X does't matter because we use
-    // mFilmScroller.isFinished() to decide when to stop. We set it to 0 so it's
-    // faster for Animatable.advanceAnimation() to calculate the progress
-    // (always 1).
-    private static final int ANIM_TIME[] = {
-        0,    // ANIM_KIND_SCROLL
-        0,    // ANIM_KIND_SCALE
-        SNAPBACK_ANIMATION_TIME,  // ANIM_KIND_SNAPBACK
-        400,  // ANIM_KIND_SLIDE
-        300,  // ANIM_KIND_ZOOM
-        300,  // ANIM_KIND_OPENING
-        0,    // ANIM_KIND_FLING (the duration is calculated dynamically)
-        0,    // ANIM_KIND_FLING_X (see the comment above)
-        0,    // ANIM_KIND_DELETE (the duration is calculated dynamically)
-        CAPTURE_ANIMATION_TIME,  // ANIM_KIND_CAPTURE
-    };
-
-    // We try to scale up the image to fill the screen. But in order not to
-    // scale too much for small icons, we limit the max up-scaling factor here.
-    private static final float SCALE_LIMIT = 4;
-
-    // For user's gestures, we give a temporary extra scaling range which goes
-    // above or below the usual scaling limits.
-    private static final float SCALE_MIN_EXTRA = 0.7f;
-    private static final float SCALE_MAX_EXTRA = 1.4f;
-
-    // Setting this true makes the extra scaling range permanent (until this is
-    // set to false again).
-    private boolean mExtraScalingRange = false;
-
-    // Film Mode v.s. Page Mode: in film mode we show smaller pictures.
-    private boolean mFilmMode = false;
-
-    // These are the limits for width / height of the picture in film mode.
-    private static final float FILM_MODE_PORTRAIT_HEIGHT = 0.48f;
-    private static final float FILM_MODE_PORTRAIT_WIDTH = 0.7f;
-    private static final float FILM_MODE_LANDSCAPE_HEIGHT = 0.7f;
-    private static final float FILM_MODE_LANDSCAPE_WIDTH = 0.7f;
-
-    // In addition to the focused box (index == 0). We also keep information
-    // about this many boxes on each side.
-    private static final int BOX_MAX = PhotoView.SCREEN_NAIL_MAX;
-    private static final int[] CENTER_OUT_INDEX = new int[2 * BOX_MAX + 1];
-
-    private static final int IMAGE_GAP = GalleryUtils.dpToPixel(16);
-    private static final int HORIZONTAL_SLACK = GalleryUtils.dpToPixel(12);
-
-    // These are constants for the delete gesture.
-    private static final int DEFAULT_DELETE_ANIMATION_DURATION = 200; // ms
-    private static final int MAX_DELETE_ANIMATION_DURATION = 400; // ms
-
-    private Listener mListener;
-    private volatile Rect mOpenAnimationRect;
-
-    // Use a large enough value, so we won't see the gray shadow in the beginning.
-    private int mViewW = 1200;
-    private int mViewH = 1200;
-
-    // A scaling gesture is in progress.
-    private boolean mInScale;
-    // The focus point of the scaling gesture, relative to the center of the
-    // picture in bitmap pixels.
-    private float mFocusX, mFocusY;
-
-    // whether there is a previous/next picture.
-    private boolean mHasPrev, mHasNext;
-
-    // This is used by the fling animation (page mode).
-    private FlingScroller mPageScroller;
-
-    // This is used by the fling animation (film mode).
-    private Scroller mFilmScroller;
-
-    // The bound of the stable region that the focused box can stay, see the
-    // comments above calculateStableBound() for details.
-    private int mBoundLeft, mBoundRight, mBoundTop, mBoundBottom;
-
-    // Constrained frame is a rectangle that the focused box should fit into if
-    // it is constrained. It has two effects:
-    //
-    // (1) In page mode, if the focused box is constrained, scaling for the
-    // focused box is adjusted to fit into the constrained frame, instead of the
-    // whole view.
-    //
-    // (2) In page mode, if the focused box is constrained, the mPlatform's
-    // default center (mDefaultX/Y) is moved to the center of the constrained
-    // frame, instead of the view center.
-    //
-    private Rect mConstrainedFrame = new Rect();
-
-    // Whether the focused box is constrained.
-    //
-    // Our current program's first call to moveBox() sets constrained = true, so
-    // we set the initial value of this variable to true, and we will not see
-    // see unwanted transition animation.
-    private boolean mConstrained = true;
-
-    //
-    //  ___________________________________________________________
-    // |   _____       _____       _____       _____       _____   |
-    // |  |     |     |     |     |     |     |     |     |     |  |
-    // |  | Box |     | Box |     | Box*|     | Box |     | Box |  |
-    // |  |_____|.....|_____|.....|_____|.....|_____|.....|_____|  |
-    // |          Gap         Gap         Gap         Gap          |
-    // |___________________________________________________________|
-    //
-    //                       <--  Platform  -->
-    //
-    // The focused box (Box*) centers at mPlatform's (mCurrentX, mCurrentY)
-
-    private Platform mPlatform = new Platform();
-    private RangeArray<Box> mBoxes = new RangeArray<Box>(-BOX_MAX, BOX_MAX);
-    // The gap at the right of a Box i is at index i. The gap at the left of a
-    // Box i is at index i - 1.
-    private RangeArray<Gap> mGaps = new RangeArray<Gap>(-BOX_MAX, BOX_MAX - 1);
-    private FilmRatio mFilmRatio = new FilmRatio();
-
-    // These are only used during moveBox().
-    private RangeArray<Box> mTempBoxes = new RangeArray<Box>(-BOX_MAX, BOX_MAX);
-    private RangeArray<Gap> mTempGaps =
-        new RangeArray<Gap>(-BOX_MAX, BOX_MAX - 1);
-
-    // The output of the PositionController. Available through getPosition().
-    private RangeArray<Rect> mRects = new RangeArray<Rect>(-BOX_MAX, BOX_MAX);
-
-    // The direction of a new picture should appear. New pictures pop from top
-    // if this value is true, or from bottom if this value is false.
-    boolean mPopFromTop;
-
-    public interface Listener {
-        void invalidate();
-        boolean isHoldingDown();
-        boolean isHoldingDelete();
-
-        // EdgeView
-        void onPull(int offset, int direction);
-        void onRelease();
-        void onAbsorb(int velocity, int direction);
-    }
-
-    static {
-        // Initialize the CENTER_OUT_INDEX array.
-        // The array maps 0, 1, 2, 3, 4, ..., 2 * BOX_MAX
-        // to 0, 1, -1, 2, -2, ..., BOX_MAX, -BOX_MAX
-        for (int i = 0; i < CENTER_OUT_INDEX.length; i++) {
-            int j = (i + 1) / 2;
-            if ((i & 1) == 0) j = -j;
-            CENTER_OUT_INDEX[i] = j;
-        }
-    }
-
-    public PositionController(Context context, Listener listener) {
-        mListener = listener;
-        mPageScroller = new FlingScroller();
-        mFilmScroller = new Scroller(context, null, false);
-
-        // Initialize the areas.
-        initPlatform();
-        for (int i = -BOX_MAX; i <= BOX_MAX; i++) {
-            mBoxes.put(i, new Box());
-            initBox(i);
-            mRects.put(i, new Rect());
-        }
-        for (int i = -BOX_MAX; i < BOX_MAX; i++) {
-            mGaps.put(i, new Gap());
-            initGap(i);
-        }
-    }
-
-    public void setOpenAnimationRect(Rect r) {
-        mOpenAnimationRect = r;
-    }
-
-    public void setViewSize(int viewW, int viewH) {
-        if (viewW == mViewW && viewH == mViewH) return;
-
-        boolean wasMinimal = isAtMinimalScale();
-
-        mViewW = viewW;
-        mViewH = viewH;
-        initPlatform();
-
-        for (int i = -BOX_MAX; i <= BOX_MAX; i++) {
-            setBoxSize(i, viewW, viewH, true);
-        }
-
-        updateScaleAndGapLimit();
-
-        // If the focused box was at minimal scale, we try to make it the
-        // minimal scale under the new view size.
-        if (wasMinimal) {
-            Box b = mBoxes.get(0);
-            b.mCurrentScale = b.mScaleMin;
-        }
-
-        // If we have the opening animation, do it. Otherwise go directly to the
-        // right position.
-        if (!startOpeningAnimationIfNeeded()) {
-            skipToFinalPosition();
-        }
-    }
-
-    public void setConstrainedFrame(Rect cFrame) {
-        if (mConstrainedFrame.equals(cFrame)) return;
-        mConstrainedFrame.set(cFrame);
-        mPlatform.updateDefaultXY();
-        updateScaleAndGapLimit();
-        snapAndRedraw();
-    }
-
-    public void forceImageSize(int index, Size s) {
-        if (s.width == 0 || s.height == 0) return;
-        Box b = mBoxes.get(index);
-        b.mImageW = s.width;
-        b.mImageH = s.height;
-        return;
-    }
-
-    public void setImageSize(int index, Size s, Rect cFrame) {
-        if (s.width == 0 || s.height == 0) return;
-
-        boolean needUpdate = false;
-        if (cFrame != null && !mConstrainedFrame.equals(cFrame)) {
-            mConstrainedFrame.set(cFrame);
-            mPlatform.updateDefaultXY();
-            needUpdate = true;
-        }
-        needUpdate |= setBoxSize(index, s.width, s.height, false);
-
-        if (!needUpdate) return;
-        updateScaleAndGapLimit();
-        snapAndRedraw();
-    }
-
-    // Returns false if the box size doesn't change.
-    private boolean setBoxSize(int i, int width, int height, boolean isViewSize) {
-        Box b = mBoxes.get(i);
-        boolean wasViewSize = b.mUseViewSize;
-
-        // If we already have an image size, we don't want to use the view size.
-        if (!wasViewSize && isViewSize) return false;
-
-        b.mUseViewSize = isViewSize;
-
-        if (width == b.mImageW && height == b.mImageH) {
-            return false;
-        }
-
-        // The ratio of the old size and the new size.
-        //
-        // If the aspect ratio changes, we don't know if it is because one side
-        // grows or the other side shrinks. Currently we just assume the view
-        // angle of the longer side doesn't change (so the aspect ratio change
-        // is because the view angle of the shorter side changes). This matches
-        // what camera preview does.
-        float ratio = (width > height)
-                ? (float) b.mImageW / width
-                : (float) b.mImageH / height;
-
-        b.mImageW = width;
-        b.mImageH = height;
-
-        // If this is the first time we receive an image size or we are in fullscreen,
-        // we change the scale directly. Otherwise adjust the scales by a ratio,
-        // and snapback will animate the scale into the min/max bounds if necessary.
-        if ((wasViewSize && !isViewSize) || !mFilmMode) {
-            b.mCurrentScale = getMinimalScale(b);
-            b.mAnimationStartTime = NO_ANIMATION;
-        } else {
-            b.mCurrentScale *= ratio;
-            b.mFromScale *= ratio;
-            b.mToScale *= ratio;
-        }
-
-        if (i == 0) {
-            mFocusX /= ratio;
-            mFocusY /= ratio;
-        }
-
-        return true;
-    }
-
-    private boolean startOpeningAnimationIfNeeded() {
-        if (mOpenAnimationRect == null) return false;
-        Box b = mBoxes.get(0);
-        if (b.mUseViewSize) return false;
-
-        // Start animation from the saved rectangle if we have one.
-        Rect r = mOpenAnimationRect;
-        mOpenAnimationRect = null;
-
-        mPlatform.mCurrentX = r.centerX() - mViewW / 2;
-        b.mCurrentY = r.centerY() - mViewH / 2;
-        b.mCurrentScale = Math.max(r.width() / (float) b.mImageW,
-                r.height() / (float) b.mImageH);
-        startAnimation(mPlatform.mDefaultX, 0, b.mScaleMin,
-                ANIM_KIND_OPENING);
-
-        // Animate from large gaps for neighbor boxes to avoid them
-        // shown on the screen during opening animation.
-        for (int i = -1; i < 1; i++) {
-            Gap g = mGaps.get(i);
-            g.mCurrentGap = mViewW;
-            g.doAnimation(g.mDefaultSize, ANIM_KIND_OPENING);
-        }
-
-        return true;
-    }
-
-    public void setFilmMode(boolean enabled) {
-        if (enabled == mFilmMode) return;
-        mFilmMode = enabled;
-
-        mPlatform.updateDefaultXY();
-        updateScaleAndGapLimit();
-        stopAnimation();
-        snapAndRedraw();
-    }
-
-    public void setExtraScalingRange(boolean enabled) {
-        if (mExtraScalingRange == enabled) return;
-        mExtraScalingRange = enabled;
-        if (!enabled) {
-            snapAndRedraw();
-        }
-    }
-
-    // This should be called whenever the scale range of boxes or the default
-    // gap size may change. Currently this can happen due to change of view
-    // size, image size, mFilmMode, mConstrained, and mConstrainedFrame.
-    private void updateScaleAndGapLimit() {
-        for (int i = -BOX_MAX; i <= BOX_MAX; i++) {
-            Box b = mBoxes.get(i);
-            b.mScaleMin = getMinimalScale(b);
-            b.mScaleMax = getMaximalScale(b);
-        }
-
-        for (int i = -BOX_MAX; i < BOX_MAX; i++) {
-            Gap g = mGaps.get(i);
-            g.mDefaultSize = getDefaultGapSize(i);
-        }
-    }
-
-    // Returns the default gap size according the the size of the boxes around
-    // the gap and the current mode.
-    private int getDefaultGapSize(int i) {
-        if (mFilmMode) return IMAGE_GAP;
-        Box a = mBoxes.get(i);
-        Box b = mBoxes.get(i + 1);
-        return IMAGE_GAP + Math.max(gapToSide(a), gapToSide(b));
-    }
-
-    // Here is how we layout the boxes in the page mode.
-    //
-    //   previous             current             next
-    //  ___________       ________________     __________
-    // |  _______  |     |   __________   |   |  ______  |
-    // | |       | |     |  |   right->|  |   | |      | |
-    // | |       |<-------->|<--left   |  |   | |      | |
-    // | |_______| |  |  |  |__________|  |   | |______| |
-    // |___________|  |  |________________|   |__________|
-    //                |  <--> gapToSide()
-    //                |
-    // IMAGE_GAP + MAX(gapToSide(previous), gapToSide(current))
-    private int gapToSide(Box b) {
-        return (int) ((mViewW - getMinimalScale(b) * b.mImageW) / 2 + 0.5f);
-    }
-
-    // Stop all animations at where they are now.
-    public void stopAnimation() {
-        mPlatform.mAnimationStartTime = NO_ANIMATION;
-        for (int i = -BOX_MAX; i <= BOX_MAX; i++) {
-            mBoxes.get(i).mAnimationStartTime = NO_ANIMATION;
-        }
-        for (int i = -BOX_MAX; i < BOX_MAX; i++) {
-            mGaps.get(i).mAnimationStartTime = NO_ANIMATION;
-        }
-    }
-
-    public void skipAnimation() {
-        if (mPlatform.mAnimationStartTime != NO_ANIMATION) {
-            mPlatform.mCurrentX = mPlatform.mToX;
-            mPlatform.mCurrentY = mPlatform.mToY;
-            mPlatform.mAnimationStartTime = NO_ANIMATION;
-        }
-        for (int i = -BOX_MAX; i <= BOX_MAX; i++) {
-            Box b = mBoxes.get(i);
-            if (b.mAnimationStartTime == NO_ANIMATION) continue;
-            b.mCurrentY = b.mToY;
-            b.mCurrentScale = b.mToScale;
-            b.mAnimationStartTime = NO_ANIMATION;
-        }
-        for (int i = -BOX_MAX; i < BOX_MAX; i++) {
-            Gap g = mGaps.get(i);
-            if (g.mAnimationStartTime == NO_ANIMATION) continue;
-            g.mCurrentGap = g.mToGap;
-            g.mAnimationStartTime = NO_ANIMATION;
-        }
-        redraw();
-    }
-
-    public void snapback() {
-        snapAndRedraw();
-    }
-
-    public void skipToFinalPosition() {
-        stopAnimation();
-        snapAndRedraw();
-        skipAnimation();
-    }
-
-    ////////////////////////////////////////////////////////////////////////////
-    //  Start an animations for the focused box
-    ////////////////////////////////////////////////////////////////////////////
-
-    public void zoomIn(float tapX, float tapY, float targetScale) {
-        tapX -= mViewW / 2;
-        tapY -= mViewH / 2;
-        Box b = mBoxes.get(0);
-
-        // Convert the tap position to distance to center in bitmap coordinates
-        float tempX = (tapX - mPlatform.mCurrentX) / b.mCurrentScale;
-        float tempY = (tapY - b.mCurrentY) / b.mCurrentScale;
-
-        int x = (int) (-tempX * targetScale + 0.5f);
-        int y = (int) (-tempY * targetScale + 0.5f);
-
-        calculateStableBound(targetScale);
-        int targetX = Utils.clamp(x, mBoundLeft, mBoundRight);
-        int targetY = Utils.clamp(y, mBoundTop, mBoundBottom);
-        targetScale = Utils.clamp(targetScale, b.mScaleMin, b.mScaleMax);
-
-        startAnimation(targetX, targetY, targetScale, ANIM_KIND_ZOOM);
-    }
-
-    public void resetToFullView() {
-        Box b = mBoxes.get(0);
-        startAnimation(mPlatform.mDefaultX, 0, b.mScaleMin, ANIM_KIND_ZOOM);
-    }
-
-    public void beginScale(float focusX, float focusY) {
-        focusX -= mViewW / 2;
-        focusY -= mViewH / 2;
-        Box b = mBoxes.get(0);
-        Platform p = mPlatform;
-        mInScale = true;
-        mFocusX = (int) ((focusX - p.mCurrentX) / b.mCurrentScale + 0.5f);
-        mFocusY = (int) ((focusY - b.mCurrentY) / b.mCurrentScale + 0.5f);
-    }
-
-    // Scales the image by the given factor.
-    // Returns an out-of-range indicator:
-    //   1 if the intended scale is too large for the stable range.
-    //   0 if the intended scale is in the stable range.
-    //  -1 if the intended scale is too small for the stable range.
-    public int scaleBy(float s, float focusX, float focusY) {
-        focusX -= mViewW / 2;
-        focusY -= mViewH / 2;
-        Box b = mBoxes.get(0);
-        Platform p = mPlatform;
-
-        // We want to keep the focus point (on the bitmap) the same as when we
-        // begin the scale gesture, that is,
-        //
-        // (focusX' - currentX') / scale' = (focusX - currentX) / scale
-        //
-        s = b.clampScale(s * getTargetScale(b));
-        int x = mFilmMode ? p.mCurrentX : (int) (focusX - s * mFocusX + 0.5f);
-        int y = mFilmMode ? b.mCurrentY : (int) (focusY - s * mFocusY + 0.5f);
-        startAnimation(x, y, s, ANIM_KIND_SCALE);
-        if (s < b.mScaleMin) return -1;
-        if (s > b.mScaleMax) return 1;
-        return 0;
-    }
-
-    public void endScale() {
-        mInScale = false;
-        snapAndRedraw();
-    }
-
-    // Slide the focused box to the center of the view.
-    public void startHorizontalSlide() {
-        Box b = mBoxes.get(0);
-        startAnimation(mPlatform.mDefaultX, 0, b.mScaleMin, ANIM_KIND_SLIDE);
-    }
-
-    // Slide the focused box to the center of the view with the capture
-    // animation. In addition to the sliding, the animation will also scale the
-    // the focused box, the specified neighbor box, and the gap between the
-    // two. The specified offset should be 1 or -1.
-    public void startCaptureAnimationSlide(int offset) {
-        Box b = mBoxes.get(0);
-        Box n = mBoxes.get(offset);  // the neighbor box
-        Gap g = mGaps.get(offset);  // the gap between the two boxes
-
-        mPlatform.doAnimation(mPlatform.mDefaultX, mPlatform.mDefaultY,
-                ANIM_KIND_CAPTURE);
-        b.doAnimation(0, b.mScaleMin, ANIM_KIND_CAPTURE);
-        n.doAnimation(0, n.mScaleMin, ANIM_KIND_CAPTURE);
-        g.doAnimation(g.mDefaultSize, ANIM_KIND_CAPTURE);
-        redraw();
-    }
-
-    // Only allow scrolling when we are not currently in an animation or we
-    // are in some animation with can be interrupted.
-    private boolean canScroll() {
-        Box b = mBoxes.get(0);
-        if (b.mAnimationStartTime == NO_ANIMATION) return true;
-        switch (b.mAnimationKind) {
-            case ANIM_KIND_SCROLL:
-            case ANIM_KIND_FLING:
-            case ANIM_KIND_FLING_X:
-                return true;
-        }
-        return false;
-    }
-
-    public void scrollPage(int dx, int dy) {
-        if (!canScroll()) return;
-
-        Box b = mBoxes.get(0);
-        Platform p = mPlatform;
-
-        calculateStableBound(b.mCurrentScale);
-
-        int x = p.mCurrentX + dx;
-        int y = b.mCurrentY + dy;
-
-        // Vertical direction: If we have space to move in the vertical
-        // direction, we show the edge effect when scrolling reaches the edge.
-        if (mBoundTop != mBoundBottom) {
-            if (y < mBoundTop) {
-                mListener.onPull(mBoundTop - y, EdgeView.BOTTOM);
-            } else if (y > mBoundBottom) {
-                mListener.onPull(y - mBoundBottom, EdgeView.TOP);
-            }
-        }
-
-        y = Utils.clamp(y, mBoundTop, mBoundBottom);
-
-        // Horizontal direction: we show the edge effect when the scrolling
-        // tries to go left of the first image or go right of the last image.
-        if (!mHasPrev && x > mBoundRight) {
-            int pixels = x - mBoundRight;
-            mListener.onPull(pixels, EdgeView.LEFT);
-            x = mBoundRight;
-        } else if (!mHasNext && x < mBoundLeft) {
-            int pixels = mBoundLeft - x;
-            mListener.onPull(pixels, EdgeView.RIGHT);
-            x = mBoundLeft;
-        }
-
-        startAnimation(x, y, b.mCurrentScale, ANIM_KIND_SCROLL);
-    }
-
-    public void scrollFilmX(int dx) {
-        if (!canScroll()) return;
-
-        Box b = mBoxes.get(0);
-        Platform p = mPlatform;
-
-        // Only allow scrolling when we are not currently in an animation or we
-        // are in some animation with can be interrupted.
-        if (b.mAnimationStartTime != NO_ANIMATION) {
-            switch (b.mAnimationKind) {
-                case ANIM_KIND_SCROLL:
-                case ANIM_KIND_FLING:
-                case ANIM_KIND_FLING_X:
-                    break;
-                default:
-                    return;
-            }
-        }
-
-        int x = p.mCurrentX + dx;
-
-        // Horizontal direction: we show the edge effect when the scrolling
-        // tries to go left of the first image or go right of the last image.
-        x -= mPlatform.mDefaultX;
-        if (!mHasPrev && x > 0) {
-            mListener.onPull(x, EdgeView.LEFT);
-            x = 0;
-        } else if (!mHasNext && x < 0) {
-            mListener.onPull(-x, EdgeView.RIGHT);
-            x = 0;
-        }
-        x += mPlatform.mDefaultX;
-        startAnimation(x, b.mCurrentY, b.mCurrentScale, ANIM_KIND_SCROLL);
-    }
-
-    public void scrollFilmY(int boxIndex, int dy) {
-        if (!canScroll()) return;
-
-        Box b = mBoxes.get(boxIndex);
-        int y = b.mCurrentY + dy;
-        b.doAnimation(y, b.mCurrentScale, ANIM_KIND_SCROLL);
-        redraw();
-    }
-
-    public boolean flingPage(int velocityX, int velocityY) {
-        Box b = mBoxes.get(0);
-        Platform p = mPlatform;
-
-        // We only want to do fling when the picture is zoomed-in.
-        if (viewWiderThanScaledImage(b.mCurrentScale) &&
-            viewTallerThanScaledImage(b.mCurrentScale)) {
-            return false;
-        }
-
-        // We only allow flinging in the directions where it won't go over the
-        // picture.
-        int edges = getImageAtEdges();
-        if ((velocityX > 0 && (edges & IMAGE_AT_LEFT_EDGE) != 0) ||
-            (velocityX < 0 && (edges & IMAGE_AT_RIGHT_EDGE) != 0)) {
-            velocityX = 0;
-        }
-        if ((velocityY > 0 && (edges & IMAGE_AT_TOP_EDGE) != 0) ||
-            (velocityY < 0 && (edges & IMAGE_AT_BOTTOM_EDGE) != 0)) {
-            velocityY = 0;
-        }
-
-        if (velocityX == 0 && velocityY == 0) return false;
-
-        mPageScroller.fling(p.mCurrentX, b.mCurrentY, velocityX, velocityY,
-                mBoundLeft, mBoundRight, mBoundTop, mBoundBottom);
-        int targetX = mPageScroller.getFinalX();
-        int targetY = mPageScroller.getFinalY();
-        ANIM_TIME[ANIM_KIND_FLING] = mPageScroller.getDuration();
-        return startAnimation(targetX, targetY, b.mCurrentScale, ANIM_KIND_FLING);
-    }
-
-    public boolean flingFilmX(int velocityX) {
-        if (velocityX == 0) return false;
-
-        Box b = mBoxes.get(0);
-        Platform p = mPlatform;
-
-        // If we are already at the edge, don't start the fling.
-        int defaultX = p.mDefaultX;
-        if ((!mHasPrev && p.mCurrentX >= defaultX)
-                || (!mHasNext && p.mCurrentX <= defaultX)) {
-            return false;
-        }
-
-        mFilmScroller.fling(p.mCurrentX, 0, velocityX, 0,
-                Integer.MIN_VALUE, Integer.MAX_VALUE, 0, 0);
-        int targetX = mFilmScroller.getFinalX();
-        return startAnimation(
-                targetX, b.mCurrentY, b.mCurrentScale, ANIM_KIND_FLING_X);
-    }
-
-    // Moves the specified box out of screen. If velocityY is 0, a default
-    // velocity is used. Returns the time for the duration, or -1 if we cannot
-    // not do the animation.
-    public int flingFilmY(int boxIndex, int velocityY) {
-        Box b = mBoxes.get(boxIndex);
-
-        // Calculate targetY
-        int h = heightOf(b);
-        int targetY;
-        int FUZZY = 3;  // TODO: figure out why this is needed.
-        if (velocityY < 0 || (velocityY == 0 && b.mCurrentY <= 0)) {
-            targetY = -mViewH / 2 - (h + 1) / 2 - FUZZY;
-        } else {
-            targetY = (mViewH + 1) / 2 + h / 2 + FUZZY;
-        }
-
-        // Calculate duration
-        int duration;
-        if (velocityY != 0) {
-            duration = (int) (Math.abs(targetY - b.mCurrentY) * 1000f
-                    / Math.abs(velocityY));
-            duration = Math.min(MAX_DELETE_ANIMATION_DURATION, duration);
-        } else {
-            duration = DEFAULT_DELETE_ANIMATION_DURATION;
-        }
-
-        // Start animation
-        ANIM_TIME[ANIM_KIND_DELETE] = duration;
-        if (b.doAnimation(targetY, b.mCurrentScale, ANIM_KIND_DELETE)) {
-            redraw();
-            return duration;
-        }
-        return -1;
-    }
-
-    // Returns the index of the box which contains the given point (x, y)
-    // Returns Integer.MAX_VALUE if there is no hit. There may be more than
-    // one box contains the given point, and we want to give priority to the
-    // one closer to the focused index (0).
-    public int hitTest(int x, int y) {
-        for (int i = 0; i < 2 * BOX_MAX + 1; i++) {
-            int j = CENTER_OUT_INDEX[i];
-            Rect r = mRects.get(j);
-            if (r.contains(x, y)) {
-                return j;
-            }
-        }
-
-        return Integer.MAX_VALUE;
-    }
-
-    ////////////////////////////////////////////////////////////////////////////
-    //  Redraw
-    //
-    //  If a method changes box positions directly, redraw()
-    //  should be called.
-    //
-    //  If a method may also cause a snapback to happen, snapAndRedraw() should
-    //  be called.
-    //
-    //  If a method starts an animation to change the position of focused box,
-    //  startAnimation() should be called.
-    //
-    //  If time advances to change the box position, advanceAnimation() should
-    //  be called.
-    ////////////////////////////////////////////////////////////////////////////
-    private void redraw() {
-        layoutAndSetPosition();
-        mListener.invalidate();
-    }
-
-    private void snapAndRedraw() {
-        mPlatform.startSnapback();
-        for (int i = -BOX_MAX; i <= BOX_MAX; i++) {
-            mBoxes.get(i).startSnapback();
-        }
-        for (int i = -BOX_MAX; i < BOX_MAX; i++) {
-            mGaps.get(i).startSnapback();
-        }
-        mFilmRatio.startSnapback();
-        redraw();
-    }
-
-    private boolean startAnimation(int targetX, int targetY, float targetScale,
-            int kind) {
-        boolean changed = false;
-        changed |= mPlatform.doAnimation(targetX, mPlatform.mDefaultY, kind);
-        changed |= mBoxes.get(0).doAnimation(targetY, targetScale, kind);
-        if (changed) redraw();
-        return changed;
-    }
-
-    public void advanceAnimation() {
-        boolean changed = false;
-        changed |= mPlatform.advanceAnimation();
-        for (int i = -BOX_MAX; i <= BOX_MAX; i++) {
-            changed |= mBoxes.get(i).advanceAnimation();
-        }
-        for (int i = -BOX_MAX; i < BOX_MAX; i++) {
-            changed |= mGaps.get(i).advanceAnimation();
-        }
-        changed |= mFilmRatio.advanceAnimation();
-        if (changed) redraw();
-    }
-
-    public boolean inOpeningAnimation() {
-        return (mPlatform.mAnimationKind == ANIM_KIND_OPENING &&
-                mPlatform.mAnimationStartTime != NO_ANIMATION) ||
-               (mBoxes.get(0).mAnimationKind == ANIM_KIND_OPENING &&
-                mBoxes.get(0).mAnimationStartTime != NO_ANIMATION);
-    }
-
-    ////////////////////////////////////////////////////////////////////////////
-    //  Layout
-    ////////////////////////////////////////////////////////////////////////////
-
-    // Returns the display width of this box.
-    private int widthOf(Box b) {
-        return (int) (b.mImageW * b.mCurrentScale + 0.5f);
-    }
-
-    // Returns the display height of this box.
-    private int heightOf(Box b) {
-        return (int) (b.mImageH * b.mCurrentScale + 0.5f);
-    }
-
-    // Returns the display width of this box, using the given scale.
-    private int widthOf(Box b, float scale) {
-        return (int) (b.mImageW * scale + 0.5f);
-    }
-
-    // Returns the display height of this box, using the given scale.
-    private int heightOf(Box b, float scale) {
-        return (int) (b.mImageH * scale + 0.5f);
-    }
-
-    // Convert the information in mPlatform and mBoxes to mRects, so the user
-    // can get the position of each box by getPosition().
-    //
-    // Note we go from center-out because each box's X coordinate
-    // is relative to its anchor box (except the focused box).
-    private void layoutAndSetPosition() {
-        for (int i = 0; i < 2 * BOX_MAX + 1; i++) {
-            convertBoxToRect(CENTER_OUT_INDEX[i]);
-        }
-        //dumpState();
-    }
-
-    @SuppressWarnings("unused")
-    private void dumpState() {
-        for (int i = -BOX_MAX; i < BOX_MAX; i++) {
-            Log.d(TAG, "Gap " + i + ": " + mGaps.get(i).mCurrentGap);
-        }
-
-        for (int i = 0; i < 2 * BOX_MAX + 1; i++) {
-            dumpRect(CENTER_OUT_INDEX[i]);
-        }
-
-        for (int i = -BOX_MAX; i <= BOX_MAX; i++) {
-            for (int j = i + 1; j <= BOX_MAX; j++) {
-                if (Rect.intersects(mRects.get(i), mRects.get(j))) {
-                    Log.d(TAG, "rect " + i + " and rect " + j + "intersects!");
-                }
-            }
-        }
-    }
-
-    private void dumpRect(int i) {
-        StringBuilder sb = new StringBuilder();
-        Rect r = mRects.get(i);
-        sb.append("Rect " + i + ":");
-        sb.append("(");
-        sb.append(r.centerX());
-        sb.append(",");
-        sb.append(r.centerY());
-        sb.append(") [");
-        sb.append(r.width());
-        sb.append("x");
-        sb.append(r.height());
-        sb.append("]");
-        Log.d(TAG, sb.toString());
-    }
-
-    private void convertBoxToRect(int i) {
-        Box b = mBoxes.get(i);
-        Rect r = mRects.get(i);
-        int y = b.mCurrentY + mPlatform.mCurrentY + mViewH / 2;
-        int w = widthOf(b);
-        int h = heightOf(b);
-        if (i == 0) {
-            int x = mPlatform.mCurrentX + mViewW / 2;
-            r.left = x - w / 2;
-            r.right = r.left + w;
-        } else if (i > 0) {
-            Rect a = mRects.get(i - 1);
-            Gap g = mGaps.get(i - 1);
-            r.left = a.right + g.mCurrentGap;
-            r.right = r.left + w;
-        } else {  // i < 0
-            Rect a = mRects.get(i + 1);
-            Gap g = mGaps.get(i);
-            r.right = a.left - g.mCurrentGap;
-            r.left = r.right - w;
-        }
-        r.top = y - h / 2;
-        r.bottom = r.top + h;
-    }
-
-    // Returns the position of a box.
-    public Rect getPosition(int index) {
-        return mRects.get(index);
-    }
-
-    ////////////////////////////////////////////////////////////////////////////
-    //  Box management
-    ////////////////////////////////////////////////////////////////////////////
-
-    // Initialize the platform to be at the view center.
-    private void initPlatform() {
-        mPlatform.updateDefaultXY();
-        mPlatform.mCurrentX = mPlatform.mDefaultX;
-        mPlatform.mCurrentY = mPlatform.mDefaultY;
-        mPlatform.mAnimationStartTime = NO_ANIMATION;
-    }
-
-    // Initialize a box to have the size of the view.
-    private void initBox(int index) {
-        Box b = mBoxes.get(index);
-        b.mImageW = mViewW;
-        b.mImageH = mViewH;
-        b.mUseViewSize = true;
-        b.mScaleMin = getMinimalScale(b);
-        b.mScaleMax = getMaximalScale(b);
-        b.mCurrentY = 0;
-        b.mCurrentScale = b.mScaleMin;
-        b.mAnimationStartTime = NO_ANIMATION;
-        b.mAnimationKind = ANIM_KIND_NONE;
-    }
-
-    // Initialize a box to a given size.
-    private void initBox(int index, Size size) {
-        if (size.width == 0 || size.height == 0) {
-            initBox(index);
-            return;
-        }
-        Box b = mBoxes.get(index);
-        b.mImageW = size.width;
-        b.mImageH = size.height;
-        b.mUseViewSize = false;
-        b.mScaleMin = getMinimalScale(b);
-        b.mScaleMax = getMaximalScale(b);
-        b.mCurrentY = 0;
-        b.mCurrentScale = b.mScaleMin;
-        b.mAnimationStartTime = NO_ANIMATION;
-        b.mAnimationKind = ANIM_KIND_NONE;
-    }
-
-    // Initialize a gap. This can only be called after the boxes around the gap
-    // has been initialized.
-    private void initGap(int index) {
-        Gap g = mGaps.get(index);
-        g.mDefaultSize = getDefaultGapSize(index);
-        g.mCurrentGap = g.mDefaultSize;
-        g.mAnimationStartTime = NO_ANIMATION;
-    }
-
-    private void initGap(int index, int size) {
-        Gap g = mGaps.get(index);
-        g.mDefaultSize = getDefaultGapSize(index);
-        g.mCurrentGap = size;
-        g.mAnimationStartTime = NO_ANIMATION;
-    }
-
-    @SuppressWarnings("unused")
-    private void debugMoveBox(int fromIndex[]) {
-        StringBuilder s = new StringBuilder("moveBox:");
-        for (int i = 0; i < fromIndex.length; i++) {
-            int j = fromIndex[i];
-            if (j == Integer.MAX_VALUE) {
-                s.append(" N");
-            } else {
-                s.append(" ");
-                s.append(fromIndex[i]);
-            }
-        }
-        Log.d(TAG, s.toString());
-    }
-
-    // Move the boxes: it may indicate focus change, box deleted, box appearing,
-    // box reordered, etc.
-    //
-    // Each element in the fromIndex array indicates where each box was in the
-    // old array. If the value is Integer.MAX_VALUE (pictured as N below), it
-    // means the box is new.
-    //
-    // For example:
-    // N N N N N N N -- all new boxes
-    // -3 -2 -1 0 1 2 3 -- nothing changed
-    // -2 -1 0 1 2 3 N -- focus goes to the next box
-    // N -3 -2 -1 0 1 2 -- focus goes to the previous box
-    // -3 -2 -1 1 2 3 N -- the focused box was deleted.
-    //
-    // hasPrev/hasNext indicates if there are previous/next boxes for the
-    // focused box. constrained indicates whether the focused box should be put
-    // into the constrained frame.
-    public void moveBox(int fromIndex[], boolean hasPrev, boolean hasNext,
-            boolean constrained, Size[] sizes) {
-        //debugMoveBox(fromIndex);
-        mHasPrev = hasPrev;
-        mHasNext = hasNext;
-
-        RangeIntArray from = new RangeIntArray(fromIndex, -BOX_MAX, BOX_MAX);
-
-        // 1. Get the absolute X coordinates for the boxes.
-        layoutAndSetPosition();
-        for (int i = -BOX_MAX; i <= BOX_MAX; i++) {
-            Box b = mBoxes.get(i);
-            Rect r = mRects.get(i);
-            b.mAbsoluteX = r.centerX() - mViewW / 2;
-        }
-
-        // 2. copy boxes and gaps to temporary storage.
-        for (int i = -BOX_MAX; i <= BOX_MAX; i++) {
-            mTempBoxes.put(i, mBoxes.get(i));
-            mBoxes.put(i, null);
-        }
-        for (int i = -BOX_MAX; i < BOX_MAX; i++) {
-            mTempGaps.put(i, mGaps.get(i));
-            mGaps.put(i, null);
-        }
-
-        // 3. move back boxes that are used in the new array.
-        for (int i = -BOX_MAX; i <= BOX_MAX; i++) {
-            int j = from.get(i);
-            if (j == Integer.MAX_VALUE) continue;
-            mBoxes.put(i, mTempBoxes.get(j));
-            mTempBoxes.put(j, null);
-        }
-
-        // 4. move back gaps if both boxes around it are kept together.
-        for (int i = -BOX_MAX; i < BOX_MAX; i++) {
-            int j = from.get(i);
-            if (j == Integer.MAX_VALUE) continue;
-            int k = from.get(i + 1);
-            if (k == Integer.MAX_VALUE) continue;
-            if (j + 1 == k) {
-                mGaps.put(i, mTempGaps.get(j));
-                mTempGaps.put(j, null);
-            }
-        }
-
-        // 5. recycle the boxes that are not used in the new array.
-        int k = -BOX_MAX;
-        for (int i = -BOX_MAX; i <= BOX_MAX; i++) {
-            if (mBoxes.get(i) != null) continue;
-            while (mTempBoxes.get(k) == null) {
-                k++;
-            }
-            mBoxes.put(i, mTempBoxes.get(k++));
-            initBox(i, sizes[i + BOX_MAX]);
-        }
-
-        // 6. Now give the recycled box a reasonable absolute X position.
-        //
-        // First try to find the first and the last box which the absolute X
-        // position is known.
-        int first, last;
-        for (first = -BOX_MAX; first <= BOX_MAX; first++) {
-            if (from.get(first) != Integer.MAX_VALUE) break;
-        }
-        for (last = BOX_MAX; last >= -BOX_MAX; last--) {
-            if (from.get(last) != Integer.MAX_VALUE) break;
-        }
-        // If there is no box has known X position at all, make the focused one
-        // as known.
-        if (first > BOX_MAX) {
-            mBoxes.get(0).mAbsoluteX = mPlatform.mCurrentX;
-            first = last = 0;
-        }
-        // Now for those boxes between first and last, assign their position to
-        // align to the previous box or the next box with known position. For
-        // the boxes before first or after last, we will use a new default gap
-        // size below.
-
-        // Align to the previous box
-        for (int i = Math.max(0, first + 1); i < last; i++) {
-            if (from.get(i) != Integer.MAX_VALUE) continue;
-            Box a = mBoxes.get(i - 1);
-            Box b = mBoxes.get(i);
-            int wa = widthOf(a);
-            int wb = widthOf(b);
-            b.mAbsoluteX = a.mAbsoluteX + (wa - wa / 2) + wb / 2
-                    + getDefaultGapSize(i);
-            if (mPopFromTop) {
-                b.mCurrentY = -(mViewH / 2 + heightOf(b) / 2);
-            } else {
-                b.mCurrentY = (mViewH / 2 + heightOf(b) / 2);
-            }
-        }
-
-        // Align to the next box
-        for (int i = Math.min(-1, last - 1); i > first; i--) {
-            if (from.get(i) != Integer.MAX_VALUE) continue;
-            Box a = mBoxes.get(i + 1);
-            Box b = mBoxes.get(i);
-            int wa = widthOf(a);
-            int wb = widthOf(b);
-            b.mAbsoluteX = a.mAbsoluteX - wa / 2 - (wb - wb / 2)
-                    - getDefaultGapSize(i);
-            if (mPopFromTop) {
-                b.mCurrentY = -(mViewH / 2 + heightOf(b) / 2);
-            } else {
-                b.mCurrentY = (mViewH / 2 + heightOf(b) / 2);
-            }
-        }
-
-        // 7. recycle the gaps that are not used in the new array.
-        k = -BOX_MAX;
-        for (int i = -BOX_MAX; i < BOX_MAX; i++) {
-            if (mGaps.get(i) != null) continue;
-            while (mTempGaps.get(k) == null) {
-                k++;
-            }
-            mGaps.put(i, mTempGaps.get(k++));
-            Box a = mBoxes.get(i);
-            Box b = mBoxes.get(i + 1);
-            int wa = widthOf(a);
-            int wb = widthOf(b);
-            if (i >= first && i < last) {
-                int g = b.mAbsoluteX - a.mAbsoluteX - wb / 2 - (wa - wa / 2);
-                initGap(i, g);
-            } else {
-                initGap(i);
-            }
-        }
-
-        // 8. calculate the new absolute X coordinates for those box before
-        // first or after last.
-        for (int i = first - 1; i >= -BOX_MAX; i--) {
-            Box a = mBoxes.get(i + 1);
-            Box b = mBoxes.get(i);
-            int wa = widthOf(a);
-            int wb = widthOf(b);
-            Gap g = mGaps.get(i);
-            b.mAbsoluteX = a.mAbsoluteX - wa / 2 - (wb - wb / 2) - g.mCurrentGap;
-        }
-
-        for (int i = last + 1; i <= BOX_MAX; i++) {
-            Box a = mBoxes.get(i - 1);
-            Box b = mBoxes.get(i);
-            int wa = widthOf(a);
-            int wb = widthOf(b);
-            Gap g = mGaps.get(i - 1);
-            b.mAbsoluteX = a.mAbsoluteX + (wa - wa / 2) + wb / 2 + g.mCurrentGap;
-        }
-
-        // 9. offset the Platform position
-        int dx = mBoxes.get(0).mAbsoluteX - mPlatform.mCurrentX;
-        mPlatform.mCurrentX += dx;
-        mPlatform.mFromX += dx;
-        mPlatform.mToX += dx;
-        mPlatform.mFlingOffset += dx;
-
-        if (mConstrained != constrained) {
-            mConstrained = constrained;
-            mPlatform.updateDefaultXY();
-            updateScaleAndGapLimit();
-        }
-
-        snapAndRedraw();
-    }
-
-    ////////////////////////////////////////////////////////////////////////////
-    //  Public utilities
-    ////////////////////////////////////////////////////////////////////////////
-
-    public boolean isAtMinimalScale() {
-        Box b = mBoxes.get(0);
-        return isAlmostEqual(b.mCurrentScale, b.mScaleMin);
-    }
-
-    public boolean isCenter() {
-        Box b = mBoxes.get(0);
-        return mPlatform.mCurrentX == mPlatform.mDefaultX
-            && b.mCurrentY == 0;
-    }
-
-    public int getImageWidth() {
-        Box b = mBoxes.get(0);
-        return b.mImageW;
-    }
-
-    public int getImageHeight() {
-        Box b = mBoxes.get(0);
-        return b.mImageH;
-    }
-
-    public float getImageScale() {
-        Box b = mBoxes.get(0);
-        return b.mCurrentScale;
-    }
-
-    public int getImageAtEdges() {
-        Box b = mBoxes.get(0);
-        Platform p = mPlatform;
-        calculateStableBound(b.mCurrentScale);
-        int edges = 0;
-        if (p.mCurrentX <= mBoundLeft) {
-            edges |= IMAGE_AT_RIGHT_EDGE;
-        }
-        if (p.mCurrentX >= mBoundRight) {
-            edges |= IMAGE_AT_LEFT_EDGE;
-        }
-        if (b.mCurrentY <= mBoundTop) {
-            edges |= IMAGE_AT_BOTTOM_EDGE;
-        }
-        if (b.mCurrentY >= mBoundBottom) {
-            edges |= IMAGE_AT_TOP_EDGE;
-        }
-        return edges;
-    }
-
-    public boolean isScrolling() {
-        return mPlatform.mAnimationStartTime != NO_ANIMATION
-                && mPlatform.mCurrentX != mPlatform.mToX;
-    }
-
-    public void stopScrolling() {
-        if (mPlatform.mAnimationStartTime == NO_ANIMATION) return;
-        if (mFilmMode) mFilmScroller.forceFinished(true);
-        mPlatform.mFromX = mPlatform.mToX = mPlatform.mCurrentX;
-    }
-
-    public float getFilmRatio() {
-        return mFilmRatio.mCurrentRatio;
-    }
-
-    public void setPopFromTop(boolean top) {
-        mPopFromTop = top;
-    }
-
-    public boolean hasDeletingBox() {
-        for(int i = -BOX_MAX; i <= BOX_MAX; i++) {
-            if (mBoxes.get(i).mAnimationKind == ANIM_KIND_DELETE) {
-                return true;
-            }
-        }
-        return false;
-    }
-
-    ////////////////////////////////////////////////////////////////////////////
-    //  Private utilities
-    ////////////////////////////////////////////////////////////////////////////
-
-    private float getMinimalScale(Box b) {
-        float wFactor = 1.0f;
-        float hFactor = 1.0f;
-        int viewW, viewH;
-
-        if (!mFilmMode && mConstrained && !mConstrainedFrame.isEmpty()
-                && b == mBoxes.get(0)) {
-            viewW = mConstrainedFrame.width();
-            viewH = mConstrainedFrame.height();
-        } else {
-            viewW = mViewW;
-            viewH = mViewH;
-        }
-
-        if (mFilmMode) {
-            if (mViewH > mViewW) {  // portrait
-                wFactor = FILM_MODE_PORTRAIT_WIDTH;
-                hFactor = FILM_MODE_PORTRAIT_HEIGHT;
-            } else {  // landscape
-                wFactor = FILM_MODE_LANDSCAPE_WIDTH;
-                hFactor = FILM_MODE_LANDSCAPE_HEIGHT;
-            }
-        }
-
-        float s = Math.min(wFactor * viewW / b.mImageW,
-                hFactor * viewH / b.mImageH);
-        return Math.min(SCALE_LIMIT, s);
-    }
-
-    private float getMaximalScale(Box b) {
-        if (mFilmMode) return getMinimalScale(b);
-        if (mConstrained && !mConstrainedFrame.isEmpty()) return getMinimalScale(b);
-        return SCALE_LIMIT;
-    }
-
-    private static boolean isAlmostEqual(float a, float b) {
-        float diff = a - b;
-        return (diff < 0 ? -diff : diff) < 0.02f;
-    }
-
-    // Calculates the stable region of mPlatform.mCurrentX and
-    // mBoxes.get(0).mCurrentY, where "stable" means
-    //
-    // (1) If the dimension of scaled image >= view dimension, we will not
-    // see black region outside the image (at that dimension).
-    // (2) If the dimension of scaled image < view dimension, we will center
-    // the scaled image.
-    //
-    // We might temporarily go out of this stable during user interaction,
-    // but will "snap back" after user stops interaction.
-    //
-    // The results are stored in mBound{Left/Right/Top/Bottom}.
-    //
-    // An extra parameter "horizontalSlack" (which has the value of 0 usually)
-    // is used to extend the stable region by some pixels on each side
-    // horizontally.
-    private void calculateStableBound(float scale, int horizontalSlack) {
-        Box b = mBoxes.get(0);
-
-        // The width and height of the box in number of view pixels
-        int w = widthOf(b, scale);
-        int h = heightOf(b, scale);
-
-        // When the edge of the view is aligned with the edge of the box
-        mBoundLeft = (mViewW + 1) / 2 - (w + 1) / 2 - horizontalSlack;
-        mBoundRight = w / 2 - mViewW / 2 + horizontalSlack;
-        mBoundTop = (mViewH + 1) / 2 - (h + 1) / 2;
-        mBoundBottom = h / 2 - mViewH / 2;
-
-        // If the scaled height is smaller than the view height,
-        // force it to be in the center.
-        if (viewTallerThanScaledImage(scale)) {
-            mBoundTop = mBoundBottom = 0;
-        }
-
-        // Same for width
-        if (viewWiderThanScaledImage(scale)) {
-            mBoundLeft = mBoundRight = mPlatform.mDefaultX;
-        }
-    }
-
-    private void calculateStableBound(float scale) {
-        calculateStableBound(scale, 0);
-    }
-
-    private boolean viewTallerThanScaledImage(float scale) {
-        return mViewH >= heightOf(mBoxes.get(0), scale);
-    }
-
-    private boolean viewWiderThanScaledImage(float scale) {
-        return mViewW >= widthOf(mBoxes.get(0), scale);
-    }
-
-    private float getTargetScale(Box b) {
-        return b.mAnimationStartTime == NO_ANIMATION
-                ? b.mCurrentScale : b.mToScale;
-    }
-
-    ////////////////////////////////////////////////////////////////////////////
-    //  Animatable: an thing which can do animation.
-    ////////////////////////////////////////////////////////////////////////////
-    private abstract static class Animatable {
-        public long mAnimationStartTime;
-        public int mAnimationKind;
-        public int mAnimationDuration;
-
-        // This should be overridden in subclass to change the animation values
-        // give the progress value in [0, 1].
-        protected abstract boolean interpolate(float progress);
-        public abstract boolean startSnapback();
-
-        // Returns true if the animation values changes, so things need to be
-        // redrawn.
-        public boolean advanceAnimation() {
-            if (mAnimationStartTime == NO_ANIMATION) {
-                return false;
-            }
-            if (mAnimationStartTime == LAST_ANIMATION) {
-                mAnimationStartTime = NO_ANIMATION;
-                return startSnapback();
-            }
-
-            float progress;
-            if (mAnimationDuration == 0) {
-                progress = 1;
-            } else {
-                long now = AnimationTime.get();
-                progress =
-                    (float) (now - mAnimationStartTime) / mAnimationDuration;
-            }
-
-            if (progress >= 1) {
-                progress = 1;
-            } else {
-                progress = applyInterpolationCurve(mAnimationKind, progress);
-            }
-
-            boolean done = interpolate(progress);
-
-            if (done) {
-                mAnimationStartTime = LAST_ANIMATION;
-            }
-
-            return true;
-        }
-
-        private static float applyInterpolationCurve(int kind, float progress) {
-            float f = 1 - progress;
-            switch (kind) {
-                case ANIM_KIND_SCROLL:
-                case ANIM_KIND_FLING:
-                case ANIM_KIND_FLING_X:
-                case ANIM_KIND_DELETE:
-                case ANIM_KIND_CAPTURE:
-                    progress = 1 - f;  // linear
-                    break;
-                case ANIM_KIND_OPENING:
-                case ANIM_KIND_SCALE:
-                    progress = 1 - f * f;  // quadratic
-                    break;
-                case ANIM_KIND_SNAPBACK:
-                case ANIM_KIND_ZOOM:
-                case ANIM_KIND_SLIDE:
-                    progress = 1 - f * f * f * f * f; // x^5
-                    break;
-            }
-            return progress;
-        }
-    }
-
-    ////////////////////////////////////////////////////////////////////////////
-    //  Platform: captures the global X/Y movement.
-    ////////////////////////////////////////////////////////////////////////////
-    private class Platform extends Animatable {
-        public int mCurrentX, mFromX, mToX, mDefaultX;
-        public int mCurrentY, mFromY, mToY, mDefaultY;
-        public int mFlingOffset;
-
-        @Override
-        public boolean startSnapback() {
-            if (mAnimationStartTime != NO_ANIMATION) return false;
-            if (mAnimationKind == ANIM_KIND_SCROLL
-                    && mListener.isHoldingDown()) return false;
-            if (mInScale) return false;
-
-            Box b = mBoxes.get(0);
-            float scaleMin = mExtraScalingRange ?
-                b.mScaleMin * SCALE_MIN_EXTRA : b.mScaleMin;
-            float scaleMax = mExtraScalingRange ?
-                b.mScaleMax * SCALE_MAX_EXTRA : b.mScaleMax;
-            float scale = Utils.clamp(b.mCurrentScale, scaleMin, scaleMax);
-            int x = mCurrentX;
-            int y = mDefaultY;
-            if (mFilmMode) {
-                x = mDefaultX;
-            } else {
-                calculateStableBound(scale, HORIZONTAL_SLACK);
-                // If the picture is zoomed-in, we want to keep the focus point
-                // stay in the same position on screen, so we need to adjust
-                // target mCurrentX (which is the center of the focused
-                // box). The position of the focus point on screen (relative the
-                // the center of the view) is:
-                //
-                // mCurrentX + scale * mFocusX = mCurrentX' + scale' * mFocusX
-                // => mCurrentX' = mCurrentX + (scale - scale') * mFocusX
-                //
-                if (!viewWiderThanScaledImage(scale)) {
-                    float scaleDiff = b.mCurrentScale - scale;
-                    x += (int) (mFocusX * scaleDiff + 0.5f);
-                }
-                x = Utils.clamp(x, mBoundLeft, mBoundRight);
-            }
-            if (mCurrentX != x || mCurrentY != y) {
-                return doAnimation(x, y, ANIM_KIND_SNAPBACK);
-            }
-            return false;
-        }
-
-        // The updateDefaultXY() should be called whenever these variables
-        // changes: (1) mConstrained (2) mConstrainedFrame (3) mViewW/H (4)
-        // mFilmMode
-        public void updateDefaultXY() {
-            // We don't check mFilmMode and return 0 for mDefaultX. Because
-            // otherwise if we decide to leave film mode because we are
-            // centered, we will immediately back into film mode because we find
-            // we are not centered.
-            if (mConstrained && !mConstrainedFrame.isEmpty()) {
-                mDefaultX = mConstrainedFrame.centerX() - mViewW / 2;
-                mDefaultY = mFilmMode ? 0 :
-                        mConstrainedFrame.centerY() - mViewH / 2;
-            } else {
-                mDefaultX = 0;
-                mDefaultY = 0;
-            }
-        }
-
-        // Starts an animation for the platform.
-        private boolean doAnimation(int targetX, int targetY, int kind) {
-            if (mCurrentX == targetX && mCurrentY == targetY) return false;
-            mAnimationKind = kind;
-            mFromX = mCurrentX;
-            mFromY = mCurrentY;
-            mToX = targetX;
-            mToY = targetY;
-            mAnimationStartTime = AnimationTime.startTime();
-            mAnimationDuration = ANIM_TIME[kind];
-            mFlingOffset = 0;
-            advanceAnimation();
-            return true;
-        }
-
-        @Override
-        protected boolean interpolate(float progress) {
-            if (mAnimationKind == ANIM_KIND_FLING) {
-                return interpolateFlingPage(progress);
-            } else if (mAnimationKind == ANIM_KIND_FLING_X) {
-                return interpolateFlingFilm(progress);
-            } else {
-                return interpolateLinear(progress);
-            }
-        }
-
-        private boolean interpolateFlingFilm(float progress) {
-            mFilmScroller.computeScrollOffset();
-            mCurrentX = mFilmScroller.getCurrX() + mFlingOffset;
-
-            int dir = EdgeView.INVALID_DIRECTION;
-            if (mCurrentX < mDefaultX) {
-                if (!mHasNext) {
-                    dir = EdgeView.RIGHT;
-                }
-            } else if (mCurrentX > mDefaultX) {
-                if (!mHasPrev) {
-                    dir = EdgeView.LEFT;
-                }
-            }
-            if (dir != EdgeView.INVALID_DIRECTION) {
-                // TODO: restore this onAbsorb call
-                //int v = (int) (mFilmScroller.getCurrVelocity() + 0.5f);
-                //mListener.onAbsorb(v, dir);
-                mFilmScroller.forceFinished(true);
-                mCurrentX = mDefaultX;
-            }
-            return mFilmScroller.isFinished();
-        }
-
-        private boolean interpolateFlingPage(float progress) {
-            mPageScroller.computeScrollOffset(progress);
-            Box b = mBoxes.get(0);
-            calculateStableBound(b.mCurrentScale);
-
-            int oldX = mCurrentX;
-            mCurrentX = mPageScroller.getCurrX();
-
-            // Check if we hit the edges; show edge effects if we do.
-            if (oldX > mBoundLeft && mCurrentX == mBoundLeft) {
-                int v = (int) (-mPageScroller.getCurrVelocityX() + 0.5f);
-                mListener.onAbsorb(v, EdgeView.RIGHT);
-            } else if (oldX < mBoundRight && mCurrentX == mBoundRight) {
-                int v = (int) (mPageScroller.getCurrVelocityX() + 0.5f);
-                mListener.onAbsorb(v, EdgeView.LEFT);
-            }
-
-            return progress >= 1;
-        }
-
-        private boolean interpolateLinear(float progress) {
-            // Other animations
-            if (progress >= 1) {
-                mCurrentX = mToX;
-                mCurrentY = mToY;
-                return true;
-            } else {
-                if (mAnimationKind == ANIM_KIND_CAPTURE) {
-                    progress = CaptureAnimation.calculateSlide(progress);
-                }
-                mCurrentX = (int) (mFromX + progress * (mToX - mFromX));
-                mCurrentY = (int) (mFromY + progress * (mToY - mFromY));
-                if (mAnimationKind == ANIM_KIND_CAPTURE) {
-                    return false;
-                } else {
-                    return (mCurrentX == mToX && mCurrentY == mToY);
-                }
-            }
-        }
-    }
-
-    ////////////////////////////////////////////////////////////////////////////
-    //  Box: represents a rectangular area which shows a picture.
-    ////////////////////////////////////////////////////////////////////////////
-    private class Box extends Animatable {
-        // Size of the bitmap
-        public int mImageW, mImageH;
-
-        // This is true if we assume the image size is the same as view size
-        // until we know the actual size of image. This is also used to
-        // determine if there is an image ready to show.
-        public boolean mUseViewSize;
-
-        // The minimum and maximum scale we allow for this box.
-        public float mScaleMin, mScaleMax;
-
-        // The X/Y value indicates where the center of the box is on the view
-        // coordinate. We always keep the mCurrent{X,Y,Scale} sync with the
-        // actual values used currently. Note that the X values are implicitly
-        // defined by Platform and Gaps.
-        public int mCurrentY, mFromY, mToY;
-        public float mCurrentScale, mFromScale, mToScale;
-
-        // The absolute X coordinate of the center of the box. This is only used
-        // during moveBox().
-        public int mAbsoluteX;
-
-        @Override
-        public boolean startSnapback() {
-            if (mAnimationStartTime != NO_ANIMATION) return false;
-            if (mAnimationKind == ANIM_KIND_SCROLL
-                    && mListener.isHoldingDown()) return false;
-            if (mAnimationKind == ANIM_KIND_DELETE
-                    && mListener.isHoldingDelete()) return false;
-            if (mInScale && this == mBoxes.get(0)) return false;
-
-            int y = mCurrentY;
-            float scale;
-
-            if (this == mBoxes.get(0)) {
-                float scaleMin = mExtraScalingRange ?
-                    mScaleMin * SCALE_MIN_EXTRA : mScaleMin;
-                float scaleMax = mExtraScalingRange ?
-                    mScaleMax * SCALE_MAX_EXTRA : mScaleMax;
-                scale = Utils.clamp(mCurrentScale, scaleMin, scaleMax);
-                if (mFilmMode) {
-                    y = 0;
-                } else {
-                    calculateStableBound(scale, HORIZONTAL_SLACK);
-                    // If the picture is zoomed-in, we want to keep the focus
-                    // point stay in the same position on screen. See the
-                    // comment in Platform.startSnapback for details.
-                    if (!viewTallerThanScaledImage(scale)) {
-                        float scaleDiff = mCurrentScale - scale;
-                        y += (int) (mFocusY * scaleDiff + 0.5f);
-                    }
-                    y = Utils.clamp(y, mBoundTop, mBoundBottom);
-                }
-            } else {
-                y = 0;
-                scale = mScaleMin;
-            }
-
-            if (mCurrentY != y || mCurrentScale != scale) {
-                return doAnimation(y, scale, ANIM_KIND_SNAPBACK);
-            }
-            return false;
-        }
-
-        private boolean doAnimation(int targetY, float targetScale, int kind) {
-            targetScale = clampScale(targetScale);
-
-            if (mCurrentY == targetY && mCurrentScale == targetScale
-                    && kind != ANIM_KIND_CAPTURE) {
-                return false;
-            }
-
-            // Now starts an animation for the box.
-            mAnimationKind = kind;
-            mFromY = mCurrentY;
-            mFromScale = mCurrentScale;
-            mToY = targetY;
-            mToScale = targetScale;
-            mAnimationStartTime = AnimationTime.startTime();
-            mAnimationDuration = ANIM_TIME[kind];
-            advanceAnimation();
-            return true;
-        }
-
-        // Clamps the input scale to the range that doAnimation() can reach.
-        public float clampScale(float s) {
-            return Utils.clamp(s,
-                    SCALE_MIN_EXTRA * mScaleMin,
-                    SCALE_MAX_EXTRA * mScaleMax);
-        }
-
-        @Override
-        protected boolean interpolate(float progress) {
-            if (mAnimationKind == ANIM_KIND_FLING) {
-                return interpolateFlingPage(progress);
-            } else {
-                return interpolateLinear(progress);
-            }
-        }
-
-        private boolean interpolateFlingPage(float progress) {
-            mPageScroller.computeScrollOffset(progress);
-            calculateStableBound(mCurrentScale);
-
-            int oldY = mCurrentY;
-            mCurrentY = mPageScroller.getCurrY();
-
-            // Check if we hit the edges; show edge effects if we do.
-            if (oldY > mBoundTop && mCurrentY == mBoundTop) {
-                int v = (int) (-mPageScroller.getCurrVelocityY() + 0.5f);
-                mListener.onAbsorb(v, EdgeView.BOTTOM);
-            } else if (oldY < mBoundBottom && mCurrentY == mBoundBottom) {
-                int v = (int) (mPageScroller.getCurrVelocityY() + 0.5f);
-                mListener.onAbsorb(v, EdgeView.TOP);
-            }
-
-            return progress >= 1;
-        }
-
-        private boolean interpolateLinear(float progress) {
-            if (progress >= 1) {
-                mCurrentY = mToY;
-                mCurrentScale = mToScale;
-                return true;
-            } else {
-                mCurrentY = (int) (mFromY + progress * (mToY - mFromY));
-                mCurrentScale = mFromScale + progress * (mToScale - mFromScale);
-                if (mAnimationKind == ANIM_KIND_CAPTURE) {
-                    float f = CaptureAnimation.calculateScale(progress);
-                    mCurrentScale *= f;
-                    return false;
-                } else {
-                    return (mCurrentY == mToY && mCurrentScale == mToScale);
-                }
-            }
-        }
-    }
-
-    ////////////////////////////////////////////////////////////////////////////
-    //  Gap: represents a rectangular area which is between two boxes.
-    ////////////////////////////////////////////////////////////////////////////
-    private class Gap extends Animatable {
-        // The default gap size between two boxes. The value may vary for
-        // different image size of the boxes and for different modes (page or
-        // film).
-        public int mDefaultSize;
-
-        // The gap size between the two boxes.
-        public int mCurrentGap, mFromGap, mToGap;
-
-        @Override
-        public boolean startSnapback() {
-            if (mAnimationStartTime != NO_ANIMATION) return false;
-            return doAnimation(mDefaultSize, ANIM_KIND_SNAPBACK);
-        }
-
-        // Starts an animation for a gap.
-        public boolean doAnimation(int targetSize, int kind) {
-            if (mCurrentGap == targetSize && kind != ANIM_KIND_CAPTURE) {
-                return false;
-            }
-            mAnimationKind = kind;
-            mFromGap = mCurrentGap;
-            mToGap = targetSize;
-            mAnimationStartTime = AnimationTime.startTime();
-            mAnimationDuration = ANIM_TIME[mAnimationKind];
-            advanceAnimation();
-            return true;
-        }
-
-        @Override
-        protected boolean interpolate(float progress) {
-            if (progress >= 1) {
-                mCurrentGap = mToGap;
-                return true;
-            } else {
-                mCurrentGap = (int) (mFromGap + progress * (mToGap - mFromGap));
-                if (mAnimationKind == ANIM_KIND_CAPTURE) {
-                    float f = CaptureAnimation.calculateScale(progress);
-                    mCurrentGap = (int) (mCurrentGap * f);
-                    return false;
-                } else {
-                    return (mCurrentGap == mToGap);
-                }
-            }
-        }
-    }
-
-    ////////////////////////////////////////////////////////////////////////////
-    //  FilmRatio: represents the progress of film mode change.
-    ////////////////////////////////////////////////////////////////////////////
-    private class FilmRatio extends Animatable {
-        // The film ratio: 1 means switching to film mode is complete, 0 means
-        // switching to page mode is complete.
-        public float mCurrentRatio, mFromRatio, mToRatio;
-
-        @Override
-        public boolean startSnapback() {
-            float target = mFilmMode ? 1f : 0f;
-            if (target == mToRatio) return false;
-            return doAnimation(target, ANIM_KIND_SNAPBACK);
-        }
-
-        // Starts an animation for the film ratio.
-        private boolean doAnimation(float targetRatio, int kind) {
-            mAnimationKind = kind;
-            mFromRatio = mCurrentRatio;
-            mToRatio = targetRatio;
-            mAnimationStartTime = AnimationTime.startTime();
-            mAnimationDuration = ANIM_TIME[mAnimationKind];
-            advanceAnimation();
-            return true;
-        }
-
-        @Override
-        protected boolean interpolate(float progress) {
-            if (progress >= 1) {
-                mCurrentRatio = mToRatio;
-                return true;
-            } else {
-                mCurrentRatio = mFromRatio + progress * (mToRatio - mFromRatio);
-                return (mCurrentRatio == mToRatio);
-            }
-        }
-    }
-}
diff --git a/src/com/android/gallery3d/ui/PreparePageFadeoutTexture.java b/src/com/android/gallery3d/ui/PreparePageFadeoutTexture.java
deleted file mode 100644
index ce672f2..0000000
--- a/src/com/android/gallery3d/ui/PreparePageFadeoutTexture.java
+++ /dev/null
@@ -1,85 +0,0 @@
-package com.android.gallery3d.ui;
-
-import android.os.ConditionVariable;
-
-import com.android.gallery3d.app.AbstractGalleryActivity;
-import com.android.gallery3d.glrenderer.GLCanvas;
-import com.android.gallery3d.glrenderer.RawTexture;
-import com.android.gallery3d.ui.GLRoot.OnGLIdleListener;
-
-public class PreparePageFadeoutTexture implements OnGLIdleListener {
-    private static final long TIMEOUT = 200;
-    public static final String KEY_FADE_TEXTURE = "fade_texture";
-
-    private RawTexture mTexture;
-    private ConditionVariable mResultReady = new ConditionVariable(false);
-    private boolean mCancelled = false;
-    private GLView mRootPane;
-
-    public PreparePageFadeoutTexture(GLView rootPane) {
-        if (rootPane == null) {
-            mCancelled = true;
-            return;
-        }
-        int w = rootPane.getWidth();
-        int h = rootPane.getHeight();
-        if (w == 0 || h == 0) {
-            mCancelled = true;
-            return;
-        }
-        mTexture = new RawTexture(w, h, true);
-        mRootPane =  rootPane;
-    }
-
-    public boolean isCancelled() {
-        return mCancelled;
-    }
-
-    public synchronized RawTexture get() {
-        if (mCancelled) {
-            return null;
-        } else if (mResultReady.block(TIMEOUT)) {
-            return mTexture;
-        } else {
-            mCancelled = true;
-            return null;
-        }
-    }
-
-    @Override
-    public boolean onGLIdle(GLCanvas canvas, boolean renderRequested) {
-        if (!mCancelled) {
-            try {
-                canvas.beginRenderTarget(mTexture);
-                mRootPane.render(canvas);
-                canvas.endRenderTarget();
-            } catch (RuntimeException e) {
-                mTexture = null;
-            }
-        } else {
-            mTexture = null;
-        }
-        mResultReady.open();
-        return false;
-    }
-
-    public static void prepareFadeOutTexture(AbstractGalleryActivity activity,
-            GLView rootPane) {
-        PreparePageFadeoutTexture task = new PreparePageFadeoutTexture(rootPane);
-        if (task.isCancelled()) return;
-        GLRoot root = activity.getGLRoot();
-        RawTexture texture = null;
-        root.unlockRenderThread();
-        try {
-            root.addOnGLIdleListener(task);
-            texture = task.get();
-        } finally {
-            root.lockRenderThread();
-        }
-
-        if (texture == null) {
-            return;
-        }
-        activity.getTransitionStore().put(KEY_FADE_TEXTURE, texture);
-    }
-}
diff --git a/src/com/android/gallery3d/ui/ProgressSpinner.java b/src/com/android/gallery3d/ui/ProgressSpinner.java
deleted file mode 100644
index 1b31af2..0000000
--- a/src/com/android/gallery3d/ui/ProgressSpinner.java
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * Copyright (C) 2010 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.gallery3d.ui;
-
-import android.content.Context;
-
-import com.android.gallery3d.R;
-import com.android.gallery3d.glrenderer.GLCanvas;
-import com.android.gallery3d.glrenderer.ResourceTexture;
-
-public class ProgressSpinner {
-    private static float ROTATE_SPEED_OUTER = 1080f / 3500f;
-    private static float ROTATE_SPEED_INNER = -720f / 3500f;
-    private final ResourceTexture mOuter;
-    private final ResourceTexture mInner;
-    private final int mWidth;
-    private final int mHeight;
-
-    private float mInnerDegree = 0f;
-    private float mOuterDegree = 0f;
-    private long mAnimationTimestamp = -1;
-
-    public ProgressSpinner(Context context) {
-        mOuter = new ResourceTexture(context, R.drawable.spinner_76_outer_holo);
-        mInner = new ResourceTexture(context, R.drawable.spinner_76_inner_holo);
-
-        mWidth = Math.max(mOuter.getWidth(), mInner.getWidth());
-        mHeight = Math.max(mOuter.getHeight(), mInner.getHeight());
-    }
-
-    public int getWidth() {
-        return mWidth;
-    }
-
-    public int getHeight() {
-        return mHeight;
-    }
-
-    public void startAnimation() {
-        mAnimationTimestamp = -1;
-        mOuterDegree = 0;
-        mInnerDegree = 0;
-    }
-
-    public void draw(GLCanvas canvas, int x, int y) {
-        long now = AnimationTime.get();
-        if (mAnimationTimestamp == -1) mAnimationTimestamp = now;
-        mOuterDegree += (now - mAnimationTimestamp) * ROTATE_SPEED_OUTER;
-        mInnerDegree += (now - mAnimationTimestamp) * ROTATE_SPEED_INNER;
-
-        mAnimationTimestamp = now;
-
-        // just preventing overflow
-        if (mOuterDegree > 360) mOuterDegree -= 360f;
-        if (mInnerDegree < 0) mInnerDegree += 360f;
-
-        canvas.save(GLCanvas.SAVE_FLAG_MATRIX);
-
-        canvas.translate(x + mWidth / 2, y + mHeight / 2);
-        canvas.rotate(mInnerDegree, 0, 0, 1);
-        mOuter.draw(canvas, -mOuter.getWidth() / 2, -mOuter.getHeight() / 2);
-        canvas.rotate(mOuterDegree - mInnerDegree, 0, 0, 1);
-        mInner.draw(canvas, -mInner.getWidth() / 2, -mInner.getHeight() / 2);
-        canvas.restore();
-    }
-}
diff --git a/src/com/android/gallery3d/ui/RelativePosition.java b/src/com/android/gallery3d/ui/RelativePosition.java
deleted file mode 100644
index 0f2bfd8..0000000
--- a/src/com/android/gallery3d/ui/RelativePosition.java
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Copyright (C) 2010 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.gallery3d.ui;
-
-public class RelativePosition {
-    private float mAbsoluteX;
-    private float mAbsoluteY;
-    private float mReferenceX;
-    private float mReferenceY;
-
-    public void setAbsolutePosition(int absoluteX, int absoluteY) {
-        mAbsoluteX = absoluteX;
-        mAbsoluteY = absoluteY;
-    }
-
-    public void setReferencePosition(int x, int y) {
-        mReferenceX = x;
-        mReferenceY = y;
-    }
-
-    public float getX() {
-        return mAbsoluteX - mReferenceX;
-    }
-
-    public float getY() {
-        return mAbsoluteY - mReferenceY;
-    }
-}
diff --git a/src/com/android/gallery3d/ui/ScreenNail.java b/src/com/android/gallery3d/ui/ScreenNail.java
deleted file mode 100644
index 965bf0b..0000000
--- a/src/com/android/gallery3d/ui/ScreenNail.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * 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.gallery3d.ui;
-
-import android.graphics.RectF;
-
-import com.android.gallery3d.glrenderer.GLCanvas;
-
-public interface ScreenNail {
-    public int getWidth();
-    public int getHeight();
-    public void draw(GLCanvas canvas, int x, int y, int width, int height);
-
-    // We do not need to draw this ScreenNail in this frame.
-    public void noDraw();
-
-    // This ScreenNail will not be used anymore. Release related resources.
-    public void recycle();
-
-    // This is only used by TileImageView to back up the tiles not yet loaded.
-    public void draw(GLCanvas canvas, RectF source, RectF dest);
-}
diff --git a/src/com/android/gallery3d/ui/ScrollBarView.java b/src/com/android/gallery3d/ui/ScrollBarView.java
deleted file mode 100644
index 34fbcef..0000000
--- a/src/com/android/gallery3d/ui/ScrollBarView.java
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- * Copyright (C) 2010 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.gallery3d.ui;
-
-import android.content.Context;
-import android.graphics.Rect;
-import android.util.TypedValue;
-
-import com.android.gallery3d.glrenderer.GLCanvas;
-import com.android.gallery3d.glrenderer.NinePatchTexture;
-
-public class ScrollBarView extends GLView {
-    @SuppressWarnings("unused")
-    private static final String TAG = "ScrollBarView";
-
-    private int mBarHeight;
-
-    private int mGripHeight;
-    private int mGripPosition;  // left side of the grip
-    private int mGripWidth;     // zero if the grip is disabled
-    private int mGivenGripWidth;
-
-    private int mContentPosition;
-    private int mContentTotal;
-
-    private NinePatchTexture mScrollBarTexture;
-
-    public ScrollBarView(Context context, int gripHeight, int gripWidth) {
-        TypedValue outValue = new TypedValue();
-        context.getTheme().resolveAttribute(
-                android.R.attr.scrollbarThumbHorizontal, outValue, true);
-        mScrollBarTexture = new NinePatchTexture(
-                context, outValue.resourceId);
-        mGripPosition = 0;
-        mGripWidth = 0;
-        mGivenGripWidth = gripWidth;
-        mGripHeight = gripHeight;
-    }
-
-    @Override
-    protected void onLayout(
-            boolean changed, int left, int top, int right, int bottom) {
-        if (!changed) return;
-        mBarHeight = bottom - top;
-    }
-
-    // The content position is between 0 to "total". The current position is
-    // in "position".
-    public void setContentPosition(int position, int total) {
-        if (position == mContentPosition && total == mContentTotal) {
-            return;
-        }
-
-        invalidate();
-
-        mContentPosition = position;
-        mContentTotal = total;
-
-        // If the grip cannot move, don't draw it.
-        if (mContentTotal <= 0) {
-            mGripPosition = 0;
-            mGripWidth = 0;
-            return;
-        }
-
-        // Map from the content range to scroll bar range.
-        //
-        // mContentTotal --> getWidth() - mGripWidth
-        // mContentPosition --> mGripPosition
-        mGripWidth = mGivenGripWidth;
-        float r = (getWidth() - mGripWidth) / (float) mContentTotal;
-        mGripPosition = Math.round(r * mContentPosition);
-    }
-
-    @Override
-    protected void render(GLCanvas canvas) {
-        super.render(canvas);
-        if (mGripWidth == 0) return;
-        Rect b = bounds();
-        int y = (mBarHeight - mGripHeight) / 2;
-        mScrollBarTexture.draw(canvas, mGripPosition, y, mGripWidth, mGripHeight);
-    }
-}
diff --git a/src/com/android/gallery3d/ui/ScrollerHelper.java b/src/com/android/gallery3d/ui/ScrollerHelper.java
deleted file mode 100644
index aa68d19..0000000
--- a/src/com/android/gallery3d/ui/ScrollerHelper.java
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- * Copyright (C) 2010 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.gallery3d.ui;
-
-import android.content.Context;
-import android.view.ViewConfiguration;
-
-import com.android.gallery3d.common.OverScroller;
-import com.android.gallery3d.common.Utils;
-
-public class ScrollerHelper {
-    private OverScroller mScroller;
-    private int mOverflingDistance;
-    private boolean mOverflingEnabled;
-
-    public ScrollerHelper(Context context) {
-        mScroller = new OverScroller(context);
-        ViewConfiguration configuration = ViewConfiguration.get(context);
-        mOverflingDistance = configuration.getScaledOverflingDistance();
-    }
-
-    public void setOverfling(boolean enabled) {
-        mOverflingEnabled = enabled;
-    }
-
-    /**
-     * Call this when you want to know the new location. The position will be
-     * updated and can be obtained by getPosition(). Returns true if  the
-     * animation is not yet finished.
-     */
-    public boolean advanceAnimation(long currentTimeMillis) {
-        return mScroller.computeScrollOffset();
-    }
-
-    public boolean isFinished() {
-        return mScroller.isFinished();
-    }
-
-    public void forceFinished() {
-        mScroller.forceFinished(true);
-    }
-
-    public int getPosition() {
-        return mScroller.getCurrX();
-    }
-
-    public float getCurrVelocity() {
-        return mScroller.getCurrVelocity();
-    }
-
-    public void setPosition(int position) {
-        mScroller.startScroll(
-                position, 0,    // startX, startY
-                0, 0, 0);       // dx, dy, duration
-
-        // This forces the scroller to reach the final position.
-        mScroller.abortAnimation();
-    }
-
-    public void fling(int velocity, int min, int max) {
-        int currX = getPosition();
-        mScroller.fling(
-                currX, 0,      // startX, startY
-                velocity, 0,   // velocityX, velocityY
-                min, max,      // minX, maxX
-                0, 0,          // minY, maxY
-                mOverflingEnabled ? mOverflingDistance : 0, 0);
-    }
-
-    // Returns the distance that over the scroll limit.
-    public int startScroll(int distance, int min, int max) {
-        int currPosition = mScroller.getCurrX();
-        int finalPosition = mScroller.isFinished() ? currPosition :
-                mScroller.getFinalX();
-        int newPosition = Utils.clamp(finalPosition + distance, min, max);
-        if (newPosition != currPosition) {
-            mScroller.startScroll(
-                currPosition, 0,                    // startX, startY
-                newPosition - currPosition, 0, 0);  // dx, dy, duration
-        }
-        return finalPosition + distance - newPosition;
-    }
-}
diff --git a/src/com/android/gallery3d/ui/SelectionManager.java b/src/com/android/gallery3d/ui/SelectionManager.java
deleted file mode 100644
index be6811b..0000000
--- a/src/com/android/gallery3d/ui/SelectionManager.java
+++ /dev/null
@@ -1,251 +0,0 @@
-/*
- * Copyright (C) 2010 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.gallery3d.ui;
-
-import com.android.gallery3d.app.AbstractGalleryActivity;
-import com.android.gallery3d.data.DataManager;
-import com.android.gallery3d.data.MediaItem;
-import com.android.gallery3d.data.MediaSet;
-import com.android.gallery3d.data.Path;
-
-import java.util.ArrayList;
-import java.util.HashSet;
-import java.util.Set;
-
-public class SelectionManager {
-    @SuppressWarnings("unused")
-    private static final String TAG = "SelectionManager";
-
-    public static final int ENTER_SELECTION_MODE = 1;
-    public static final int LEAVE_SELECTION_MODE = 2;
-    public static final int SELECT_ALL_MODE = 3;
-
-    private Set<Path> mClickedSet;
-    private MediaSet mSourceMediaSet;
-    private SelectionListener mListener;
-    private DataManager mDataManager;
-    private boolean mInverseSelection;
-    private boolean mIsAlbumSet;
-    private boolean mInSelectionMode;
-    private boolean mAutoLeave = true;
-    private int mTotal;
-
-    public interface SelectionListener {
-        public void onSelectionModeChange(int mode);
-        public void onSelectionChange(Path path, boolean selected);
-    }
-
-    public SelectionManager(AbstractGalleryActivity activity, boolean isAlbumSet) {
-        mDataManager = activity.getDataManager();
-        mClickedSet = new HashSet<Path>();
-        mIsAlbumSet = isAlbumSet;
-        mTotal = -1;
-    }
-
-    // Whether we will leave selection mode automatically once the number of
-    // selected items is down to zero.
-    public void setAutoLeaveSelectionMode(boolean enable) {
-        mAutoLeave = enable;
-    }
-
-    public void setSelectionListener(SelectionListener listener) {
-        mListener = listener;
-    }
-
-    public void selectAll() {
-        mInverseSelection = true;
-        mClickedSet.clear();
-        enterSelectionMode();
-        if (mListener != null) mListener.onSelectionModeChange(SELECT_ALL_MODE);
-    }
-
-    public void deSelectAll() {
-        leaveSelectionMode();
-        mInverseSelection = false;
-        mClickedSet.clear();
-    }
-
-    public boolean inSelectAllMode() {
-        return mInverseSelection;
-    }
-
-    public boolean inSelectionMode() {
-        return mInSelectionMode;
-    }
-
-    public void enterSelectionMode() {
-        if (mInSelectionMode) return;
-
-        mInSelectionMode = true;
-        if (mListener != null) mListener.onSelectionModeChange(ENTER_SELECTION_MODE);
-    }
-
-    public void leaveSelectionMode() {
-        if (!mInSelectionMode) return;
-
-        mInSelectionMode = false;
-        mInverseSelection = false;
-        mClickedSet.clear();
-        if (mListener != null) mListener.onSelectionModeChange(LEAVE_SELECTION_MODE);
-    }
-
-    public boolean isItemSelected(Path itemId) {
-        return mInverseSelection ^ mClickedSet.contains(itemId);
-    }
-
-    private int getTotalCount() {
-        if (mSourceMediaSet == null) return -1;
-
-        if (mTotal < 0) {
-            mTotal = mIsAlbumSet
-                    ? mSourceMediaSet.getSubMediaSetCount()
-                    : mSourceMediaSet.getMediaItemCount();
-        }
-        return mTotal;
-    }
-
-    public int getSelectedCount() {
-        int count = mClickedSet.size();
-        if (mInverseSelection) {
-            count = getTotalCount() - count;
-        }
-        return count;
-    }
-
-    public void toggle(Path path) {
-        if (mClickedSet.contains(path)) {
-            mClickedSet.remove(path);
-        } else {
-            enterSelectionMode();
-            mClickedSet.add(path);
-        }
-
-        // Convert to inverse selection mode if everything is selected.
-        int count = getSelectedCount();
-        if (count == getTotalCount()) {
-            selectAll();
-        }
-
-        if (mListener != null) mListener.onSelectionChange(path, isItemSelected(path));
-        if (count == 0 && mAutoLeave) {
-            leaveSelectionMode();
-        }
-    }
-
-    private static boolean expandMediaSet(ArrayList<Path> items, MediaSet set, int maxSelection) {
-        int subCount = set.getSubMediaSetCount();
-        for (int i = 0; i < subCount; i++) {
-            if (!expandMediaSet(items, set.getSubMediaSet(i), maxSelection)) {
-                return false;
-            }
-        }
-        int total = set.getMediaItemCount();
-        int batch = 50;
-        int index = 0;
-
-        while (index < total) {
-            int count = index + batch < total
-                    ? batch
-                    : total - index;
-            ArrayList<MediaItem> list = set.getMediaItem(index, count);
-            if (list != null
-                    && list.size() > (maxSelection - items.size())) {
-                return false;
-            }
-            for (MediaItem item : list) {
-                items.add(item.getPath());
-            }
-            index += batch;
-        }
-        return true;
-    }
-
-    public ArrayList<Path> getSelected(boolean expandSet) {
-        return getSelected(expandSet, Integer.MAX_VALUE);
-    }
-
-    public ArrayList<Path> getSelected(boolean expandSet, int maxSelection) {
-        ArrayList<Path> selected = new ArrayList<Path>();
-        if (mIsAlbumSet) {
-            if (mInverseSelection) {
-                int total = getTotalCount();
-                for (int i = 0; i < total; i++) {
-                    MediaSet set = mSourceMediaSet.getSubMediaSet(i);
-                    Path id = set.getPath();
-                    if (!mClickedSet.contains(id)) {
-                        if (expandSet) {
-                            if (!expandMediaSet(selected, set, maxSelection)) {
-                                return null;
-                            }
-                        } else {
-                            selected.add(id);
-                            if (selected.size() > maxSelection) {
-                                return null;
-                            }
-                        }
-                    }
-                }
-            } else {
-                for (Path id : mClickedSet) {
-                    if (expandSet) {
-                        if (!expandMediaSet(selected, mDataManager.getMediaSet(id),
-                                maxSelection)) {
-                            return null;
-                        }
-                    } else {
-                        selected.add(id);
-                        if (selected.size() > maxSelection) {
-                            return null;
-                        }
-                    }
-                }
-            }
-        } else {
-            if (mInverseSelection) {
-                int total = getTotalCount();
-                int index = 0;
-                while (index < total) {
-                    int count = Math.min(total - index, MediaSet.MEDIAITEM_BATCH_FETCH_COUNT);
-                    ArrayList<MediaItem> list = mSourceMediaSet.getMediaItem(index, count);
-                    for (MediaItem item : list) {
-                        Path id = item.getPath();
-                        if (!mClickedSet.contains(id)) {
-                            selected.add(id);
-                            if (selected.size() > maxSelection) {
-                                return null;
-                            }
-                        }
-                    }
-                    index += count;
-                }
-            } else {
-                for (Path id : mClickedSet) {
-                    selected.add(id);
-                    if (selected.size() > maxSelection) {
-                        return null;
-                    }
-                }
-            }
-        }
-        return selected;
-    }
-
-    public void setSourceMediaSet(MediaSet set) {
-        mSourceMediaSet = set;
-        mTotal = -1;
-    }
-}
diff --git a/src/com/android/gallery3d/ui/SelectionMenu.java b/src/com/android/gallery3d/ui/SelectionMenu.java
deleted file mode 100644
index 5b08283..0000000
--- a/src/com/android/gallery3d/ui/SelectionMenu.java
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Copyright (C) 2010 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.gallery3d.ui;
-
-import android.content.Context;
-import android.view.View;
-import android.view.View.OnClickListener;
-import android.widget.Button;
-
-import com.android.gallery3d.R;
-import com.android.gallery3d.ui.PopupList.OnPopupItemClickListener;
-
-public class SelectionMenu implements OnClickListener {
-    @SuppressWarnings("unused")
-    private static final String TAG = "SelectionMenu";
-
-    private final Context mContext;
-    private final Button mButton;
-    private final PopupList mPopupList;
-
-    public SelectionMenu(Context context, Button button, OnPopupItemClickListener listener) {
-        mContext = context;
-        mButton = button;
-        mPopupList = new PopupList(context, mButton);
-        mPopupList.addItem(R.id.action_select_all,
-                context.getString(R.string.select_all));
-        mPopupList.setOnPopupItemClickListener(listener);
-        mButton.setOnClickListener(this);
-    }
-
-    @Override
-    public void onClick(View v) {
-        mPopupList.show();
-    }
-
-    public void updateSelectAllMode(boolean inSelectAllMode) {
-        PopupList.Item item = mPopupList.findItem(R.id.action_select_all);
-        if (item != null) {
-            item.setTitle(mContext.getString(
-                    inSelectAllMode ? R.string.deselect_all : R.string.select_all));
-        }
-    }
-
-    public void setTitle(CharSequence title) {
-        mButton.setText(title);
-    }
-}
diff --git a/src/com/android/gallery3d/ui/SlideshowView.java b/src/com/android/gallery3d/ui/SlideshowView.java
deleted file mode 100644
index 4378423..0000000
--- a/src/com/android/gallery3d/ui/SlideshowView.java
+++ /dev/null
@@ -1,163 +0,0 @@
-/*
- * Copyright (C) 2010 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.gallery3d.ui;
-
-import android.graphics.Bitmap;
-import android.graphics.PointF;
-
-import com.android.gallery3d.anim.CanvasAnimation;
-import com.android.gallery3d.anim.FloatAnimation;
-import com.android.gallery3d.glrenderer.BitmapTexture;
-import com.android.gallery3d.glrenderer.GLCanvas;
-
-import java.util.Random;
-
-public class SlideshowView extends GLView {
-    @SuppressWarnings("unused")
-    private static final String TAG = "SlideshowView";
-
-    private static final int SLIDESHOW_DURATION = 3500;
-    private static final int TRANSITION_DURATION = 1000;
-
-    private static final float SCALE_SPEED = 0.20f ;
-    private static final float MOVE_SPEED = SCALE_SPEED;
-
-    private int mCurrentRotation;
-    private BitmapTexture mCurrentTexture;
-    private SlideshowAnimation mCurrentAnimation;
-
-    private int mPrevRotation;
-    private BitmapTexture mPrevTexture;
-    private SlideshowAnimation mPrevAnimation;
-
-    private final FloatAnimation mTransitionAnimation =
-            new FloatAnimation(0, 1, TRANSITION_DURATION);
-
-    private Random mRandom = new Random();
-
-    public void next(Bitmap bitmap, int rotation) {
-
-        mTransitionAnimation.start();
-
-        if (mPrevTexture != null) {
-            mPrevTexture.getBitmap().recycle();
-            mPrevTexture.recycle();
-        }
-
-        mPrevTexture = mCurrentTexture;
-        mPrevAnimation = mCurrentAnimation;
-        mPrevRotation = mCurrentRotation;
-
-        mCurrentRotation = rotation;
-        mCurrentTexture = new BitmapTexture(bitmap);
-        if (((rotation / 90) & 0x01) == 0) {
-            mCurrentAnimation = new SlideshowAnimation(
-                    mCurrentTexture.getWidth(), mCurrentTexture.getHeight(),
-                    mRandom);
-        } else {
-            mCurrentAnimation = new SlideshowAnimation(
-                    mCurrentTexture.getHeight(), mCurrentTexture.getWidth(),
-                    mRandom);
-        }
-        mCurrentAnimation.start();
-
-        invalidate();
-    }
-
-    public void release() {
-        if (mPrevTexture != null) {
-            mPrevTexture.recycle();
-            mPrevTexture = null;
-        }
-        if (mCurrentTexture != null) {
-            mCurrentTexture.recycle();
-            mCurrentTexture = null;
-        }
-    }
-
-    @Override
-    protected void render(GLCanvas canvas) {
-        long animTime = AnimationTime.get();
-        boolean requestRender = mTransitionAnimation.calculate(animTime);
-        float alpha = mPrevTexture == null ? 1f : mTransitionAnimation.get();
-
-        if (mPrevTexture != null && alpha != 1f) {
-            requestRender |= mPrevAnimation.calculate(animTime);
-            canvas.save(GLCanvas.SAVE_FLAG_ALPHA | GLCanvas.SAVE_FLAG_MATRIX);
-            canvas.setAlpha(1f - alpha);
-            mPrevAnimation.apply(canvas);
-            canvas.rotate(mPrevRotation, 0, 0, 1);
-            mPrevTexture.draw(canvas, -mPrevTexture.getWidth() / 2,
-                    -mPrevTexture.getHeight() / 2);
-            canvas.restore();
-        }
-        if (mCurrentTexture != null) {
-            requestRender |= mCurrentAnimation.calculate(animTime);
-            canvas.save(GLCanvas.SAVE_FLAG_ALPHA | GLCanvas.SAVE_FLAG_MATRIX);
-            canvas.setAlpha(alpha);
-            mCurrentAnimation.apply(canvas);
-            canvas.rotate(mCurrentRotation, 0, 0, 1);
-            mCurrentTexture.draw(canvas, -mCurrentTexture.getWidth() / 2,
-                    -mCurrentTexture.getHeight() / 2);
-            canvas.restore();
-        }
-        if (requestRender) invalidate();
-    }
-
-    private class SlideshowAnimation extends CanvasAnimation {
-        private final int mWidth;
-        private final int mHeight;
-
-        private final PointF mMovingVector;
-        private float mProgress;
-
-        public SlideshowAnimation(int width, int height, Random random) {
-            mWidth = width;
-            mHeight = height;
-            mMovingVector = new PointF(
-                    MOVE_SPEED * mWidth * (random.nextFloat() - 0.5f),
-                    MOVE_SPEED * mHeight * (random.nextFloat() - 0.5f));
-            setDuration(SLIDESHOW_DURATION);
-        }
-
-        @Override
-        public void apply(GLCanvas canvas) {
-            int viewWidth = getWidth();
-            int viewHeight = getHeight();
-
-            float initScale = Math.min((float)
-                    viewWidth / mWidth, (float) viewHeight / mHeight);
-            float scale = initScale * (1 + SCALE_SPEED * mProgress);
-
-            float centerX = viewWidth / 2 + mMovingVector.x * mProgress;
-            float centerY = viewHeight / 2 + mMovingVector.y * mProgress;
-
-            canvas.translate(centerX, centerY);
-            canvas.scale(scale, scale, 0);
-        }
-
-        @Override
-        public int getCanvasSaveFlags() {
-            return GLCanvas.SAVE_FLAG_MATRIX;
-        }
-
-        @Override
-        protected void onCalculate(float progress) {
-            mProgress = progress;
-        }
-    }
-}
diff --git a/src/com/android/gallery3d/ui/SlotView.java b/src/com/android/gallery3d/ui/SlotView.java
deleted file mode 100644
index bd0ffdc..0000000
--- a/src/com/android/gallery3d/ui/SlotView.java
+++ /dev/null
@@ -1,788 +0,0 @@
-/*
- * Copyright (C) 2010 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.gallery3d.ui;
-
-import android.graphics.Rect;
-import android.os.Handler;
-import android.view.GestureDetector;
-import android.view.MotionEvent;
-import android.view.animation.DecelerateInterpolator;
-
-import com.android.gallery3d.anim.Animation;
-import com.android.gallery3d.app.AbstractGalleryActivity;
-import com.android.gallery3d.common.Utils;
-import com.android.gallery3d.glrenderer.GLCanvas;
-
-public class SlotView extends GLView {
-    @SuppressWarnings("unused")
-    private static final String TAG = "SlotView";
-
-    private static final boolean WIDE = true;
-    private static final int INDEX_NONE = -1;
-
-    public static final int RENDER_MORE_PASS = 1;
-    public static final int RENDER_MORE_FRAME = 2;
-
-    public interface Listener {
-        public void onDown(int index);
-        public void onUp(boolean followedByLongPress);
-        public void onSingleTapUp(int index);
-        public void onLongTap(int index);
-        public void onScrollPositionChanged(int position, int total);
-    }
-
-    public static class SimpleListener implements Listener {
-        @Override public void onDown(int index) {}
-        @Override public void onUp(boolean followedByLongPress) {}
-        @Override public void onSingleTapUp(int index) {}
-        @Override public void onLongTap(int index) {}
-        @Override public void onScrollPositionChanged(int position, int total) {}
-    }
-
-    public static interface SlotRenderer {
-        public void prepareDrawing();
-        public void onVisibleRangeChanged(int visibleStart, int visibleEnd);
-        public void onSlotSizeChanged(int width, int height);
-        public int renderSlot(GLCanvas canvas, int index, int pass, int width, int height);
-    }
-
-    private final GestureDetector mGestureDetector;
-    private final ScrollerHelper mScroller;
-    private final Paper mPaper = new Paper();
-
-    private Listener mListener;
-    private UserInteractionListener mUIListener;
-
-    private boolean mMoreAnimation = false;
-    private SlotAnimation mAnimation = null;
-    private final Layout mLayout = new Layout();
-    private int mStartIndex = INDEX_NONE;
-
-    // whether the down action happened while the view is scrolling.
-    private boolean mDownInScrolling;
-    private int mOverscrollEffect = OVERSCROLL_3D;
-    private final Handler mHandler;
-
-    private SlotRenderer mRenderer;
-
-    private int[] mRequestRenderSlots = new int[16];
-
-    public static final int OVERSCROLL_3D = 0;
-    public static final int OVERSCROLL_SYSTEM = 1;
-    public static final int OVERSCROLL_NONE = 2;
-
-    // to prevent allocating memory
-    private final Rect mTempRect = new Rect();
-
-    public SlotView(AbstractGalleryActivity activity, Spec spec) {
-        mGestureDetector = new GestureDetector(activity, new MyGestureListener());
-        mScroller = new ScrollerHelper(activity);
-        mHandler = new SynchronizedHandler(activity.getGLRoot());
-        setSlotSpec(spec);
-    }
-
-    public void setSlotRenderer(SlotRenderer slotDrawer) {
-        mRenderer = slotDrawer;
-        if (mRenderer != null) {
-            mRenderer.onSlotSizeChanged(mLayout.mSlotWidth, mLayout.mSlotHeight);
-            mRenderer.onVisibleRangeChanged(getVisibleStart(), getVisibleEnd());
-        }
-    }
-
-    public void setCenterIndex(int index) {
-        int slotCount = mLayout.mSlotCount;
-        if (index < 0 || index >= slotCount) {
-            return;
-        }
-        Rect rect = mLayout.getSlotRect(index, mTempRect);
-        int position = WIDE
-                ? (rect.left + rect.right - getWidth()) / 2
-                : (rect.top + rect.bottom - getHeight()) / 2;
-        setScrollPosition(position);
-    }
-
-    public void makeSlotVisible(int index) {
-        Rect rect = mLayout.getSlotRect(index, mTempRect);
-        int visibleBegin = WIDE ? mScrollX : mScrollY;
-        int visibleLength = WIDE ? getWidth() : getHeight();
-        int visibleEnd = visibleBegin + visibleLength;
-        int slotBegin = WIDE ? rect.left : rect.top;
-        int slotEnd = WIDE ? rect.right : rect.bottom;
-
-        int position = visibleBegin;
-        if (visibleLength < slotEnd - slotBegin) {
-            position = visibleBegin;
-        } else if (slotBegin < visibleBegin) {
-            position = slotBegin;
-        } else if (slotEnd > visibleEnd) {
-            position = slotEnd - visibleLength;
-        }
-
-        setScrollPosition(position);
-    }
-
-    public void setScrollPosition(int position) {
-        position = Utils.clamp(position, 0, mLayout.getScrollLimit());
-        mScroller.setPosition(position);
-        updateScrollPosition(position, false);
-    }
-
-    public void setSlotSpec(Spec spec) {
-        mLayout.setSlotSpec(spec);
-    }
-
-    @Override
-    public void addComponent(GLView view) {
-        throw new UnsupportedOperationException();
-    }
-
-    @Override
-    protected void onLayout(boolean changeSize, int l, int t, int r, int b) {
-        if (!changeSize) return;
-
-        // Make sure we are still at a resonable scroll position after the size
-        // is changed (like orientation change). We choose to keep the center
-        // visible slot still visible. This is arbitrary but reasonable.
-        int visibleIndex =
-                (mLayout.getVisibleStart() + mLayout.getVisibleEnd()) / 2;
-        mLayout.setSize(r - l, b - t);
-        makeSlotVisible(visibleIndex);
-        if (mOverscrollEffect == OVERSCROLL_3D) {
-            mPaper.setSize(r - l, b - t);
-        }
-    }
-
-    public void startScatteringAnimation(RelativePosition position) {
-        mAnimation = new ScatteringAnimation(position);
-        mAnimation.start();
-        if (mLayout.mSlotCount != 0) invalidate();
-    }
-
-    public void startRisingAnimation() {
-        mAnimation = new RisingAnimation();
-        mAnimation.start();
-        if (mLayout.mSlotCount != 0) invalidate();
-    }
-
-    private void updateScrollPosition(int position, boolean force) {
-        if (!force && (WIDE ? position == mScrollX : position == mScrollY)) return;
-        if (WIDE) {
-            mScrollX = position;
-        } else {
-            mScrollY = position;
-        }
-        mLayout.setScrollPosition(position);
-        onScrollPositionChanged(position);
-    }
-
-    protected void onScrollPositionChanged(int newPosition) {
-        int limit = mLayout.getScrollLimit();
-        mListener.onScrollPositionChanged(newPosition, limit);
-    }
-
-    public Rect getSlotRect(int slotIndex) {
-        return mLayout.getSlotRect(slotIndex, new Rect());
-    }
-
-    @Override
-    protected boolean onTouch(MotionEvent event) {
-        if (mUIListener != null) mUIListener.onUserInteraction();
-        mGestureDetector.onTouchEvent(event);
-        switch (event.getAction()) {
-            case MotionEvent.ACTION_DOWN:
-                mDownInScrolling = !mScroller.isFinished();
-                mScroller.forceFinished();
-                break;
-            case MotionEvent.ACTION_UP:
-                mPaper.onRelease();
-                invalidate();
-                break;
-        }
-        return true;
-    }
-
-    public void setListener(Listener listener) {
-        mListener = listener;
-    }
-
-    public void setUserInteractionListener(UserInteractionListener listener) {
-        mUIListener = listener;
-    }
-
-    public void setOverscrollEffect(int kind) {
-        mOverscrollEffect = kind;
-        mScroller.setOverfling(kind == OVERSCROLL_SYSTEM);
-    }
-
-    private static int[] expandIntArray(int array[], int capacity) {
-        while (array.length < capacity) {
-            array = new int[array.length * 2];
-        }
-        return array;
-    }
-
-    @Override
-    protected void render(GLCanvas canvas) {
-        super.render(canvas);
-
-        if (mRenderer == null) return;
-        mRenderer.prepareDrawing();
-
-        long animTime = AnimationTime.get();
-        boolean more = mScroller.advanceAnimation(animTime);
-        more |= mLayout.advanceAnimation(animTime);
-        int oldX = mScrollX;
-        updateScrollPosition(mScroller.getPosition(), false);
-
-        boolean paperActive = false;
-        if (mOverscrollEffect == OVERSCROLL_3D) {
-            // Check if an edge is reached and notify mPaper if so.
-            int newX = mScrollX;
-            int limit = mLayout.getScrollLimit();
-            if (oldX > 0 && newX == 0 || oldX < limit && newX == limit) {
-                float v = mScroller.getCurrVelocity();
-                if (newX == limit) v = -v;
-
-                // I don't know why, but getCurrVelocity() can return NaN.
-                if (!Float.isNaN(v)) {
-                    mPaper.edgeReached(v);
-                }
-            }
-            paperActive = mPaper.advanceAnimation();
-        }
-
-        more |= paperActive;
-
-        if (mAnimation != null) {
-            more |= mAnimation.calculate(animTime);
-        }
-
-        canvas.translate(-mScrollX, -mScrollY);
-
-        int requestCount = 0;
-        int requestedSlot[] = expandIntArray(mRequestRenderSlots,
-                mLayout.mVisibleEnd - mLayout.mVisibleStart);
-
-        for (int i = mLayout.mVisibleEnd - 1; i >= mLayout.mVisibleStart; --i) {
-            int r = renderItem(canvas, i, 0, paperActive);
-            if ((r & RENDER_MORE_FRAME) != 0) more = true;
-            if ((r & RENDER_MORE_PASS) != 0) requestedSlot[requestCount++] = i;
-        }
-
-        for (int pass = 1; requestCount != 0; ++pass) {
-            int newCount = 0;
-            for (int i = 0; i < requestCount; ++i) {
-                int r = renderItem(canvas,
-                        requestedSlot[i], pass, paperActive);
-                if ((r & RENDER_MORE_FRAME) != 0) more = true;
-                if ((r & RENDER_MORE_PASS) != 0) requestedSlot[newCount++] = i;
-            }
-            requestCount = newCount;
-        }
-
-        canvas.translate(mScrollX, mScrollY);
-
-        if (more) invalidate();
-
-        final UserInteractionListener listener = mUIListener;
-        if (mMoreAnimation && !more && listener != null) {
-            mHandler.post(new Runnable() {
-                @Override
-                public void run() {
-                    listener.onUserInteractionEnd();
-                }
-            });
-        }
-        mMoreAnimation = more;
-    }
-
-    private int renderItem(
-            GLCanvas canvas, int index, int pass, boolean paperActive) {
-        canvas.save(GLCanvas.SAVE_FLAG_ALPHA | GLCanvas.SAVE_FLAG_MATRIX);
-        Rect rect = mLayout.getSlotRect(index, mTempRect);
-        if (paperActive) {
-            canvas.multiplyMatrix(mPaper.getTransform(rect, mScrollX), 0);
-        } else {
-            canvas.translate(rect.left, rect.top, 0);
-        }
-        if (mAnimation != null && mAnimation.isActive()) {
-            mAnimation.apply(canvas, index, rect);
-        }
-        int result = mRenderer.renderSlot(
-                canvas, index, pass, rect.right - rect.left, rect.bottom - rect.top);
-        canvas.restore();
-        return result;
-    }
-
-    public static abstract class SlotAnimation extends Animation {
-        protected float mProgress = 0;
-
-        public SlotAnimation() {
-            setInterpolator(new DecelerateInterpolator(4));
-            setDuration(1500);
-        }
-
-        @Override
-        protected void onCalculate(float progress) {
-            mProgress = progress;
-        }
-
-        abstract public void apply(GLCanvas canvas, int slotIndex, Rect target);
-    }
-
-    public static class RisingAnimation extends SlotAnimation {
-        private static final int RISING_DISTANCE = 128;
-
-        @Override
-        public void apply(GLCanvas canvas, int slotIndex, Rect target) {
-            canvas.translate(0, 0, RISING_DISTANCE * (1 - mProgress));
-        }
-    }
-
-    public static class ScatteringAnimation extends SlotAnimation {
-        private int PHOTO_DISTANCE = 1000;
-        private RelativePosition mCenter;
-
-        public ScatteringAnimation(RelativePosition center) {
-            mCenter = center;
-        }
-
-        @Override
-        public void apply(GLCanvas canvas, int slotIndex, Rect target) {
-            canvas.translate(
-                    (mCenter.getX() - target.centerX()) * (1 - mProgress),
-                    (mCenter.getY() - target.centerY()) * (1 - mProgress),
-                    slotIndex * PHOTO_DISTANCE * (1 - mProgress));
-            canvas.setAlpha(mProgress);
-        }
-    }
-
-    // This Spec class is used to specify the size of each slot in the SlotView.
-    // There are two ways to do it:
-    //
-    // (1) Specify slotWidth and slotHeight: they specify the width and height
-    //     of each slot. The number of rows and the gap between slots will be
-    //     determined automatically.
-    // (2) Specify rowsLand, rowsPort, and slotGap: they specify the number
-    //     of rows in landscape/portrait mode and the gap between slots. The
-    //     width and height of each slot is determined automatically.
-    //
-    // The initial value of -1 means they are not specified.
-    public static class Spec {
-        public int slotWidth = -1;
-        public int slotHeight = -1;
-        public int slotHeightAdditional = 0;
-
-        public int rowsLand = -1;
-        public int rowsPort = -1;
-        public int slotGap = -1;
-    }
-
-    public class Layout {
-
-        private int mVisibleStart;
-        private int mVisibleEnd;
-
-        private int mSlotCount;
-        private int mSlotWidth;
-        private int mSlotHeight;
-        private int mSlotGap;
-
-        private Spec mSpec;
-
-        private int mWidth;
-        private int mHeight;
-
-        private int mUnitCount;
-        private int mContentLength;
-        private int mScrollPosition;
-
-        private IntegerAnimation mVerticalPadding = new IntegerAnimation();
-        private IntegerAnimation mHorizontalPadding = new IntegerAnimation();
-
-        public void setSlotSpec(Spec spec) {
-            mSpec = spec;
-        }
-
-        public boolean setSlotCount(int slotCount) {
-            if (slotCount == mSlotCount) return false;
-            if (mSlotCount != 0) {
-                mHorizontalPadding.setEnabled(true);
-                mVerticalPadding.setEnabled(true);
-            }
-            mSlotCount = slotCount;
-            int hPadding = mHorizontalPadding.getTarget();
-            int vPadding = mVerticalPadding.getTarget();
-            initLayoutParameters();
-            return vPadding != mVerticalPadding.getTarget()
-                    || hPadding != mHorizontalPadding.getTarget();
-        }
-
-        public Rect getSlotRect(int index, Rect rect) {
-            int col, row;
-            if (WIDE) {
-                col = index / mUnitCount;
-                row = index - col * mUnitCount;
-            } else {
-                row = index / mUnitCount;
-                col = index - row * mUnitCount;
-            }
-
-            int x = mHorizontalPadding.get() + col * (mSlotWidth + mSlotGap);
-            int y = mVerticalPadding.get() + row * (mSlotHeight + mSlotGap);
-            rect.set(x, y, x + mSlotWidth, y + mSlotHeight);
-            return rect;
-        }
-
-        public int getSlotWidth() {
-            return mSlotWidth;
-        }
-
-        public int getSlotHeight() {
-            return mSlotHeight;
-        }
-
-        // Calculate
-        // (1) mUnitCount: the number of slots we can fit into one column (or row).
-        // (2) mContentLength: the width (or height) we need to display all the
-        //     columns (rows).
-        // (3) padding[]: the vertical and horizontal padding we need in order
-        //     to put the slots towards to the center of the display.
-        //
-        // The "major" direction is the direction the user can scroll. The other
-        // direction is the "minor" direction.
-        //
-        // The comments inside this method are the description when the major
-        // directon is horizontal (X), and the minor directon is vertical (Y).
-        private void initLayoutParameters(
-                int majorLength, int minorLength,  /* The view width and height */
-                int majorUnitSize, int minorUnitSize,  /* The slot width and height */
-                int[] padding) {
-            int unitCount = (minorLength + mSlotGap) / (minorUnitSize + mSlotGap);
-            if (unitCount == 0) unitCount = 1;
-            mUnitCount = unitCount;
-
-            // We put extra padding above and below the column.
-            int availableUnits = Math.min(mUnitCount, mSlotCount);
-            int usedMinorLength = availableUnits * minorUnitSize +
-                    (availableUnits - 1) * mSlotGap;
-            padding[0] = (minorLength - usedMinorLength) / 2;
-
-            // Then calculate how many columns we need for all slots.
-            int count = ((mSlotCount + mUnitCount - 1) / mUnitCount);
-            mContentLength = count * majorUnitSize + (count - 1) * mSlotGap;
-
-            // If the content length is less then the screen width, put
-            // extra padding in left and right.
-            padding[1] = Math.max(0, (majorLength - mContentLength) / 2);
-        }
-
-        private void initLayoutParameters() {
-            // Initialize mSlotWidth and mSlotHeight from mSpec
-            if (mSpec.slotWidth != -1) {
-                mSlotGap = 0;
-                mSlotWidth = mSpec.slotWidth;
-                mSlotHeight = mSpec.slotHeight;
-            } else {
-                int rows = (mWidth > mHeight) ? mSpec.rowsLand : mSpec.rowsPort;
-                mSlotGap = mSpec.slotGap;
-                mSlotHeight = Math.max(1, (mHeight - (rows - 1) * mSlotGap) / rows);
-                mSlotWidth = mSlotHeight - mSpec.slotHeightAdditional;
-            }
-
-            if (mRenderer != null) {
-                mRenderer.onSlotSizeChanged(mSlotWidth, mSlotHeight);
-            }
-
-            int[] padding = new int[2];
-            if (WIDE) {
-                initLayoutParameters(mWidth, mHeight, mSlotWidth, mSlotHeight, padding);
-                mVerticalPadding.startAnimateTo(padding[0]);
-                mHorizontalPadding.startAnimateTo(padding[1]);
-            } else {
-                initLayoutParameters(mHeight, mWidth, mSlotHeight, mSlotWidth, padding);
-                mVerticalPadding.startAnimateTo(padding[1]);
-                mHorizontalPadding.startAnimateTo(padding[0]);
-            }
-            updateVisibleSlotRange();
-        }
-
-        public void setSize(int width, int height) {
-            mWidth = width;
-            mHeight = height;
-            initLayoutParameters();
-        }
-
-        private void updateVisibleSlotRange() {
-            int position = mScrollPosition;
-
-            if (WIDE) {
-                int startCol = position / (mSlotWidth + mSlotGap);
-                int start = Math.max(0, mUnitCount * startCol);
-                int endCol = (position + mWidth + mSlotWidth + mSlotGap - 1) /
-                        (mSlotWidth + mSlotGap);
-                int end = Math.min(mSlotCount, mUnitCount * endCol);
-                setVisibleRange(start, end);
-            } else {
-                int startRow = position / (mSlotHeight + mSlotGap);
-                int start = Math.max(0, mUnitCount * startRow);
-                int endRow = (position + mHeight + mSlotHeight + mSlotGap - 1) /
-                        (mSlotHeight + mSlotGap);
-                int end = Math.min(mSlotCount, mUnitCount * endRow);
-                setVisibleRange(start, end);
-            }
-        }
-
-        public void setScrollPosition(int position) {
-            if (mScrollPosition == position) return;
-            mScrollPosition = position;
-            updateVisibleSlotRange();
-        }
-
-        private void setVisibleRange(int start, int end) {
-            if (start == mVisibleStart && end == mVisibleEnd) return;
-            if (start < end) {
-                mVisibleStart = start;
-                mVisibleEnd = end;
-            } else {
-                mVisibleStart = mVisibleEnd = 0;
-            }
-            if (mRenderer != null) {
-                mRenderer.onVisibleRangeChanged(mVisibleStart, mVisibleEnd);
-            }
-        }
-
-        public int getVisibleStart() {
-            return mVisibleStart;
-        }
-
-        public int getVisibleEnd() {
-            return mVisibleEnd;
-        }
-
-        public int getSlotIndexByPosition(float x, float y) {
-            int absoluteX = Math.round(x) + (WIDE ? mScrollPosition : 0);
-            int absoluteY = Math.round(y) + (WIDE ? 0 : mScrollPosition);
-
-            absoluteX -= mHorizontalPadding.get();
-            absoluteY -= mVerticalPadding.get();
-
-            if (absoluteX < 0 || absoluteY < 0) {
-                return INDEX_NONE;
-            }
-
-            int columnIdx = absoluteX / (mSlotWidth + mSlotGap);
-            int rowIdx = absoluteY / (mSlotHeight + mSlotGap);
-
-            if (!WIDE && columnIdx >= mUnitCount) {
-                return INDEX_NONE;
-            }
-
-            if (WIDE && rowIdx >= mUnitCount) {
-                return INDEX_NONE;
-            }
-
-            if (absoluteX % (mSlotWidth + mSlotGap) >= mSlotWidth) {
-                return INDEX_NONE;
-            }
-
-            if (absoluteY % (mSlotHeight + mSlotGap) >= mSlotHeight) {
-                return INDEX_NONE;
-            }
-
-            int index = WIDE
-                    ? (columnIdx * mUnitCount + rowIdx)
-                    : (rowIdx * mUnitCount + columnIdx);
-
-            return index >= mSlotCount ? INDEX_NONE : index;
-        }
-
-        public int getScrollLimit() {
-            int limit = WIDE ? mContentLength - mWidth : mContentLength - mHeight;
-            return limit <= 0 ? 0 : limit;
-        }
-
-        public boolean advanceAnimation(long animTime) {
-            // use '|' to make sure both sides will be executed
-            return mVerticalPadding.calculate(animTime) | mHorizontalPadding.calculate(animTime);
-        }
-    }
-
-    private class MyGestureListener implements GestureDetector.OnGestureListener {
-        private boolean isDown;
-
-        // We call the listener's onDown() when our onShowPress() is called and
-        // call the listener's onUp() when we receive any further event.
-        @Override
-        public void onShowPress(MotionEvent e) {
-            GLRoot root = getGLRoot();
-            root.lockRenderThread();
-            try {
-                if (isDown) return;
-                int index = mLayout.getSlotIndexByPosition(e.getX(), e.getY());
-                if (index != INDEX_NONE) {
-                    isDown = true;
-                    mListener.onDown(index);
-                }
-            } finally {
-                root.unlockRenderThread();
-            }
-        }
-
-        private void cancelDown(boolean byLongPress) {
-            if (!isDown) return;
-            isDown = false;
-            mListener.onUp(byLongPress);
-        }
-
-        @Override
-        public boolean onDown(MotionEvent e) {
-            return false;
-        }
-
-        @Override
-        public boolean onFling(MotionEvent e1,
-                MotionEvent e2, float velocityX, float velocityY) {
-            cancelDown(false);
-            int scrollLimit = mLayout.getScrollLimit();
-            if (scrollLimit == 0) return false;
-            float velocity = WIDE ? velocityX : velocityY;
-            mScroller.fling((int) -velocity, 0, scrollLimit);
-            if (mUIListener != null) mUIListener.onUserInteractionBegin();
-            invalidate();
-            return true;
-        }
-
-        @Override
-        public boolean onScroll(MotionEvent e1,
-                MotionEvent e2, float distanceX, float distanceY) {
-            cancelDown(false);
-            float distance = WIDE ? distanceX : distanceY;
-            int overDistance = mScroller.startScroll(
-                    Math.round(distance), 0, mLayout.getScrollLimit());
-            if (mOverscrollEffect == OVERSCROLL_3D && overDistance != 0) {
-                mPaper.overScroll(overDistance);
-            }
-            invalidate();
-            return true;
-        }
-
-        @Override
-        public boolean onSingleTapUp(MotionEvent e) {
-            cancelDown(false);
-            if (mDownInScrolling) return true;
-            int index = mLayout.getSlotIndexByPosition(e.getX(), e.getY());
-            if (index != INDEX_NONE) mListener.onSingleTapUp(index);
-            return true;
-        }
-
-        @Override
-        public void onLongPress(MotionEvent e) {
-            cancelDown(true);
-            if (mDownInScrolling) return;
-            lockRendering();
-            try {
-                int index = mLayout.getSlotIndexByPosition(e.getX(), e.getY());
-                if (index != INDEX_NONE) mListener.onLongTap(index);
-            } finally {
-                unlockRendering();
-            }
-        }
-    }
-
-    public void setStartIndex(int index) {
-        mStartIndex = index;
-    }
-
-    // Return true if the layout parameters have been changed
-    public boolean setSlotCount(int slotCount) {
-        boolean changed = mLayout.setSlotCount(slotCount);
-
-        // mStartIndex is applied the first time setSlotCount is called.
-        if (mStartIndex != INDEX_NONE) {
-            setCenterIndex(mStartIndex);
-            mStartIndex = INDEX_NONE;
-        }
-        // Reset the scroll position to avoid scrolling over the updated limit.
-        setScrollPosition(WIDE ? mScrollX : mScrollY);
-        return changed;
-    }
-
-    public int getVisibleStart() {
-        return mLayout.getVisibleStart();
-    }
-
-    public int getVisibleEnd() {
-        return mLayout.getVisibleEnd();
-    }
-
-    public int getScrollX() {
-        return mScrollX;
-    }
-
-    public int getScrollY() {
-        return mScrollY;
-    }
-
-    public Rect getSlotRect(int slotIndex, GLView rootPane) {
-        // Get slot rectangle relative to this root pane.
-        Rect offset = new Rect();
-        rootPane.getBoundsOf(this, offset);
-        Rect r = getSlotRect(slotIndex);
-        r.offset(offset.left - getScrollX(),
-                offset.top - getScrollY());
-        return r;
-    }
-
-    private static class IntegerAnimation extends Animation {
-        private int mTarget;
-        private int mCurrent = 0;
-        private int mFrom = 0;
-        private boolean mEnabled = false;
-
-        public void setEnabled(boolean enabled) {
-            mEnabled = enabled;
-        }
-
-        public void startAnimateTo(int target) {
-            if (!mEnabled) {
-                mTarget = mCurrent = target;
-                return;
-            }
-            if (target == mTarget) return;
-
-            mFrom = mCurrent;
-            mTarget = target;
-            setDuration(180);
-            start();
-        }
-
-        public int get() {
-            return mCurrent;
-        }
-
-        public int getTarget() {
-            return mTarget;
-        }
-
-        @Override
-        protected void onCalculate(float progress) {
-            mCurrent = Math.round(mFrom + progress * (mTarget - mFrom));
-            if (progress == 1f) mEnabled = false;
-        }
-    }
-}
diff --git a/src/com/android/gallery3d/ui/SurfaceTextureScreenNail.java b/src/com/android/gallery3d/ui/SurfaceTextureScreenNail.java
deleted file mode 100644
index 18121e6..0000000
--- a/src/com/android/gallery3d/ui/SurfaceTextureScreenNail.java
+++ /dev/null
@@ -1,142 +0,0 @@
-/*
- * 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.gallery3d.ui;
-
-import android.annotation.TargetApi;
-import android.graphics.RectF;
-import android.graphics.SurfaceTexture;
-
-import com.android.gallery3d.common.ApiHelper;
-import com.android.gallery3d.glrenderer.ExtTexture;
-import com.android.gallery3d.glrenderer.GLCanvas;
-
-@TargetApi(ApiHelper.VERSION_CODES.HONEYCOMB)
-public abstract class SurfaceTextureScreenNail implements ScreenNail,
-        SurfaceTexture.OnFrameAvailableListener {
-    @SuppressWarnings("unused")
-    private static final String TAG = "SurfaceTextureScreenNail";
-    // This constant is not available in API level before 15, but it was just an
-    // oversight.
-    private static final int GL_TEXTURE_EXTERNAL_OES = 0x8D65;
-
-    protected ExtTexture mExtTexture;
-    private SurfaceTexture mSurfaceTexture;
-    private int mWidth, mHeight;
-    private float[] mTransform = new float[16];
-    private boolean mHasTexture = false;
-
-    public SurfaceTextureScreenNail() {
-    }
-
-    public void acquireSurfaceTexture(GLCanvas canvas) {
-        mExtTexture = new ExtTexture(canvas, GL_TEXTURE_EXTERNAL_OES);
-        mExtTexture.setSize(mWidth, mHeight);
-        mSurfaceTexture = new SurfaceTexture(mExtTexture.getId());
-        setDefaultBufferSize(mSurfaceTexture, mWidth, mHeight);
-        mSurfaceTexture.setOnFrameAvailableListener(this);
-        synchronized (this) {
-            mHasTexture = true;
-        }
-    }
-
-    @TargetApi(ApiHelper.VERSION_CODES.ICE_CREAM_SANDWICH_MR1)
-    private static void setDefaultBufferSize(SurfaceTexture st, int width, int height) {
-        if (ApiHelper.HAS_SET_DEFALT_BUFFER_SIZE) {
-            st.setDefaultBufferSize(width, height);
-        }
-    }
-
-    @TargetApi(ApiHelper.VERSION_CODES.ICE_CREAM_SANDWICH)
-    private static void releaseSurfaceTexture(SurfaceTexture st) {
-        st.setOnFrameAvailableListener(null);
-        if (ApiHelper.HAS_RELEASE_SURFACE_TEXTURE) {
-            st.release();
-        }
-    }
-
-    public SurfaceTexture getSurfaceTexture() {
-        return mSurfaceTexture;
-    }
-
-    public void releaseSurfaceTexture() {
-        synchronized (this) {
-            mHasTexture = false;
-        }
-        mExtTexture.recycle();
-        mExtTexture = null;
-        releaseSurfaceTexture(mSurfaceTexture);
-        mSurfaceTexture = null;
-    }
-
-    public void setSize(int width, int height) {
-        mWidth = width;
-        mHeight = height;
-    }
-
-    public void resizeTexture() {
-        if (mExtTexture != null) {
-            mExtTexture.setSize(mWidth, mHeight);
-            setDefaultBufferSize(mSurfaceTexture, mWidth, mHeight);
-        }
-    }
-
-    @Override
-    public int getWidth() {
-        return mWidth;
-    }
-
-    @Override
-    public int getHeight() {
-        return mHeight;
-    }
-
-    @Override
-    public void draw(GLCanvas canvas, int x, int y, int width, int height) {
-        synchronized (this) {
-            if (!mHasTexture) return;
-            mSurfaceTexture.updateTexImage();
-            mSurfaceTexture.getTransformMatrix(mTransform);
-
-            // Flip vertically.
-            canvas.save(GLCanvas.SAVE_FLAG_MATRIX);
-            int cx = x + width / 2;
-            int cy = y + height / 2;
-            canvas.translate(cx, cy);
-            canvas.scale(1, -1, 1);
-            canvas.translate(-cx, -cy);
-            updateTransformMatrix(mTransform);
-            canvas.drawTexture(mExtTexture, mTransform, x, y, width, height);
-            canvas.restore();
-        }
-    }
-
-    @Override
-    public void draw(GLCanvas canvas, RectF source, RectF dest) {
-        throw new UnsupportedOperationException();
-    }
-
-    protected void updateTransformMatrix(float[] matrix) {}
-
-    @Override
-    abstract public void noDraw();
-
-    @Override
-    abstract public void recycle();
-
-    @Override
-    abstract public void onFrameAvailable(SurfaceTexture surfaceTexture);
-}
diff --git a/src/com/android/gallery3d/ui/SynchronizedHandler.java b/src/com/android/gallery3d/ui/SynchronizedHandler.java
deleted file mode 100644
index ba10357..0000000
--- a/src/com/android/gallery3d/ui/SynchronizedHandler.java
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright (C) 2010 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.gallery3d.ui;
-
-import android.os.Handler;
-import android.os.Message;
-
-import com.android.gallery3d.common.Utils;
-
-public class SynchronizedHandler extends Handler {
-
-    private final GLRoot mRoot;
-
-    public SynchronizedHandler(GLRoot root) {
-        mRoot = Utils.checkNotNull(root);
-    }
-
-    @Override
-    public void dispatchMessage(Message message) {
-        mRoot.lockRenderThread();
-        try {
-            super.dispatchMessage(message);
-        } finally {
-            mRoot.unlockRenderThread();
-        }
-    }
-}
diff --git a/src/com/android/gallery3d/ui/TileImageView.java b/src/com/android/gallery3d/ui/TileImageView.java
deleted file mode 100644
index 3185c75..0000000
--- a/src/com/android/gallery3d/ui/TileImageView.java
+++ /dev/null
@@ -1,786 +0,0 @@
-/*
- * Copyright (C) 2010 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.gallery3d.ui;
-
-import android.content.Context;
-import android.graphics.Bitmap;
-import android.graphics.Point;
-import android.graphics.Rect;
-import android.graphics.RectF;
-import android.support.v4.util.LongSparseArray;
-import android.util.DisplayMetrics;
-import android.util.FloatMath;
-import android.view.WindowManager;
-
-import com.android.gallery3d.app.GalleryContext;
-import com.android.gallery3d.common.Utils;
-import com.android.gallery3d.data.DecodeUtils;
-import com.android.photos.data.GalleryBitmapPool;
-import com.android.gallery3d.glrenderer.GLCanvas;
-import com.android.gallery3d.glrenderer.UploadedTexture;
-import com.android.gallery3d.util.Future;
-import com.android.gallery3d.util.ThreadPool;
-import com.android.gallery3d.util.ThreadPool.CancelListener;
-import com.android.gallery3d.util.ThreadPool.JobContext;
-
-import java.util.concurrent.atomic.AtomicBoolean;
-
-public class TileImageView extends GLView {
-    public static final int SIZE_UNKNOWN = -1;
-
-    @SuppressWarnings("unused")
-    private static final String TAG = "TileImageView";
-    private static final int UPLOAD_LIMIT = 1;
-
-    // TILE_SIZE must be 2^N
-    private static int sTileSize;
-
-    /*
-     *  This is the tile state in the CPU side.
-     *  Life of a Tile:
-     *      ACTIVATED (initial state)
-     *              --> IN_QUEUE - by queueForDecode()
-     *              --> RECYCLED - by recycleTile()
-     *      IN_QUEUE --> DECODING - by decodeTile()
-     *               --> RECYCLED - by recycleTile)
-     *      DECODING --> RECYCLING - by recycleTile()
-     *               --> DECODED  - by decodeTile()
-     *               --> DECODE_FAIL - by decodeTile()
-     *      RECYCLING --> RECYCLED - by decodeTile()
-     *      DECODED --> ACTIVATED - (after the decoded bitmap is uploaded)
-     *      DECODED --> RECYCLED - by recycleTile()
-     *      DECODE_FAIL -> RECYCLED - by recycleTile()
-     *      RECYCLED --> ACTIVATED - by obtainTile()
-     */
-    private static final int STATE_ACTIVATED = 0x01;
-    private static final int STATE_IN_QUEUE = 0x02;
-    private static final int STATE_DECODING = 0x04;
-    private static final int STATE_DECODED = 0x08;
-    private static final int STATE_DECODE_FAIL = 0x10;
-    private static final int STATE_RECYCLING = 0x20;
-    private static final int STATE_RECYCLED = 0x40;
-
-    private TileSource mModel;
-    private ScreenNail mScreenNail;
-    protected int mLevelCount;  // cache the value of mScaledBitmaps.length
-
-    // The mLevel variable indicates which level of bitmap we should use.
-    // Level 0 means the original full-sized bitmap, and a larger value means
-    // a smaller scaled bitmap (The width and height of each scaled bitmap is
-    // half size of the previous one). If the value is in [0, mLevelCount), we
-    // use the bitmap in mScaledBitmaps[mLevel] for display, otherwise the value
-    // is mLevelCount, and that means we use mScreenNail for display.
-    private int mLevel = 0;
-
-    // The offsets of the (left, top) of the upper-left tile to the (left, top)
-    // of the view.
-    private int mOffsetX;
-    private int mOffsetY;
-
-    private int mUploadQuota;
-    private boolean mRenderComplete;
-
-    private final RectF mSourceRect = new RectF();
-    private final RectF mTargetRect = new RectF();
-
-    private final LongSparseArray<Tile> mActiveTiles = new LongSparseArray<Tile>();
-
-    // The following three queue is guarded by TileImageView.this
-    private final TileQueue mRecycledQueue = new TileQueue();
-    private final TileQueue mUploadQueue = new TileQueue();
-    private final TileQueue mDecodeQueue = new TileQueue();
-
-    // The width and height of the full-sized bitmap
-    protected int mImageWidth = SIZE_UNKNOWN;
-    protected int mImageHeight = SIZE_UNKNOWN;
-
-    protected int mCenterX;
-    protected int mCenterY;
-    protected float mScale;
-    protected int mRotation;
-
-    // Temp variables to avoid memory allocation
-    private final Rect mTileRange = new Rect();
-    private final Rect mActiveRange[] = {new Rect(), new Rect()};
-
-    private final TileUploader mTileUploader = new TileUploader();
-    private boolean mIsTextureFreed;
-    private Future<Void> mTileDecoder;
-    private final ThreadPool mThreadPool;
-    private boolean mBackgroundTileUploaded;
-
-    public static interface TileSource {
-        public int getLevelCount();
-        public ScreenNail getScreenNail();
-        public int getImageWidth();
-        public int getImageHeight();
-
-        // The tile returned by this method can be specified this way: Assuming
-        // the image size is (width, height), first take the intersection of (0,
-        // 0) - (width, height) and (x, y) - (x + tileSize, y + tileSize). If
-        // in extending the region, we found some part of the region are outside
-        // the image, those pixels are filled with black.
-        //
-        // If level > 0, it does the same operation on a down-scaled version of
-        // the original image (down-scaled by a factor of 2^level), but (x, y)
-        // still refers to the coordinate on the original image.
-        //
-        // The method would be called in another thread.
-        public Bitmap getTile(int level, int x, int y, int tileSize);
-    }
-
-    public static boolean isHighResolution(Context context) {
-        DisplayMetrics metrics = new DisplayMetrics();
-        WindowManager wm = (WindowManager)
-                context.getSystemService(Context.WINDOW_SERVICE);
-        wm.getDefaultDisplay().getMetrics(metrics);
-        return metrics.heightPixels > 2048 ||  metrics.widthPixels > 2048;
-    }
-
-    public TileImageView(GalleryContext context) {
-        mThreadPool = context.getThreadPool();
-        mTileDecoder = mThreadPool.submit(new TileDecoder());
-        if (sTileSize == 0) {
-            if (isHighResolution(context.getAndroidContext())) {
-                sTileSize = 512 ;
-            } else {
-                sTileSize = 256;
-            }
-        }
-    }
-
-    public void setModel(TileSource model) {
-        mModel = model;
-        if (model != null) notifyModelInvalidated();
-    }
-
-    public void setScreenNail(ScreenNail s) {
-        mScreenNail = s;
-    }
-
-    public void notifyModelInvalidated() {
-        invalidateTiles();
-        if (mModel == null) {
-            mScreenNail = null;
-            mImageWidth = 0;
-            mImageHeight = 0;
-            mLevelCount = 0;
-        } else {
-            setScreenNail(mModel.getScreenNail());
-            mImageWidth = mModel.getImageWidth();
-            mImageHeight = mModel.getImageHeight();
-            mLevelCount = mModel.getLevelCount();
-        }
-        layoutTiles(mCenterX, mCenterY, mScale, mRotation);
-        invalidate();
-    }
-
-    @Override
-    protected void onLayout(
-            boolean changeSize, int left, int top, int right, int bottom) {
-        super.onLayout(changeSize, left, top, right, bottom);
-        if (changeSize) layoutTiles(mCenterX, mCenterY, mScale, mRotation);
-    }
-
-    // Prepare the tiles we want to use for display.
-    //
-    // 1. Decide the tile level we want to use for display.
-    // 2. Decide the tile levels we want to keep as texture (in addition to
-    //    the one we use for display).
-    // 3. Recycle unused tiles.
-    // 4. Activate the tiles we want.
-    private void layoutTiles(int centerX, int centerY, float scale, int rotation) {
-        // The width and height of this view.
-        int width = getWidth();
-        int height = getHeight();
-
-        // The tile levels we want to keep as texture is in the range
-        // [fromLevel, endLevel).
-        int fromLevel;
-        int endLevel;
-
-        // We want to use a texture larger than or equal to the display size.
-        mLevel = Utils.clamp(Utils.floorLog2(1f / scale), 0, mLevelCount);
-
-        // We want to keep one more tile level as texture in addition to what
-        // we use for display. So it can be faster when the scale moves to the
-        // next level. We choose a level closer to the current scale.
-        if (mLevel != mLevelCount) {
-            Rect range = mTileRange;
-            getRange(range, centerX, centerY, mLevel, scale, rotation);
-            mOffsetX = Math.round(width / 2f + (range.left - centerX) * scale);
-            mOffsetY = Math.round(height / 2f + (range.top - centerY) * scale);
-            fromLevel = scale * (1 << mLevel) > 0.75f ? mLevel - 1 : mLevel;
-        } else {
-            // Activate the tiles of the smallest two levels.
-            fromLevel = mLevel - 2;
-            mOffsetX = Math.round(width / 2f - centerX * scale);
-            mOffsetY = Math.round(height / 2f - centerY * scale);
-        }
-
-        fromLevel = Math.max(0, Math.min(fromLevel, mLevelCount - 2));
-        endLevel = Math.min(fromLevel + 2, mLevelCount);
-
-        Rect range[] = mActiveRange;
-        for (int i = fromLevel; i < endLevel; ++i) {
-            getRange(range[i - fromLevel], centerX, centerY, i, rotation);
-        }
-
-        // If rotation is transient, don't update the tile.
-        if (rotation % 90 != 0) return;
-
-        synchronized (this) {
-            mDecodeQueue.clean();
-            mUploadQueue.clean();
-            mBackgroundTileUploaded = false;
-
-            // Recycle unused tiles: if the level of the active tile is outside the
-            // range [fromLevel, endLevel) or not in the visible range.
-            int n = mActiveTiles.size();
-            for (int i = 0; i < n; i++) {
-                Tile tile = mActiveTiles.valueAt(i);
-                int level = tile.mTileLevel;
-                if (level < fromLevel || level >= endLevel
-                        || !range[level - fromLevel].contains(tile.mX, tile.mY)) {
-                    mActiveTiles.removeAt(i);
-                    i--;
-                    n--;
-                    recycleTile(tile);
-                }
-            }
-        }
-
-        for (int i = fromLevel; i < endLevel; ++i) {
-            int size = sTileSize << i;
-            Rect r = range[i - fromLevel];
-            for (int y = r.top, bottom = r.bottom; y < bottom; y += size) {
-                for (int x = r.left, right = r.right; x < right; x += size) {
-                    activateTile(x, y, i);
-                }
-            }
-        }
-        invalidate();
-    }
-
-    protected synchronized void invalidateTiles() {
-        mDecodeQueue.clean();
-        mUploadQueue.clean();
-
-        // TODO disable decoder
-        int n = mActiveTiles.size();
-        for (int i = 0; i < n; i++) {
-            Tile tile = mActiveTiles.valueAt(i);
-            recycleTile(tile);
-        }
-        mActiveTiles.clear();
-    }
-
-    private void getRange(Rect out, int cX, int cY, int level, int rotation) {
-        getRange(out, cX, cY, level, 1f / (1 << (level + 1)), rotation);
-    }
-
-    // If the bitmap is scaled by the given factor "scale", return the
-    // rectangle containing visible range. The left-top coordinate returned is
-    // aligned to the tile boundary.
-    //
-    // (cX, cY) is the point on the original bitmap which will be put in the
-    // center of the ImageViewer.
-    private void getRange(Rect out,
-            int cX, int cY, int level, float scale, int rotation) {
-
-        double radians = Math.toRadians(-rotation);
-        double w = getWidth();
-        double h = getHeight();
-
-        double cos = Math.cos(radians);
-        double sin = Math.sin(radians);
-        int width = (int) Math.ceil(Math.max(
-                Math.abs(cos * w - sin * h), Math.abs(cos * w + sin * h)));
-        int height = (int) Math.ceil(Math.max(
-                Math.abs(sin * w + cos * h), Math.abs(sin * w - cos * h)));
-
-        int left = (int) FloatMath.floor(cX - width / (2f * scale));
-        int top = (int) FloatMath.floor(cY - height / (2f * scale));
-        int right = (int) FloatMath.ceil(left + width / scale);
-        int bottom = (int) FloatMath.ceil(top + height / scale);
-
-        // align the rectangle to tile boundary
-        int size = sTileSize << level;
-        left = Math.max(0, size * (left / size));
-        top = Math.max(0, size * (top / size));
-        right = Math.min(mImageWidth, right);
-        bottom = Math.min(mImageHeight, bottom);
-
-        out.set(left, top, right, bottom);
-    }
-
-    // Calculate where the center of the image is, in the view coordinates.
-    public void getImageCenter(Point center) {
-        // The width and height of this view.
-        int viewW = getWidth();
-        int viewH = getHeight();
-
-        // The distance between the center of the view to the center of the
-        // bitmap, in bitmap units. (mCenterX and mCenterY are the bitmap
-        // coordinates correspond to the center of view)
-        int distW, distH;
-        if (mRotation % 180 == 0) {
-            distW = mImageWidth / 2 - mCenterX;
-            distH = mImageHeight / 2 - mCenterY;
-        } else {
-            distW = mImageHeight / 2 - mCenterY;
-            distH = mImageWidth / 2 - mCenterX;
-        }
-
-        // Convert to view coordinates. mScale translates from bitmap units to
-        // view units.
-        center.x = Math.round(viewW / 2f + distW * mScale);
-        center.y = Math.round(viewH / 2f + distH * mScale);
-    }
-
-    public boolean setPosition(int centerX, int centerY, float scale, int rotation) {
-        if (mCenterX == centerX && mCenterY == centerY
-                && mScale == scale && mRotation == rotation) return false;
-        mCenterX = centerX;
-        mCenterY = centerY;
-        mScale = scale;
-        mRotation = rotation;
-        layoutTiles(centerX, centerY, scale, rotation);
-        invalidate();
-        return true;
-    }
-
-    public void freeTextures() {
-        mIsTextureFreed = true;
-
-        if (mTileDecoder != null) {
-            mTileDecoder.cancel();
-            mTileDecoder.get();
-            mTileDecoder = null;
-        }
-
-        int n = mActiveTiles.size();
-        for (int i = 0; i < n; i++) {
-            Tile texture = mActiveTiles.valueAt(i);
-            texture.recycle();
-        }
-        mActiveTiles.clear();
-        mTileRange.set(0, 0, 0, 0);
-
-        synchronized (this) {
-            mUploadQueue.clean();
-            mDecodeQueue.clean();
-            Tile tile = mRecycledQueue.pop();
-            while (tile != null) {
-                tile.recycle();
-                tile = mRecycledQueue.pop();
-            }
-        }
-        setScreenNail(null);
-    }
-
-    public void prepareTextures() {
-        if (mTileDecoder == null) {
-            mTileDecoder = mThreadPool.submit(new TileDecoder());
-        }
-        if (mIsTextureFreed) {
-            layoutTiles(mCenterX, mCenterY, mScale, mRotation);
-            mIsTextureFreed = false;
-            setScreenNail(mModel == null ? null : mModel.getScreenNail());
-        }
-    }
-
-    @Override
-    protected void render(GLCanvas canvas) {
-        mUploadQuota = UPLOAD_LIMIT;
-        mRenderComplete = true;
-
-        int level = mLevel;
-        int rotation = mRotation;
-        int flags = 0;
-        if (rotation != 0) flags |= GLCanvas.SAVE_FLAG_MATRIX;
-
-        if (flags != 0) {
-            canvas.save(flags);
-            if (rotation != 0) {
-                int centerX = getWidth() / 2, centerY = getHeight() / 2;
-                canvas.translate(centerX, centerY);
-                canvas.rotate(rotation, 0, 0, 1);
-                canvas.translate(-centerX, -centerY);
-            }
-        }
-        try {
-            if (level != mLevelCount && !isScreenNailAnimating()) {
-                if (mScreenNail != null) {
-                    mScreenNail.noDraw();
-                }
-
-                int size = (sTileSize << level);
-                float length = size * mScale;
-                Rect r = mTileRange;
-
-                for (int ty = r.top, i = 0; ty < r.bottom; ty += size, i++) {
-                    float y = mOffsetY + i * length;
-                    for (int tx = r.left, j = 0; tx < r.right; tx += size, j++) {
-                        float x = mOffsetX + j * length;
-                        drawTile(canvas, tx, ty, level, x, y, length);
-                    }
-                }
-            } else if (mScreenNail != null) {
-                mScreenNail.draw(canvas, mOffsetX, mOffsetY,
-                        Math.round(mImageWidth * mScale),
-                        Math.round(mImageHeight * mScale));
-                if (isScreenNailAnimating()) {
-                    invalidate();
-                }
-            }
-        } finally {
-            if (flags != 0) canvas.restore();
-        }
-
-        if (mRenderComplete) {
-            if (!mBackgroundTileUploaded) uploadBackgroundTiles(canvas);
-        } else {
-            invalidate();
-        }
-    }
-
-    private boolean isScreenNailAnimating() {
-        return (mScreenNail instanceof TiledScreenNail)
-                && ((TiledScreenNail) mScreenNail).isAnimating();
-    }
-
-    private void uploadBackgroundTiles(GLCanvas canvas) {
-        mBackgroundTileUploaded = true;
-        int n = mActiveTiles.size();
-        for (int i = 0; i < n; i++) {
-            Tile tile = mActiveTiles.valueAt(i);
-            if (!tile.isContentValid()) queueForDecode(tile);
-        }
-    }
-
-    void queueForUpload(Tile tile) {
-        synchronized (this) {
-            mUploadQueue.push(tile);
-        }
-        if (mTileUploader.mActive.compareAndSet(false, true)) {
-            getGLRoot().addOnGLIdleListener(mTileUploader);
-        }
-    }
-
-    synchronized void queueForDecode(Tile tile) {
-        if (tile.mTileState == STATE_ACTIVATED) {
-            tile.mTileState = STATE_IN_QUEUE;
-            if (mDecodeQueue.push(tile)) notifyAll();
-        }
-    }
-
-    boolean decodeTile(Tile tile) {
-        synchronized (this) {
-            if (tile.mTileState != STATE_IN_QUEUE) return false;
-            tile.mTileState = STATE_DECODING;
-        }
-        boolean decodeComplete = tile.decode();
-        synchronized (this) {
-            if (tile.mTileState == STATE_RECYCLING) {
-                tile.mTileState = STATE_RECYCLED;
-                if (tile.mDecodedTile != null) {
-                    GalleryBitmapPool.getInstance().put(tile.mDecodedTile);
-                    tile.mDecodedTile = null;
-                }
-                mRecycledQueue.push(tile);
-                return false;
-            }
-            tile.mTileState = decodeComplete ? STATE_DECODED : STATE_DECODE_FAIL;
-            return decodeComplete;
-        }
-    }
-
-    private synchronized Tile obtainTile(int x, int y, int level) {
-        Tile tile = mRecycledQueue.pop();
-        if (tile != null) {
-            tile.mTileState = STATE_ACTIVATED;
-            tile.update(x, y, level);
-            return tile;
-        }
-        return new Tile(x, y, level);
-    }
-
-    synchronized void recycleTile(Tile tile) {
-        if (tile.mTileState == STATE_DECODING) {
-            tile.mTileState = STATE_RECYCLING;
-            return;
-        }
-        tile.mTileState = STATE_RECYCLED;
-        if (tile.mDecodedTile != null) {
-            GalleryBitmapPool.getInstance().put(tile.mDecodedTile);
-            tile.mDecodedTile = null;
-        }
-        mRecycledQueue.push(tile);
-    }
-
-    private void activateTile(int x, int y, int level) {
-        long key = makeTileKey(x, y, level);
-        Tile tile = mActiveTiles.get(key);
-        if (tile != null) {
-            if (tile.mTileState == STATE_IN_QUEUE) {
-                tile.mTileState = STATE_ACTIVATED;
-            }
-            return;
-        }
-        tile = obtainTile(x, y, level);
-        mActiveTiles.put(key, tile);
-    }
-
-    private Tile getTile(int x, int y, int level) {
-        return mActiveTiles.get(makeTileKey(x, y, level));
-    }
-
-    private static long makeTileKey(int x, int y, int level) {
-        long result = x;
-        result = (result << 16) | y;
-        result = (result << 16) | level;
-        return result;
-    }
-
-    private class TileUploader implements GLRoot.OnGLIdleListener {
-        AtomicBoolean mActive = new AtomicBoolean(false);
-
-        @Override
-        public boolean onGLIdle(GLCanvas canvas, boolean renderRequested) {
-            // Skips uploading if there is a pending rendering request.
-            // Returns true to keep uploading in next rendering loop.
-            if (renderRequested) return true;
-            int quota = UPLOAD_LIMIT;
-            Tile tile = null;
-            while (quota > 0) {
-                synchronized (TileImageView.this) {
-                    tile = mUploadQueue.pop();
-                }
-                if (tile == null) break;
-                if (!tile.isContentValid()) {
-                    boolean hasBeenLoaded = tile.isLoaded();
-                    Utils.assertTrue(tile.mTileState == STATE_DECODED);
-                    tile.updateContent(canvas);
-                    if (!hasBeenLoaded) tile.draw(canvas, 0, 0);
-                    --quota;
-                }
-            }
-            if (tile == null) mActive.set(false);
-            return tile != null;
-        }
-    }
-
-    // Draw the tile to a square at canvas that locates at (x, y) and
-    // has a side length of length.
-    public void drawTile(GLCanvas canvas,
-            int tx, int ty, int level, float x, float y, float length) {
-        RectF source = mSourceRect;
-        RectF target = mTargetRect;
-        target.set(x, y, x + length, y + length);
-        source.set(0, 0, sTileSize, sTileSize);
-
-        Tile tile = getTile(tx, ty, level);
-        if (tile != null) {
-            if (!tile.isContentValid()) {
-                if (tile.mTileState == STATE_DECODED) {
-                    if (mUploadQuota > 0) {
-                        --mUploadQuota;
-                        tile.updateContent(canvas);
-                    } else {
-                        mRenderComplete = false;
-                    }
-                } else if (tile.mTileState != STATE_DECODE_FAIL){
-                    mRenderComplete = false;
-                    queueForDecode(tile);
-                }
-            }
-            if (drawTile(tile, canvas, source, target)) return;
-        }
-        if (mScreenNail != null) {
-            int size = sTileSize << level;
-            float scaleX = (float) mScreenNail.getWidth() / mImageWidth;
-            float scaleY = (float) mScreenNail.getHeight() / mImageHeight;
-            source.set(tx * scaleX, ty * scaleY, (tx + size) * scaleX,
-                    (ty + size) * scaleY);
-            mScreenNail.draw(canvas, source, target);
-        }
-    }
-
-    static boolean drawTile(
-            Tile tile, GLCanvas canvas, RectF source, RectF target) {
-        while (true) {
-            if (tile.isContentValid()) {
-                canvas.drawTexture(tile, source, target);
-                return true;
-            }
-
-            // Parent can be divided to four quads and tile is one of the four.
-            Tile parent = tile.getParentTile();
-            if (parent == null) return false;
-            if (tile.mX == parent.mX) {
-                source.left /= 2f;
-                source.right /= 2f;
-            } else {
-                source.left = (sTileSize + source.left) / 2f;
-                source.right = (sTileSize + source.right) / 2f;
-            }
-            if (tile.mY == parent.mY) {
-                source.top /= 2f;
-                source.bottom /= 2f;
-            } else {
-                source.top = (sTileSize + source.top) / 2f;
-                source.bottom = (sTileSize + source.bottom) / 2f;
-            }
-            tile = parent;
-        }
-    }
-
-    private class Tile extends UploadedTexture {
-        public int mX;
-        public int mY;
-        public int mTileLevel;
-        public Tile mNext;
-        public Bitmap mDecodedTile;
-        public volatile int mTileState = STATE_ACTIVATED;
-
-        public Tile(int x, int y, int level) {
-            mX = x;
-            mY = y;
-            mTileLevel = level;
-        }
-
-        @Override
-        protected void onFreeBitmap(Bitmap bitmap) {
-            GalleryBitmapPool.getInstance().put(bitmap);
-        }
-
-        boolean decode() {
-            // Get a tile from the original image. The tile is down-scaled
-            // by (1 << mTilelevel) from a region in the original image.
-            try {
-                mDecodedTile = DecodeUtils.ensureGLCompatibleBitmap(mModel.getTile(
-                        mTileLevel, mX, mY, sTileSize));
-            } catch (Throwable t) {
-                Log.w(TAG, "fail to decode tile", t);
-            }
-            return mDecodedTile != null;
-        }
-
-        @Override
-        protected Bitmap onGetBitmap() {
-            Utils.assertTrue(mTileState == STATE_DECODED);
-
-            // We need to override the width and height, so that we won't
-            // draw beyond the boundaries.
-            int rightEdge = ((mImageWidth - mX) >> mTileLevel);
-            int bottomEdge = ((mImageHeight - mY) >> mTileLevel);
-            setSize(Math.min(sTileSize, rightEdge), Math.min(sTileSize, bottomEdge));
-
-            Bitmap bitmap = mDecodedTile;
-            mDecodedTile = null;
-            mTileState = STATE_ACTIVATED;
-            return bitmap;
-        }
-
-        // We override getTextureWidth() and getTextureHeight() here, so the
-        // texture can be re-used for different tiles regardless of the actual
-        // size of the tile (which may be small because it is a tile at the
-        // boundary).
-        @Override
-        public int getTextureWidth() {
-            return sTileSize;
-        }
-
-        @Override
-        public int getTextureHeight() {
-            return sTileSize;
-        }
-
-        public void update(int x, int y, int level) {
-            mX = x;
-            mY = y;
-            mTileLevel = level;
-            invalidateContent();
-        }
-
-        public Tile getParentTile() {
-            if (mTileLevel + 1 == mLevelCount) return null;
-            int size = sTileSize << (mTileLevel + 1);
-            int x = size * (mX / size);
-            int y = size * (mY / size);
-            return getTile(x, y, mTileLevel + 1);
-        }
-
-        @Override
-        public String toString() {
-            return String.format("tile(%s, %s, %s / %s)",
-                    mX / sTileSize, mY / sTileSize, mLevel, mLevelCount);
-        }
-    }
-
-    private static class TileQueue {
-        private Tile mHead;
-
-        public Tile pop() {
-            Tile tile = mHead;
-            if (tile != null) mHead = tile.mNext;
-            return tile;
-        }
-
-        public boolean push(Tile tile) {
-            boolean wasEmpty = mHead == null;
-            tile.mNext = mHead;
-            mHead = tile;
-            return wasEmpty;
-        }
-
-        public void clean() {
-            mHead = null;
-        }
-    }
-
-    private class TileDecoder implements ThreadPool.Job<Void> {
-
-        private CancelListener mNotifier = new CancelListener() {
-            @Override
-            public void onCancel() {
-                synchronized (TileImageView.this) {
-                    TileImageView.this.notifyAll();
-                }
-            }
-        };
-
-        @Override
-        public Void run(JobContext jc) {
-            jc.setMode(ThreadPool.MODE_NONE);
-            jc.setCancelListener(mNotifier);
-            while (!jc.isCancelled()) {
-                Tile tile = null;
-                synchronized(TileImageView.this) {
-                    tile = mDecodeQueue.pop();
-                    if (tile == null && !jc.isCancelled()) {
-                        Utils.waitWithoutInterrupt(TileImageView.this);
-                    }
-                }
-                if (tile == null) continue;
-                if (decodeTile(tile)) queueForUpload(tile);
-            }
-            return null;
-        }
-    }
-}
diff --git a/src/com/android/gallery3d/ui/TileImageViewAdapter.java b/src/com/android/gallery3d/ui/TileImageViewAdapter.java
deleted file mode 100644
index 0c1f66d..0000000
--- a/src/com/android/gallery3d/ui/TileImageViewAdapter.java
+++ /dev/null
@@ -1,200 +0,0 @@
-/*
- * Copyright (C) 2010 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.gallery3d.ui;
-
-import android.annotation.TargetApi;
-import android.graphics.Bitmap;
-import android.graphics.Bitmap.Config;
-import android.graphics.BitmapFactory;
-import android.graphics.BitmapRegionDecoder;
-import android.graphics.Canvas;
-import android.graphics.Rect;
-
-import com.android.gallery3d.common.ApiHelper;
-import com.android.gallery3d.common.Utils;
-import com.android.photos.data.GalleryBitmapPool;
-
-public class TileImageViewAdapter implements TileImageView.TileSource {
-    private static final String TAG = "TileImageViewAdapter";
-    protected ScreenNail mScreenNail;
-    protected boolean mOwnScreenNail;
-    protected BitmapRegionDecoder mRegionDecoder;
-    protected int mImageWidth;
-    protected int mImageHeight;
-    protected int mLevelCount;
-
-    public TileImageViewAdapter() {
-    }
-
-    public synchronized void clear() {
-        mScreenNail = null;
-        mImageWidth = 0;
-        mImageHeight = 0;
-        mLevelCount = 0;
-        mRegionDecoder = null;
-    }
-
-    // Caller is responsible to recycle the ScreenNail
-    public synchronized void setScreenNail(
-            ScreenNail screenNail, int width, int height) {
-        Utils.checkNotNull(screenNail);
-        mScreenNail = screenNail;
-        mImageWidth = width;
-        mImageHeight = height;
-        mRegionDecoder = null;
-        mLevelCount = 0;
-    }
-
-    public synchronized void setRegionDecoder(BitmapRegionDecoder decoder) {
-        mRegionDecoder = Utils.checkNotNull(decoder);
-        mImageWidth = decoder.getWidth();
-        mImageHeight = decoder.getHeight();
-        mLevelCount = calculateLevelCount();
-    }
-
-    private int calculateLevelCount() {
-        return Math.max(0, Utils.ceilLog2(
-                (float) mImageWidth / mScreenNail.getWidth()));
-    }
-
-    // Gets a sub image on a rectangle of the current photo. For example,
-    // getTile(1, 50, 50, 100, 3, pool) means to get the region located
-    // at (50, 50) with sample level 1 (ie, down sampled by 2^1) and the
-    // target tile size (after sampling) 100 with border 3.
-    //
-    // From this spec, we can infer the actual tile size to be
-    // 100 + 3x2 = 106, and the size of the region to be extracted from the
-    // photo to be 200 with border 6.
-    //
-    // As a result, we should decode region (50-6, 50-6, 250+6, 250+6) or
-    // (44, 44, 256, 256) from the original photo and down sample it to 106.
-    @TargetApi(ApiHelper.VERSION_CODES.HONEYCOMB)
-    @Override
-    public Bitmap getTile(int level, int x, int y, int tileSize) {
-        if (!ApiHelper.HAS_REUSING_BITMAP_IN_BITMAP_REGION_DECODER) {
-            return getTileWithoutReusingBitmap(level, x, y, tileSize);
-        }
-
-        int t = tileSize << level;
-
-        Rect wantRegion = new Rect(x, y, x + t, y + t);
-
-        boolean needClear;
-        BitmapRegionDecoder regionDecoder = null;
-
-        synchronized (this) {
-            regionDecoder = mRegionDecoder;
-            if (regionDecoder == null) return null;
-
-            // We need to clear a reused bitmap, if wantRegion is not fully
-            // within the image.
-            needClear = !new Rect(0, 0, mImageWidth, mImageHeight)
-                    .contains(wantRegion);
-        }
-
-        Bitmap bitmap = GalleryBitmapPool.getInstance().get(tileSize, tileSize);
-        if (bitmap != null) {
-            if (needClear) bitmap.eraseColor(0);
-        } else {
-            bitmap = Bitmap.createBitmap(tileSize, tileSize, Config.ARGB_8888);
-        }
-
-        BitmapFactory.Options options = new BitmapFactory.Options();
-        options.inPreferredConfig = Config.ARGB_8888;
-        options.inPreferQualityOverSpeed = true;
-        options.inSampleSize =  (1 << level);
-        options.inBitmap = bitmap;
-
-        try {
-            // In CropImage, we may call the decodeRegion() concurrently.
-            synchronized (regionDecoder) {
-                bitmap = regionDecoder.decodeRegion(wantRegion, options);
-            }
-        } finally {
-            if (options.inBitmap != bitmap && options.inBitmap != null) {
-                GalleryBitmapPool.getInstance().put(options.inBitmap);
-                options.inBitmap = null;
-            }
-        }
-
-        if (bitmap == null) {
-            Log.w(TAG, "fail in decoding region");
-        }
-        return bitmap;
-    }
-
-    private Bitmap getTileWithoutReusingBitmap(
-            int level, int x, int y, int tileSize) {
-        int t = tileSize << level;
-        Rect wantRegion = new Rect(x, y, x + t, y + t);
-
-        BitmapRegionDecoder regionDecoder;
-        Rect overlapRegion;
-
-        synchronized (this) {
-            regionDecoder = mRegionDecoder;
-            if (regionDecoder == null) return null;
-            overlapRegion = new Rect(0, 0, mImageWidth, mImageHeight);
-            Utils.assertTrue(overlapRegion.intersect(wantRegion));
-        }
-
-        BitmapFactory.Options options = new BitmapFactory.Options();
-        options.inPreferredConfig = Config.ARGB_8888;
-        options.inPreferQualityOverSpeed = true;
-        options.inSampleSize =  (1 << level);
-        Bitmap bitmap = null;
-
-        // In CropImage, we may call the decodeRegion() concurrently.
-        synchronized (regionDecoder) {
-            bitmap = regionDecoder.decodeRegion(overlapRegion, options);
-        }
-
-        if (bitmap == null) {
-            Log.w(TAG, "fail in decoding region");
-        }
-
-        if (wantRegion.equals(overlapRegion)) return bitmap;
-
-        Bitmap result = Bitmap.createBitmap(tileSize, tileSize, Config.ARGB_8888);
-        Canvas canvas = new Canvas(result);
-        canvas.drawBitmap(bitmap,
-                (overlapRegion.left - wantRegion.left) >> level,
-                (overlapRegion.top - wantRegion.top) >> level, null);
-        return result;
-    }
-
-
-    @Override
-    public ScreenNail getScreenNail() {
-        return mScreenNail;
-    }
-
-    @Override
-    public int getImageHeight() {
-        return mImageHeight;
-    }
-
-    @Override
-    public int getImageWidth() {
-        return mImageWidth;
-    }
-
-    @Override
-    public int getLevelCount() {
-        return mLevelCount;
-    }
-}
diff --git a/src/com/android/gallery3d/ui/TiledScreenNail.java b/src/com/android/gallery3d/ui/TiledScreenNail.java
deleted file mode 100644
index 860e230..0000000
--- a/src/com/android/gallery3d/ui/TiledScreenNail.java
+++ /dev/null
@@ -1,218 +0,0 @@
-/*
- * 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.gallery3d.ui;
-
-import android.graphics.Bitmap;
-import android.graphics.RectF;
-
-import com.android.gallery3d.common.Utils;
-import com.android.photos.data.GalleryBitmapPool;
-import com.android.gallery3d.glrenderer.GLCanvas;
-import com.android.gallery3d.glrenderer.TiledTexture;
-
-// This is a ScreenNail wraps a Bitmap. There are some extra functions:
-//
-// - If we need to draw before the bitmap is available, we draw a rectange of
-// placeholder color (gray).
-//
-// - When the the bitmap is available, and we have drawn the placeholder color
-// before, we will do a fade-in animation.
-public class TiledScreenNail implements ScreenNail {
-    @SuppressWarnings("unused")
-    private static final String TAG = "TiledScreenNail";
-
-    // The duration of the fading animation in milliseconds
-    private static final int DURATION = 180;
-
-    private static int sMaxSide = 640;
-
-    // These are special values for mAnimationStartTime
-    private static final long ANIMATION_NOT_NEEDED = -1;
-    private static final long ANIMATION_NEEDED = -2;
-    private static final long ANIMATION_DONE = -3;
-
-    private int mWidth;
-    private int mHeight;
-    private long mAnimationStartTime = ANIMATION_NOT_NEEDED;
-
-    private Bitmap mBitmap;
-    private TiledTexture mTexture;
-
-    public TiledScreenNail(Bitmap bitmap) {
-        mWidth = bitmap.getWidth();
-        mHeight = bitmap.getHeight();
-        mBitmap = bitmap;
-        mTexture = new TiledTexture(bitmap);
-    }
-
-    public TiledScreenNail(int width, int height) {
-        setSize(width, height);
-    }
-
-    // This gets overridden by bitmap_screennail_placeholder
-    // in GalleryUtils.initialize
-    private static int mPlaceholderColor = 0xFF222222;
-    private static boolean mDrawPlaceholder = true;
-
-    public static void setPlaceholderColor(int color) {
-        mPlaceholderColor = color;
-    }
-
-    private void setSize(int width, int height) {
-        if (width == 0 || height == 0) {
-            width = sMaxSide;
-            height = sMaxSide * 3 / 4;
-        }
-        float scale = Math.min(1, (float) sMaxSide / Math.max(width, height));
-        mWidth = Math.round(scale * width);
-        mHeight = Math.round(scale * height);
-    }
-
-    // Combines the two ScreenNails.
-    // Returns the used one and recycle the unused one.
-    public ScreenNail combine(ScreenNail other) {
-        if (other == null) {
-            return this;
-        }
-
-        if (!(other instanceof TiledScreenNail)) {
-            recycle();
-            return other;
-        }
-
-        // Now both are TiledScreenNail. Move over the information about width,
-        // height, and Bitmap, then recycle the other.
-        TiledScreenNail newer = (TiledScreenNail) other;
-        mWidth = newer.mWidth;
-        mHeight = newer.mHeight;
-        if (newer.mTexture != null) {
-            if (mBitmap != null) GalleryBitmapPool.getInstance().put(mBitmap);
-            if (mTexture != null) mTexture.recycle();
-            mBitmap = newer.mBitmap;
-            mTexture = newer.mTexture;
-            newer.mBitmap = null;
-            newer.mTexture = null;
-        }
-        newer.recycle();
-        return this;
-    }
-
-    public void updatePlaceholderSize(int width, int height) {
-        if (mBitmap != null) return;
-        if (width == 0 || height == 0) return;
-        setSize(width, height);
-    }
-
-    @Override
-    public int getWidth() {
-        return mWidth;
-    }
-
-    @Override
-    public int getHeight() {
-        return mHeight;
-    }
-
-    @Override
-    public void noDraw() {
-    }
-
-    @Override
-    public void recycle() {
-        if (mTexture != null) {
-            mTexture.recycle();
-            mTexture = null;
-        }
-        if (mBitmap != null) {
-            GalleryBitmapPool.getInstance().put(mBitmap);
-            mBitmap = null;
-        }
-    }
-
-    public static void disableDrawPlaceholder() {
-        mDrawPlaceholder = false;
-    }
-
-    public static void enableDrawPlaceholder() {
-        mDrawPlaceholder = true;
-    }
-
-    @Override
-    public void draw(GLCanvas canvas, int x, int y, int width, int height) {
-        if (mTexture == null || !mTexture.isReady()) {
-            if (mAnimationStartTime == ANIMATION_NOT_NEEDED) {
-                mAnimationStartTime = ANIMATION_NEEDED;
-            }
-            if(mDrawPlaceholder) {
-                canvas.fillRect(x, y, width, height, mPlaceholderColor);
-            }
-            return;
-        }
-
-        if (mAnimationStartTime == ANIMATION_NEEDED) {
-            mAnimationStartTime = AnimationTime.get();
-        }
-
-        if (isAnimating()) {
-            mTexture.drawMixed(canvas, mPlaceholderColor, getRatio(), x, y,
-                    width, height);
-        } else {
-            mTexture.draw(canvas, x, y, width, height);
-        }
-    }
-
-    @Override
-    public void draw(GLCanvas canvas, RectF source, RectF dest) {
-        if (mTexture == null || !mTexture.isReady()) {
-            canvas.fillRect(dest.left, dest.top, dest.width(), dest.height(),
-                    mPlaceholderColor);
-            return;
-        }
-
-        mTexture.draw(canvas, source, dest);
-    }
-
-    public boolean isAnimating() {
-        // The TiledTexture may not be uploaded completely yet.
-        // In that case, we count it as animating state and we will draw
-        // the placeholder in TileImageView.
-        if (mTexture == null || !mTexture.isReady()) return true;
-        if (mAnimationStartTime < 0) return false;
-        if (AnimationTime.get() - mAnimationStartTime >= DURATION) {
-            mAnimationStartTime = ANIMATION_DONE;
-            return false;
-        }
-        return true;
-    }
-
-    private float getRatio() {
-        float r = (float) (AnimationTime.get() - mAnimationStartTime) / DURATION;
-        return Utils.clamp(1.0f - r, 0.0f, 1.0f);
-    }
-
-    public boolean isShowingPlaceholder() {
-        return (mBitmap == null) || isAnimating();
-    }
-
-    public TiledTexture getTexture() {
-        return mTexture;
-    }
-
-    public static void setMaxSide(int size) {
-        sMaxSide = size;
-    }
-}
diff --git a/src/com/android/gallery3d/ui/UndoBarView.java b/src/com/android/gallery3d/ui/UndoBarView.java
deleted file mode 100644
index 42f12ae..0000000
--- a/src/com/android/gallery3d/ui/UndoBarView.java
+++ /dev/null
@@ -1,211 +0,0 @@
-/*
- * 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.gallery3d.ui;
-
-import android.content.Context;
-import android.view.MotionEvent;
-
-import com.android.gallery3d.R;
-import com.android.gallery3d.common.Utils;
-import com.android.gallery3d.glrenderer.GLCanvas;
-import com.android.gallery3d.glrenderer.NinePatchTexture;
-import com.android.gallery3d.glrenderer.ResourceTexture;
-import com.android.gallery3d.glrenderer.StringTexture;
-import com.android.gallery3d.util.GalleryUtils;
-
-public class UndoBarView extends GLView {
-    @SuppressWarnings("unused")
-    private static final String TAG = "UndoBarView";
-
-    private static final int WHITE = 0xFFFFFFFF;
-    private static final int GRAY = 0xFFAAAAAA;
-
-    private final NinePatchTexture mPanel;
-    private final StringTexture mUndoText;
-    private final StringTexture mDeletedText;
-    private final ResourceTexture mUndoIcon;
-    private final int mBarHeight;
-    private final int mBarMargin;
-    private final int mUndoTextMargin;
-    private final int mIconSize;
-    private final int mIconMargin;
-    private final int mSeparatorTopMargin;
-    private final int mSeparatorBottomMargin;
-    private final int mSeparatorRightMargin;
-    private final int mSeparatorWidth;
-    private final int mDeletedTextMargin;
-    private final int mClickRegion;
-
-    private OnClickListener mOnClickListener;
-    private boolean mDownOnButton;
-
-    // This is the layout of UndoBarView. The unit is dp.
-    //
-    //    +-+----+----------------+-+--+----+-+------+--+-+
-    // 48 | |    | Deleted        | |  | <- | | UNDO |  | |
-    //    +-+----+----------------+-+--+----+-+------+--+-+
-    //     4  16                   1 12  32  8        16 4
-    public UndoBarView(Context context) {
-        mBarHeight = GalleryUtils.dpToPixel(48);
-        mBarMargin = GalleryUtils.dpToPixel(4);
-        mUndoTextMargin = GalleryUtils.dpToPixel(16);
-        mIconMargin = GalleryUtils.dpToPixel(8);
-        mIconSize = GalleryUtils.dpToPixel(32);
-        mSeparatorRightMargin = GalleryUtils.dpToPixel(12);
-        mSeparatorTopMargin = GalleryUtils.dpToPixel(10);
-        mSeparatorBottomMargin = GalleryUtils.dpToPixel(10);
-        mSeparatorWidth = GalleryUtils.dpToPixel(1);
-        mDeletedTextMargin = GalleryUtils.dpToPixel(16);
-
-        mPanel = new NinePatchTexture(context, R.drawable.panel_undo_holo);
-        mUndoText = StringTexture.newInstance(context.getString(R.string.undo),
-                GalleryUtils.dpToPixel(12), GRAY, 0, true);
-        mDeletedText = StringTexture.newInstance(
-                context.getString(R.string.deleted),
-                GalleryUtils.dpToPixel(16), WHITE);
-        mUndoIcon = new ResourceTexture(
-                context, R.drawable.ic_menu_revert_holo_dark);
-        mClickRegion = mBarMargin + mUndoTextMargin + mUndoText.getWidth()
-                + mIconMargin + mIconSize + mSeparatorRightMargin;
-    }
-
-    public void setOnClickListener(OnClickListener listener) {
-        mOnClickListener = listener;
-    }
-
-    @Override
-    protected void onMeasure(int widthSpec, int heightSpec) {
-        setMeasuredSize(0 /* unused */, mBarHeight);
-    }
-
-    @Override
-    protected void render(GLCanvas canvas) {
-        super.render(canvas);
-        advanceAnimation();
-
-        canvas.save(GLCanvas.SAVE_FLAG_ALPHA);
-        canvas.multiplyAlpha(mAlpha);
-
-        int w = getWidth();
-        int h = getHeight();
-        mPanel.draw(canvas, mBarMargin, 0, w - mBarMargin * 2, mBarHeight);
-
-        int x = w - mBarMargin;
-        int y;
-
-        x -= mUndoTextMargin + mUndoText.getWidth();
-        y = (mBarHeight - mUndoText.getHeight()) / 2;
-        mUndoText.draw(canvas, x, y);
-
-        x -= mIconMargin + mIconSize;
-        y = (mBarHeight - mIconSize) / 2;
-        mUndoIcon.draw(canvas, x, y, mIconSize, mIconSize);
-
-        x -= mSeparatorRightMargin + mSeparatorWidth;
-        y = mSeparatorTopMargin;
-        canvas.fillRect(x, y, mSeparatorWidth,
-                mBarHeight - mSeparatorTopMargin - mSeparatorBottomMargin, GRAY);
-
-        x = mBarMargin + mDeletedTextMargin;
-        y = (mBarHeight - mDeletedText.getHeight()) / 2;
-        mDeletedText.draw(canvas, x, y);
-
-        canvas.restore();
-    }
-
-    @Override
-    protected boolean onTouch(MotionEvent event) {
-        switch (event.getAction()) {
-            case MotionEvent.ACTION_DOWN:
-                mDownOnButton = inUndoButton(event);
-                break;
-            case MotionEvent.ACTION_UP:
-                if (mDownOnButton) {
-                    if (mOnClickListener != null && inUndoButton(event)) {
-                        mOnClickListener.onClick(this);
-                    }
-                    mDownOnButton = false;
-                }
-                break;
-            case MotionEvent.ACTION_CANCEL:
-                mDownOnButton = false;
-                break;
-        }
-        return true;
-    }
-
-    // Check if the event is on the right of the separator
-    private boolean inUndoButton(MotionEvent event) {
-        float x = event.getX();
-        float y = event.getY();
-        int w = getWidth();
-        int h = getHeight();
-        return (x >= w - mClickRegion && x < w && y >= 0 && y < h);
-    }
-
-    ////////////////////////////////////////////////////////////////////////////
-    //  Alpha Animation
-    ////////////////////////////////////////////////////////////////////////////
-
-    private static final long NO_ANIMATION = -1;
-    private static long ANIM_TIME = 200;
-    private long mAnimationStartTime = NO_ANIMATION;
-    private float mFromAlpha, mToAlpha;
-    private float mAlpha;
-
-    private static float getTargetAlpha(int visibility) {
-        return (visibility == VISIBLE) ? 1f : 0f;
-    }
-
-    @Override
-    public void setVisibility(int visibility) {
-        mAlpha = getTargetAlpha(visibility);
-        mAnimationStartTime = NO_ANIMATION;
-        super.setVisibility(visibility);
-        invalidate();
-    }
-
-    public void animateVisibility(int visibility) {
-        float target = getTargetAlpha(visibility);
-        if (mAnimationStartTime == NO_ANIMATION && mAlpha == target) return;
-        if (mAnimationStartTime != NO_ANIMATION && mToAlpha == target) return;
-
-        mFromAlpha = mAlpha;
-        mToAlpha = target;
-        mAnimationStartTime = AnimationTime.startTime();
-
-        super.setVisibility(VISIBLE);
-        invalidate();
-    }
-
-    private void advanceAnimation() {
-        if (mAnimationStartTime == NO_ANIMATION) return;
-
-        float delta = (float) (AnimationTime.get() - mAnimationStartTime) /
-                ANIM_TIME;
-        mAlpha = mFromAlpha + ((mToAlpha > mFromAlpha) ? delta : -delta);
-        mAlpha = Utils.clamp(mAlpha, 0f, 1f);
-
-        if (mAlpha == mToAlpha) {
-            mAnimationStartTime = NO_ANIMATION;
-            if (mAlpha == 0) {
-                super.setVisibility(INVISIBLE);
-            }
-        }
-        invalidate();
-    }
-}
diff --git a/src/com/android/gallery3d/ui/UserInteractionListener.java b/src/com/android/gallery3d/ui/UserInteractionListener.java
deleted file mode 100644
index bc4a718..0000000
--- a/src/com/android/gallery3d/ui/UserInteractionListener.java
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Copyright (C) 2010 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.gallery3d.ui;
-
-public interface UserInteractionListener {
-    // Called when a user interaction begins (for example, fling).
-    public void onUserInteractionBegin();
-    // Called when the user interaction ends.
-    public void onUserInteractionEnd();
-    // Other one-shot user interactions.
-    public void onUserInteraction();
-}
diff --git a/src/com/android/gallery3d/ui/WakeLockHoldingProgressListener.java b/src/com/android/gallery3d/ui/WakeLockHoldingProgressListener.java
deleted file mode 100644
index ee61d8e..0000000
--- a/src/com/android/gallery3d/ui/WakeLockHoldingProgressListener.java
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * 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.gallery3d.ui;
-
-import android.app.Activity;
-import android.content.Context;
-import android.os.PowerManager;
-
-import com.android.gallery3d.app.AbstractGalleryActivity;
-
-public class WakeLockHoldingProgressListener implements MenuExecutor.ProgressListener {
-    static private final String DEFAULT_WAKE_LOCK_LABEL = "Gallery Progress Listener";
-    private AbstractGalleryActivity mActivity;
-    private PowerManager.WakeLock mWakeLock;
-
-    public WakeLockHoldingProgressListener(AbstractGalleryActivity galleryActivity) {
-        this(galleryActivity, DEFAULT_WAKE_LOCK_LABEL);
-    }
-
-    public WakeLockHoldingProgressListener(AbstractGalleryActivity galleryActivity, String label) {
-        mActivity = galleryActivity;
-        PowerManager pm =
-                (PowerManager) ((Activity) mActivity).getSystemService(Context.POWER_SERVICE);
-        mWakeLock = pm.newWakeLock(PowerManager.SCREEN_DIM_WAKE_LOCK, label);
-    }
-
-    @Override
-    public void onProgressComplete(int result) {
-        mWakeLock.release();
-    }
-
-    @Override
-    public void onProgressStart() {
-        mWakeLock.acquire();
-    }
-
-    protected AbstractGalleryActivity getActivity() {
-        return mActivity;
-    }
-
-    @Override
-    public void onProgressUpdate(int index) {
-    }
-
-    @Override
-    public void onConfirmDialogDismissed(boolean confirmed) {
-    }
-
-    @Override
-    public void onConfirmDialogShown() {
-    }
-}
diff --git a/src/com/android/gallery3d/util/AccessibilityUtils.java b/src/com/android/gallery3d/util/AccessibilityUtils.java
deleted file mode 100644
index 9df8e4e..0000000
--- a/src/com/android/gallery3d/util/AccessibilityUtils.java
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * 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.gallery3d.util;
-
-import android.content.Context;
-import android.support.v4.view.accessibility.AccessibilityRecordCompat;
-import android.view.View;
-import android.view.accessibility.AccessibilityEvent;
-import android.view.accessibility.AccessibilityManager;
-
-import com.android.gallery3d.common.ApiHelper;
-
-/**
- * AccessibilityUtils provides functions needed in accessibility mode. All the functions
- * in this class are made compatible with gingerbread and later API's
-*/
-public class AccessibilityUtils {
-    public static void makeAnnouncement(View view, CharSequence announcement) {
-        if (view == null)
-            return;
-        if (ApiHelper.HAS_ANNOUNCE_FOR_ACCESSIBILITY) {
-            view.announceForAccessibility(announcement);
-        } else {
-            // For API 15 and earlier, we need to construct an accessibility event
-            Context ctx = view.getContext();
-            AccessibilityManager am = (AccessibilityManager) ctx.getSystemService(
-                    Context.ACCESSIBILITY_SERVICE);
-            if (!am.isEnabled()) return;
-            AccessibilityEvent event = AccessibilityEvent.obtain(
-                    AccessibilityEvent.TYPE_NOTIFICATION_STATE_CHANGED);
-            AccessibilityRecordCompat arc = new AccessibilityRecordCompat(event);
-            arc.setSource(view);
-            event.setClassName(view.getClass().getName());
-            event.setPackageName(view.getContext().getPackageName());
-            event.setEnabled(view.isEnabled());
-            event.getText().add(announcement);
-            am.sendAccessibilityEvent(event);
-        }
-    }
-}
\ No newline at end of file
diff --git a/src/com/android/gallery3d/util/BucketNames.java b/src/com/android/gallery3d/util/BucketNames.java
deleted file mode 100644
index 990dc82..0000000
--- a/src/com/android/gallery3d/util/BucketNames.java
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * 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.gallery3d.util;
-
-/**
- * Bucket names for buckets that are created and used in the Gallery.
- */
-public class BucketNames {
-
-    public static final String CAMERA = "DCIM/Camera";
-    public static final String IMPORTED = "Imported";
-    public static final String DOWNLOAD = "download";
-    public static final String EDITED_ONLINE_PHOTOS = "EditedOnlinePhotos";
-    public static final String SCREENSHOTS = "Pictures/Screenshots";
-}
diff --git a/src/com/android/gallery3d/util/CacheManager.java b/src/com/android/gallery3d/util/CacheManager.java
deleted file mode 100644
index ba466f7..0000000
--- a/src/com/android/gallery3d/util/CacheManager.java
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * Copyright (C) 2010 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.gallery3d.util;
-
-import android.content.Context;
-import android.content.SharedPreferences;
-import android.preference.PreferenceManager;
-
-import com.android.gallery3d.common.BlobCache;
-
-import java.io.File;
-import java.io.IOException;
-import java.util.HashMap;
-
-public class CacheManager {
-    private static final String TAG = "CacheManager";
-    private static final String KEY_CACHE_UP_TO_DATE = "cache-up-to-date";
-    private static HashMap<String, BlobCache> sCacheMap =
-            new HashMap<String, BlobCache>();
-    private static boolean sOldCheckDone = false;
-
-    // Return null when we cannot instantiate a BlobCache, e.g.:
-    // there is no SD card found.
-    // This can only be called from data thread.
-    public static BlobCache getCache(Context context, String filename,
-            int maxEntries, int maxBytes, int version) {
-        synchronized (sCacheMap) {
-            if (!sOldCheckDone) {
-                removeOldFilesIfNecessary(context);
-                sOldCheckDone = true;
-            }
-            BlobCache cache = sCacheMap.get(filename);
-            if (cache == null) {
-                File cacheDir = context.getExternalCacheDir();
-                String path = cacheDir.getAbsolutePath() + "/" + filename;
-                try {
-                    cache = new BlobCache(path, maxEntries, maxBytes, false,
-                            version);
-                    sCacheMap.put(filename, cache);
-                } catch (IOException e) {
-                    Log.e(TAG, "Cannot instantiate cache!", e);
-                }
-            }
-            return cache;
-        }
-    }
-
-    // Removes the old files if the data is wiped.
-    private static void removeOldFilesIfNecessary(Context context) {
-        SharedPreferences pref = PreferenceManager
-                .getDefaultSharedPreferences(context);
-        int n = 0;
-        try {
-            n = pref.getInt(KEY_CACHE_UP_TO_DATE, 0);
-        } catch (Throwable t) {
-            // ignore.
-        }
-        if (n != 0) return;
-        pref.edit().putInt(KEY_CACHE_UP_TO_DATE, 1).commit();
-
-        File cacheDir = context.getExternalCacheDir();
-        String prefix = cacheDir.getAbsolutePath() + "/";
-
-        BlobCache.deleteFiles(prefix + "imgcache");
-        BlobCache.deleteFiles(prefix + "rev_geocoding");
-        BlobCache.deleteFiles(prefix + "bookmark");
-    }
-}
diff --git a/src/com/android/gallery3d/util/GalleryUtils.java b/src/com/android/gallery3d/util/GalleryUtils.java
deleted file mode 100644
index 9245e2c..0000000
--- a/src/com/android/gallery3d/util/GalleryUtils.java
+++ /dev/null
@@ -1,404 +0,0 @@
-/*
- * Copyright (C) 2010 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.gallery3d.util;
-
-import android.annotation.TargetApi;
-import android.content.ActivityNotFoundException;
-import android.content.ComponentName;
-import android.content.Context;
-import android.content.Intent;
-import android.content.SharedPreferences;
-import android.content.pm.PackageManager;
-import android.content.pm.ResolveInfo;
-import android.content.res.Resources;
-import android.graphics.Color;
-import android.net.Uri;
-import android.os.ConditionVariable;
-import android.os.Environment;
-import android.os.StatFs;
-import android.preference.PreferenceManager;
-import android.provider.MediaStore;
-import android.util.DisplayMetrics;
-import android.util.Log;
-import android.view.WindowManager;
-
-import com.android.gallery3d.R;
-import com.android.gallery3d.app.Gallery;
-import com.android.gallery3d.app.PackagesMonitor;
-import com.android.gallery3d.common.ApiHelper;
-import com.android.gallery3d.data.DataManager;
-import com.android.gallery3d.data.MediaItem;
-import com.android.gallery3d.ui.TiledScreenNail;
-import com.android.gallery3d.util.ThreadPool.CancelListener;
-import com.android.gallery3d.util.ThreadPool.JobContext;
-
-import java.io.File;
-import java.util.Arrays;
-import java.util.List;
-import java.util.Locale;
-
-public class GalleryUtils {
-    private static final String TAG = "GalleryUtils";
-    private static final String MAPS_PACKAGE_NAME = "com.google.android.apps.maps";
-    private static final String MAPS_CLASS_NAME = "com.google.android.maps.MapsActivity";
-    private static final String CAMERA_LAUNCHER_NAME = "com.android.camera.CameraLauncher";
-
-    public static final String MIME_TYPE_IMAGE = "image/*";
-    public static final String MIME_TYPE_VIDEO = "video/*";
-    public static final String MIME_TYPE_PANORAMA360 = "application/vnd.google.panorama360+jpg";
-    public static final String MIME_TYPE_ALL = "*/*";
-
-    private static final String DIR_TYPE_IMAGE = "vnd.android.cursor.dir/image";
-    private static final String DIR_TYPE_VIDEO = "vnd.android.cursor.dir/video";
-
-    private static final String PREFIX_PHOTO_EDITOR_UPDATE = "editor-update-";
-    private static final String PREFIX_HAS_PHOTO_EDITOR = "has-editor-";
-
-    private static final String KEY_CAMERA_UPDATE = "camera-update";
-    private static final String KEY_HAS_CAMERA = "has-camera";
-
-    private static float sPixelDensity = -1f;
-    private static boolean sCameraAvailableInitialized = false;
-    private static boolean sCameraAvailable;
-
-    public static void initialize(Context context) {
-        DisplayMetrics metrics = new DisplayMetrics();
-        WindowManager wm = (WindowManager)
-                context.getSystemService(Context.WINDOW_SERVICE);
-        wm.getDefaultDisplay().getMetrics(metrics);
-        sPixelDensity = metrics.density;
-        Resources r = context.getResources();
-        TiledScreenNail.setPlaceholderColor(r.getColor(
-                R.color.bitmap_screennail_placeholder));
-        initializeThumbnailSizes(metrics, r);
-    }
-
-    private static void initializeThumbnailSizes(DisplayMetrics metrics, Resources r) {
-        int maxPixels = Math.max(metrics.heightPixels, metrics.widthPixels);
-
-        // For screen-nails, we never need to completely fill the screen
-        MediaItem.setThumbnailSizes(maxPixels / 2, maxPixels / 5);
-        TiledScreenNail.setMaxSide(maxPixels / 2);
-    }
-
-    public static float[] intColorToFloatARGBArray(int from) {
-        return new float[] {
-            Color.alpha(from) / 255f,
-            Color.red(from) / 255f,
-            Color.green(from) / 255f,
-            Color.blue(from) / 255f
-        };
-    }
-
-    public static float dpToPixel(float dp) {
-        return sPixelDensity * dp;
-    }
-
-    public static int dpToPixel(int dp) {
-        return Math.round(dpToPixel((float) dp));
-    }
-
-    public static int meterToPixel(float meter) {
-        // 1 meter = 39.37 inches, 1 inch = 160 dp.
-        return Math.round(dpToPixel(meter * 39.37f * 160));
-    }
-
-    public static byte[] getBytes(String in) {
-        byte[] result = new byte[in.length() * 2];
-        int output = 0;
-        for (char ch : in.toCharArray()) {
-            result[output++] = (byte) (ch & 0xFF);
-            result[output++] = (byte) (ch >> 8);
-        }
-        return result;
-    }
-
-    // Below are used the detect using database in the render thread. It only
-    // works most of the time, but that's ok because it's for debugging only.
-
-    private static volatile Thread sCurrentThread;
-    private static volatile boolean sWarned;
-
-    public static void setRenderThread() {
-        sCurrentThread = Thread.currentThread();
-    }
-
-    public static void assertNotInRenderThread() {
-        if (!sWarned) {
-            if (Thread.currentThread() == sCurrentThread) {
-                sWarned = true;
-                Log.w(TAG, new Throwable("Should not do this in render thread"));
-            }
-        }
-    }
-
-    private static final double RAD_PER_DEG = Math.PI / 180.0;
-    private static final double EARTH_RADIUS_METERS = 6367000.0;
-
-    public static double fastDistanceMeters(double latRad1, double lngRad1,
-            double latRad2, double lngRad2) {
-       if ((Math.abs(latRad1 - latRad2) > RAD_PER_DEG)
-             || (Math.abs(lngRad1 - lngRad2) > RAD_PER_DEG)) {
-           return accurateDistanceMeters(latRad1, lngRad1, latRad2, lngRad2);
-       }
-       // Approximate sin(x) = x.
-       double sineLat = (latRad1 - latRad2);
-
-       // Approximate sin(x) = x.
-       double sineLng = (lngRad1 - lngRad2);
-
-       // Approximate cos(lat1) * cos(lat2) using
-       // cos((lat1 + lat2)/2) ^ 2
-       double cosTerms = Math.cos((latRad1 + latRad2) / 2.0);
-       cosTerms = cosTerms * cosTerms;
-       double trigTerm = sineLat * sineLat + cosTerms * sineLng * sineLng;
-       trigTerm = Math.sqrt(trigTerm);
-
-       // Approximate arcsin(x) = x
-       return EARTH_RADIUS_METERS * trigTerm;
-    }
-
-    public static double accurateDistanceMeters(double lat1, double lng1,
-            double lat2, double lng2) {
-        double dlat = Math.sin(0.5 * (lat2 - lat1));
-        double dlng = Math.sin(0.5 * (lng2 - lng1));
-        double x = dlat * dlat + dlng * dlng * Math.cos(lat1) * Math.cos(lat2);
-        return (2 * Math.atan2(Math.sqrt(x), Math.sqrt(Math.max(0.0,
-                1.0 - x)))) * EARTH_RADIUS_METERS;
-    }
-
-
-    public static final double toMile(double meter) {
-        return meter / 1609;
-    }
-
-    // For debugging, it will block the caller for timeout millis.
-    public static void fakeBusy(JobContext jc, int timeout) {
-        final ConditionVariable cv = new ConditionVariable();
-        jc.setCancelListener(new CancelListener() {
-            @Override
-            public void onCancel() {
-                cv.open();
-            }
-        });
-        cv.block(timeout);
-        jc.setCancelListener(null);
-    }
-
-    public static boolean isEditorAvailable(Context context, String mimeType) {
-        int version = PackagesMonitor.getPackagesVersion(context);
-
-        String updateKey = PREFIX_PHOTO_EDITOR_UPDATE + mimeType;
-        String hasKey = PREFIX_HAS_PHOTO_EDITOR + mimeType;
-
-        SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
-        if (prefs.getInt(updateKey, 0) != version) {
-            PackageManager packageManager = context.getPackageManager();
-            List<ResolveInfo> infos = packageManager.queryIntentActivities(
-                    new Intent(Intent.ACTION_EDIT).setType(mimeType), 0);
-            prefs.edit().putInt(updateKey, version)
-                        .putBoolean(hasKey, !infos.isEmpty())
-                        .commit();
-        }
-
-        return prefs.getBoolean(hasKey, true);
-    }
-
-    public static boolean isAnyCameraAvailable(Context context) {
-        int version = PackagesMonitor.getPackagesVersion(context);
-        SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
-        if (prefs.getInt(KEY_CAMERA_UPDATE, 0) != version) {
-            PackageManager packageManager = context.getPackageManager();
-            List<ResolveInfo> infos = packageManager.queryIntentActivities(
-                    new Intent(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA), 0);
-            prefs.edit().putInt(KEY_CAMERA_UPDATE, version)
-                        .putBoolean(KEY_HAS_CAMERA, !infos.isEmpty())
-                        .commit();
-        }
-        return prefs.getBoolean(KEY_HAS_CAMERA, true);
-    }
-
-    public static boolean isCameraAvailable(Context context) {
-        if (sCameraAvailableInitialized) return sCameraAvailable;
-        PackageManager pm = context.getPackageManager();
-        ComponentName name = new ComponentName(context, CAMERA_LAUNCHER_NAME);
-        int state = pm.getComponentEnabledSetting(name);
-        sCameraAvailableInitialized = true;
-        sCameraAvailable =
-            (state == PackageManager.COMPONENT_ENABLED_STATE_DEFAULT)
-             || (state == PackageManager.COMPONENT_ENABLED_STATE_ENABLED);
-        return sCameraAvailable;
-    }
-
-    public static void startCameraActivity(Context context) {
-        Intent intent = new Intent(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA)
-                .setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP
-                        | Intent.FLAG_ACTIVITY_NEW_TASK);
-        context.startActivity(intent);
-    }
-
-    public static void startGalleryActivity(Context context) {
-        Intent intent = new Intent(context, Gallery.class)
-                .setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP
-                | Intent.FLAG_ACTIVITY_NEW_TASK);
-        context.startActivity(intent);
-    }
-
-    public static boolean isValidLocation(double latitude, double longitude) {
-        // TODO: change || to && after we fix the default location issue
-        return (latitude != MediaItem.INVALID_LATLNG || longitude != MediaItem.INVALID_LATLNG);
-    }
-
-    public static String formatLatitudeLongitude(String format, double latitude,
-            double longitude) {
-        // We need to specify the locale otherwise it may go wrong in some language
-        // (e.g. Locale.FRENCH)
-        return String.format(Locale.ENGLISH, format, latitude, longitude);
-    }
-
-    public static void showOnMap(Context context, double latitude, double longitude) {
-        try {
-            // We don't use "geo:latitude,longitude" because it only centers
-            // the MapView to the specified location, but we need a marker
-            // for further operations (routing to/from).
-            // The q=(lat, lng) syntax is suggested by geo-team.
-            String uri = formatLatitudeLongitude("http://maps.google.com/maps?f=q&q=(%f,%f)",
-                    latitude, longitude);
-            ComponentName compName = new ComponentName(MAPS_PACKAGE_NAME,
-                    MAPS_CLASS_NAME);
-            Intent mapsIntent = new Intent(Intent.ACTION_VIEW,
-                    Uri.parse(uri)).setComponent(compName);
-            context.startActivity(mapsIntent);
-        } catch (ActivityNotFoundException e) {
-            // Use the "geo intent" if no GMM is installed
-            Log.e(TAG, "GMM activity not found!", e);
-            String url = formatLatitudeLongitude("geo:%f,%f", latitude, longitude);
-            Intent mapsIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
-            context.startActivity(mapsIntent);
-        }
-    }
-
-    public static void setViewPointMatrix(
-            float matrix[], float x, float y, float z) {
-        // The matrix is
-        // -z,  0,  x,  0
-        //  0, -z,  y,  0
-        //  0,  0,  1,  0
-        //  0,  0,  1, -z
-        Arrays.fill(matrix, 0, 16, 0);
-        matrix[0] = matrix[5] = matrix[15] = -z;
-        matrix[8] = x;
-        matrix[9] = y;
-        matrix[10] = matrix[11] = 1;
-    }
-
-    public static int getBucketId(String path) {
-        return path.toLowerCase().hashCode();
-    }
-
-    // Return the local path that matches the given bucketId. If no match is
-    // found, return null
-    public static String searchDirForPath(File dir, int bucketId) {
-        File[] files = dir.listFiles();
-        if (files != null) {
-            for (File file : files) {
-                if (file.isDirectory()) {
-                    String path = file.getAbsolutePath();
-                    if (GalleryUtils.getBucketId(path) == bucketId) {
-                        return path;
-                    } else {
-                        path = searchDirForPath(file, bucketId);
-                        if (path != null) return path;
-                    }
-                }
-            }
-        }
-        return null;
-    }
-
-    // Returns a (localized) string for the given duration (in seconds).
-    public static String formatDuration(final Context context, int duration) {
-        int h = duration / 3600;
-        int m = (duration - h * 3600) / 60;
-        int s = duration - (h * 3600 + m * 60);
-        String durationValue;
-        if (h == 0) {
-            durationValue = String.format(context.getString(R.string.details_ms), m, s);
-        } else {
-            durationValue = String.format(context.getString(R.string.details_hms), h, m, s);
-        }
-        return durationValue;
-    }
-
-    @TargetApi(ApiHelper.VERSION_CODES.HONEYCOMB)
-    public static int determineTypeBits(Context context, Intent intent) {
-        int typeBits = 0;
-        String type = intent.resolveType(context);
-
-        if (MIME_TYPE_ALL.equals(type)) {
-            typeBits = DataManager.INCLUDE_ALL;
-        } else if (MIME_TYPE_IMAGE.equals(type) ||
-                DIR_TYPE_IMAGE.equals(type)) {
-            typeBits = DataManager.INCLUDE_IMAGE;
-        } else if (MIME_TYPE_VIDEO.equals(type) ||
-                DIR_TYPE_VIDEO.equals(type)) {
-            typeBits = DataManager.INCLUDE_VIDEO;
-        } else {
-            typeBits = DataManager.INCLUDE_ALL;
-        }
-
-        if (ApiHelper.HAS_INTENT_EXTRA_LOCAL_ONLY) {
-            if (intent.getBooleanExtra(Intent.EXTRA_LOCAL_ONLY, false)) {
-                typeBits |= DataManager.INCLUDE_LOCAL_ONLY;
-            }
-        }
-
-        return typeBits;
-    }
-
-    public static int getSelectionModePrompt(int typeBits) {
-        if ((typeBits & DataManager.INCLUDE_VIDEO) != 0) {
-            return (typeBits & DataManager.INCLUDE_IMAGE) == 0
-                    ? R.string.select_video
-                    : R.string.select_item;
-        }
-        return R.string.select_image;
-    }
-
-    public static boolean hasSpaceForSize(long size) {
-        String state = Environment.getExternalStorageState();
-        if (!Environment.MEDIA_MOUNTED.equals(state)) {
-            return false;
-        }
-
-        String path = Environment.getExternalStorageDirectory().getPath();
-        try {
-            StatFs stat = new StatFs(path);
-            return stat.getAvailableBlocks() * (long) stat.getBlockSize() > size;
-        } catch (Exception e) {
-            Log.i(TAG, "Fail to access external storage", e);
-        }
-        return false;
-    }
-
-    public static boolean isPanorama(MediaItem item) {
-        if (item == null) return false;
-        int w = item.getWidth();
-        int h = item.getHeight();
-        return (h > 0 && w / h >= 2);
-    }
-}
diff --git a/src/com/android/gallery3d/util/Holder.java b/src/com/android/gallery3d/util/Holder.java
deleted file mode 100644
index 0ce914c..0000000
--- a/src/com/android/gallery3d/util/Holder.java
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * 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.gallery3d.util;
-
-public class Holder<T> {
-    private T mObject;
-
-    public void set(T object) {
-        mObject = object;
-    }
-
-    public T get() {
-        return mObject;
-    }
-}
diff --git a/src/com/android/gallery3d/util/IdentityCache.java b/src/com/android/gallery3d/util/IdentityCache.java
deleted file mode 100644
index 3edc424..0000000
--- a/src/com/android/gallery3d/util/IdentityCache.java
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * Copyright (C) 2010 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.gallery3d.util;
-
-import java.lang.ref.ReferenceQueue;
-import java.lang.ref.WeakReference;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.Set;
-
-public class IdentityCache<K, V> {
-
-    private final HashMap<K, Entry<K, V>> mWeakMap =
-            new HashMap<K, Entry<K, V>>();
-    private ReferenceQueue<V> mQueue = new ReferenceQueue<V>();
-
-    public IdentityCache() {
-    }
-
-    private static class Entry<K, V> extends WeakReference<V> {
-        K mKey;
-
-        public Entry(K key, V value, ReferenceQueue<V> queue) {
-            super(value, queue);
-            mKey = key;
-        }
-    }
-
-    private void cleanUpWeakMap() {
-        Entry<K, V> entry = (Entry<K, V>) mQueue.poll();
-        while (entry != null) {
-            mWeakMap.remove(entry.mKey);
-            entry = (Entry<K, V>) mQueue.poll();
-        }
-    }
-
-    public synchronized V put(K key, V value) {
-        cleanUpWeakMap();
-        Entry<K, V> entry = mWeakMap.put(
-                key, new Entry<K, V>(key, value, mQueue));
-        return entry == null ? null : entry.get();
-    }
-
-    public synchronized V get(K key) {
-        cleanUpWeakMap();
-        Entry<K, V> entry = mWeakMap.get(key);
-        return entry == null ? null : entry.get();
-    }
-
-    // This is currently unused.
-    /*
-    public synchronized void clear() {
-        mWeakMap.clear();
-        mQueue = new ReferenceQueue<V>();
-    }
-    */
-
-    // This is for debugging only
-    public synchronized ArrayList<K> keys() {
-        Set<K> set = mWeakMap.keySet();
-        ArrayList<K> result = new ArrayList<K>(set);
-        return result;
-    }
-}
diff --git a/src/com/android/gallery3d/util/IntArray.java b/src/com/android/gallery3d/util/IntArray.java
deleted file mode 100644
index 2c4dc2c..0000000
--- a/src/com/android/gallery3d/util/IntArray.java
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * Copyright (C) 2010 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.gallery3d.util;
-
-public class IntArray {
-    private static final int INIT_CAPACITY = 8;
-
-    private int mData[] = new int[INIT_CAPACITY];
-    private int mSize = 0;
-
-    public void add(int value) {
-        if (mData.length == mSize) {
-            int temp[] = new int[mSize + mSize];
-            System.arraycopy(mData, 0, temp, 0, mSize);
-            mData = temp;
-        }
-        mData[mSize++] = value;
-    }
-
-    public int removeLast() {
-        mSize--;
-        return mData[mSize];
-    }
-
-    public int size() {
-        return mSize;
-    }
-
-    // For testing only
-    public int[] toArray(int[] result) {
-        if (result == null || result.length < mSize) {
-            result = new int[mSize];
-        }
-        System.arraycopy(mData, 0, result, 0, mSize);
-        return result;
-    }
-
-    public int[] getInternalArray() {
-        return mData;
-    }
-
-    public void clear() {
-        mSize = 0;
-        if (mData.length != INIT_CAPACITY) mData = new int[INIT_CAPACITY];
-    }
-}
diff --git a/src/com/android/gallery3d/util/InterruptableOutputStream.java b/src/com/android/gallery3d/util/InterruptableOutputStream.java
deleted file mode 100644
index 1ab62ab..0000000
--- a/src/com/android/gallery3d/util/InterruptableOutputStream.java
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * Copyright (C) 2010 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.gallery3d.util;
-
-import com.android.gallery3d.common.Utils;
-
-import java.io.IOException;
-import java.io.InterruptedIOException;
-import java.io.OutputStream;
-
-public class InterruptableOutputStream extends OutputStream {
-
-    private static final int MAX_WRITE_BYTES = 4096;
-
-    private OutputStream mOutputStream;
-    private volatile boolean mIsInterrupted = false;
-
-    public InterruptableOutputStream(OutputStream outputStream) {
-        mOutputStream = Utils.checkNotNull(outputStream);
-    }
-
-    @Override
-    public void write(int oneByte) throws IOException {
-        if (mIsInterrupted) throw new InterruptedIOException();
-        mOutputStream.write(oneByte);
-    }
-
-    @Override
-    public void write(byte[] buffer, int offset, int count) throws IOException {
-        int end = offset + count;
-        while (offset < end) {
-            if (mIsInterrupted) throw new InterruptedIOException();
-            int bytesCount = Math.min(MAX_WRITE_BYTES, end - offset);
-            mOutputStream.write(buffer, offset, bytesCount);
-            offset += bytesCount;
-        }
-    }
-
-    @Override
-    public void close() throws IOException {
-        mOutputStream.close();
-    }
-
-    @Override
-    public void flush() throws IOException {
-        if (mIsInterrupted) throw new InterruptedIOException();
-        mOutputStream.flush();
-    }
-
-    public void interrupt() {
-        mIsInterrupted = true;
-    }
-}
diff --git a/src/com/android/gallery3d/util/JobLimiter.java b/src/com/android/gallery3d/util/JobLimiter.java
deleted file mode 100644
index 42b7541..0000000
--- a/src/com/android/gallery3d/util/JobLimiter.java
+++ /dev/null
@@ -1,159 +0,0 @@
-/*
- * Copyright (C) 2011 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.gallery3d.util;
-
-import com.android.gallery3d.common.Utils;
-import com.android.gallery3d.util.ThreadPool.Job;
-import com.android.gallery3d.util.ThreadPool.JobContext;
-
-import java.util.LinkedList;
-
-// Limit the number of concurrent jobs that has been submitted into a ThreadPool
-@SuppressWarnings("rawtypes")
-public class JobLimiter implements FutureListener {
-    private static final String TAG = "JobLimiter";
-
-    // State Transition:
-    //      INIT -> DONE, CANCELLED
-    //      DONE -> CANCELLED
-    private static final int STATE_INIT = 0;
-    private static final int STATE_DONE = 1;
-    private static final int STATE_CANCELLED = 2;
-
-    private final LinkedList<JobWrapper<?>> mJobs = new LinkedList<JobWrapper<?>>();
-    private final ThreadPool mPool;
-    private int mLimit;
-
-    private static class JobWrapper<T> implements Future<T>, Job<T> {
-        private int mState = STATE_INIT;
-        private Job<T> mJob;
-        private Future<T> mDelegate;
-        private FutureListener<T> mListener;
-        private T mResult;
-
-        public JobWrapper(Job<T> job, FutureListener<T> listener) {
-            mJob = job;
-            mListener = listener;
-        }
-
-        public synchronized void setFuture(Future<T> future) {
-            if (mState != STATE_INIT) return;
-            mDelegate = future;
-        }
-
-        @Override
-        public void cancel() {
-            FutureListener<T> listener = null;
-            synchronized (this) {
-                if (mState != STATE_DONE) {
-                    listener = mListener;
-                    mJob = null;
-                    mListener = null;
-                    if (mDelegate != null) {
-                        mDelegate.cancel();
-                        mDelegate = null;
-                    }
-                }
-                mState = STATE_CANCELLED;
-                mResult = null;
-                notifyAll();
-            }
-            if (listener != null) listener.onFutureDone(this);
-        }
-
-        @Override
-        public synchronized boolean isCancelled() {
-            return mState == STATE_CANCELLED;
-        }
-
-        @Override
-        public boolean isDone() {
-            // Both CANCELLED AND DONE is considered as done
-            return mState !=  STATE_INIT;
-        }
-
-        @Override
-        public synchronized T get() {
-            while (mState == STATE_INIT) {
-                // handle the interrupted exception of wait()
-                Utils.waitWithoutInterrupt(this);
-            }
-            return mResult;
-        }
-
-        @Override
-        public void waitDone() {
-            get();
-        }
-
-        @Override
-        public T run(JobContext jc) {
-            Job<T> job = null;
-            synchronized (this) {
-                if (mState == STATE_CANCELLED) return null;
-                job = mJob;
-            }
-            T result  = null;
-            try {
-                result = job.run(jc);
-            } catch (Throwable t) {
-                Log.w(TAG, "error executing job: " + job, t);
-            }
-            FutureListener<T> listener = null;
-            synchronized (this) {
-                if (mState == STATE_CANCELLED) return null;
-                mState = STATE_DONE;
-                listener = mListener;
-                mListener = null;
-                mJob = null;
-                mResult = result;
-                notifyAll();
-            }
-            if (listener != null) listener.onFutureDone(this);
-            return result;
-        }
-    }
-
-    public JobLimiter(ThreadPool pool, int limit) {
-        mPool = Utils.checkNotNull(pool);
-        mLimit = limit;
-    }
-
-    public synchronized <T> Future<T> submit(Job<T> job, FutureListener<T> listener) {
-        JobWrapper<T> future = new JobWrapper<T>(Utils.checkNotNull(job), listener);
-        mJobs.addLast(future);
-        submitTasksIfAllowed();
-        return future;
-    }
-
-    @SuppressWarnings({"rawtypes", "unchecked"})
-    private void submitTasksIfAllowed() {
-        while (mLimit > 0 && !mJobs.isEmpty()) {
-            JobWrapper wrapper = mJobs.removeFirst();
-            if (!wrapper.isCancelled()) {
-                --mLimit;
-                wrapper.setFuture(mPool.submit(wrapper, this));
-            }
-        }
-    }
-
-    @Override
-    public synchronized void onFutureDone(Future future) {
-        ++mLimit;
-        submitTasksIfAllowed();
-    }
-}
diff --git a/src/com/android/gallery3d/util/LinkedNode.java b/src/com/android/gallery3d/util/LinkedNode.java
deleted file mode 100644
index 4cfc3cd..0000000
--- a/src/com/android/gallery3d/util/LinkedNode.java
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * Copyright (C) 2010 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.gallery3d.util;
-
-
-public class LinkedNode {
-    private LinkedNode mPrev;
-    private LinkedNode mNext;
-
-    public LinkedNode() {
-        mPrev = mNext = this;
-    }
-
-    public void insert(LinkedNode node) {
-        node.mNext = mNext;
-        mNext.mPrev = node;
-        node.mPrev = this;
-        mNext = node;
-    }
-
-    public void remove() {
-        if (mNext == this) throw new IllegalStateException();
-        mPrev.mNext = mNext;
-        mNext.mPrev = mPrev;
-        mPrev = mNext = null;
-    }
-
-    @SuppressWarnings("unchecked")
-    public static class List<T extends LinkedNode> {
-        private LinkedNode mHead = new LinkedNode();
-
-        public void insertLast(T node) {
-            mHead.mPrev.insert(node);
-        }
-
-        public T getFirst() {
-            return (T) (mHead.mNext == mHead ? null : mHead.mNext);
-        }
-
-        public T getLast() {
-            return (T) (mHead.mPrev == mHead ? null : mHead.mPrev);
-        }
-
-        public T nextOf(T node) {
-            return (T) (node.mNext == mHead ? null : node.mNext);
-        }
-
-        public T previousOf(T node) {
-            return (T) (node.mPrev == mHead ? null : node.mPrev);
-        }
-
-    }
-
-    public static <T extends LinkedNode> List<T> newList() {
-        return new List<T>();
-    }
-}
diff --git a/src/com/android/gallery3d/util/Log.java b/src/com/android/gallery3d/util/Log.java
deleted file mode 100644
index d7f8e85..0000000
--- a/src/com/android/gallery3d/util/Log.java
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Copyright (C) 2010 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.gallery3d.util;
-
-public class Log {
-    public static int v(String tag, String msg) {
-        return android.util.Log.v(tag, msg);
-    }
-    public static int v(String tag, String msg, Throwable tr) {
-        return android.util.Log.v(tag, msg, tr);
-    }
-    public static int d(String tag, String msg) {
-        return android.util.Log.d(tag, msg);
-    }
-    public static int d(String tag, String msg, Throwable tr) {
-        return android.util.Log.d(tag, msg, tr);
-    }
-    public static int i(String tag, String msg) {
-        return android.util.Log.i(tag, msg);
-    }
-    public static int i(String tag, String msg, Throwable tr) {
-        return android.util.Log.i(tag, msg, tr);
-    }
-    public static int w(String tag, String msg) {
-        return android.util.Log.w(tag, msg);
-    }
-    public static int w(String tag, String msg, Throwable tr) {
-        return android.util.Log.w(tag, msg, tr);
-    }
-    public static int w(String tag, Throwable tr) {
-        return android.util.Log.w(tag, tr);
-    }
-    public static int e(String tag, String msg) {
-        return android.util.Log.e(tag, msg);
-    }
-    public static int e(String tag, String msg, Throwable tr) {
-        return android.util.Log.e(tag, msg, tr);
-    }
-}
diff --git a/src/com/android/gallery3d/util/MediaSetUtils.java b/src/com/android/gallery3d/util/MediaSetUtils.java
deleted file mode 100644
index 0438005..0000000
--- a/src/com/android/gallery3d/util/MediaSetUtils.java
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * Copyright (C) 2010 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.gallery3d.util;
-
-import android.os.Environment;
-
-import com.android.gallery3d.data.LocalAlbum;
-import com.android.gallery3d.data.LocalMergeAlbum;
-import com.android.gallery3d.data.MediaSet;
-import com.android.gallery3d.data.Path;
-
-import java.util.Comparator;
-
-public class MediaSetUtils {
-    public static final Comparator<MediaSet> NAME_COMPARATOR = new NameComparator();
-
-    public static final int CAMERA_BUCKET_ID = GalleryUtils.getBucketId(
-            Environment.getExternalStorageDirectory().toString() + "/"
-            + BucketNames.CAMERA);
-    public static final int DOWNLOAD_BUCKET_ID = GalleryUtils.getBucketId(
-            Environment.getExternalStorageDirectory().toString() + "/"
-            + BucketNames.DOWNLOAD);
-    public static final int EDITED_ONLINE_PHOTOS_BUCKET_ID = GalleryUtils.getBucketId(
-            Environment.getExternalStorageDirectory().toString() + "/"
-            + BucketNames.EDITED_ONLINE_PHOTOS);
-    public static final int IMPORTED_BUCKET_ID = GalleryUtils.getBucketId(
-            Environment.getExternalStorageDirectory().toString() + "/"
-            + BucketNames.IMPORTED);
-    public static final int SNAPSHOT_BUCKET_ID = GalleryUtils.getBucketId(
-            Environment.getExternalStorageDirectory().toString() +
-            "/" + BucketNames.SCREENSHOTS);
-
-    private static final Path[] CAMERA_PATHS = {
-            Path.fromString("/local/all/" + CAMERA_BUCKET_ID),
-            Path.fromString("/local/image/" + CAMERA_BUCKET_ID),
-            Path.fromString("/local/video/" + CAMERA_BUCKET_ID)};
-
-    public static boolean isCameraSource(Path path) {
-        return CAMERA_PATHS[0] == path || CAMERA_PATHS[1] == path
-                || CAMERA_PATHS[2] == path;
-    }
-
-    // Sort MediaSets by name
-    public static class NameComparator implements Comparator<MediaSet> {
-        @Override
-        public int compare(MediaSet set1, MediaSet set2) {
-            int result = set1.getName().compareToIgnoreCase(set2.getName());
-            if (result != 0) return result;
-            return set1.getPath().toString().compareTo(set2.getPath().toString());
-        }
-    }
-}
diff --git a/src/com/android/gallery3d/util/MotionEventHelper.java b/src/com/android/gallery3d/util/MotionEventHelper.java
deleted file mode 100644
index 715f7fa..0000000
--- a/src/com/android/gallery3d/util/MotionEventHelper.java
+++ /dev/null
@@ -1,120 +0,0 @@
-/*
- * 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.gallery3d.util;
-
-import android.annotation.TargetApi;
-import android.graphics.Matrix;
-import android.util.FloatMath;
-import android.view.MotionEvent;
-import android.view.MotionEvent.PointerCoords;
-
-import com.android.gallery3d.common.ApiHelper;
-
-public final class MotionEventHelper {
-    private MotionEventHelper() {}
-
-    public static MotionEvent transformEvent(MotionEvent e, Matrix m) {
-        // We try to use the new transform method if possible because it uses
-        // less memory.
-        if (ApiHelper.HAS_MOTION_EVENT_TRANSFORM) {
-            return transformEventNew(e, m);
-        } else {
-            return transformEventOld(e, m);
-        }
-    }
-
-    @TargetApi(ApiHelper.VERSION_CODES.HONEYCOMB)
-    private static MotionEvent transformEventNew(MotionEvent e, Matrix m) {
-        MotionEvent newEvent = MotionEvent.obtain(e);
-        newEvent.transform(m);
-        return newEvent;
-    }
-
-    // This is copied from Input.cpp in the android framework.
-    private static MotionEvent transformEventOld(MotionEvent e, Matrix m) {
-        long downTime = e.getDownTime();
-        long eventTime = e.getEventTime();
-        int action = e.getAction();
-        int pointerCount = e.getPointerCount();
-        int[] pointerIds = getPointerIds(e);
-        PointerCoords[] pointerCoords = getPointerCoords(e);
-        int metaState = e.getMetaState();
-        float xPrecision = e.getXPrecision();
-        float yPrecision = e.getYPrecision();
-        int deviceId = e.getDeviceId();
-        int edgeFlags = e.getEdgeFlags();
-        int source = e.getSource();
-        int flags = e.getFlags();
-
-        // Copy the x and y coordinates into an array, map them, and copy back.
-        float[] xy = new float[pointerCoords.length * 2];
-        for (int i = 0; i < pointerCount;i++) {
-            xy[2 * i] = pointerCoords[i].x;
-            xy[2 * i + 1] = pointerCoords[i].y;
-        }
-        m.mapPoints(xy);
-        for (int i = 0; i < pointerCount;i++) {
-            pointerCoords[i].x = xy[2 * i];
-            pointerCoords[i].y = xy[2 * i + 1];
-            pointerCoords[i].orientation = transformAngle(
-                m, pointerCoords[i].orientation);
-        }
-
-        MotionEvent n = MotionEvent.obtain(downTime, eventTime, action,
-                pointerCount, pointerIds, pointerCoords, metaState, xPrecision,
-                yPrecision, deviceId, edgeFlags, source, flags);
-
-        return n;
-    }
-
-    private static int[] getPointerIds(MotionEvent e) {
-        int n = e.getPointerCount();
-        int[] r = new int[n];
-        for (int i = 0; i < n; i++) {
-            r[i] = e.getPointerId(i);
-        }
-        return r;
-    }
-
-    private static PointerCoords[] getPointerCoords(MotionEvent e) {
-        int n = e.getPointerCount();
-        PointerCoords[] r = new PointerCoords[n];
-        for (int i = 0; i < n; i++) {
-            r[i] = new PointerCoords();
-            e.getPointerCoords(i, r[i]);
-        }
-        return r;
-    }
-
-    private static float transformAngle(Matrix m, float angleRadians) {
-        // Construct and transform a vector oriented at the specified clockwise
-        // angle from vertical.  Coordinate system: down is increasing Y, right is
-        // increasing X.
-        float[] v = new float[2];
-        v[0] = FloatMath.sin(angleRadians);
-        v[1] = -FloatMath.cos(angleRadians);
-        m.mapVectors(v);
-
-        // Derive the transformed vector's clockwise angle from vertical.
-        float result = (float) Math.atan2(v[0], -v[1]);
-        if (result < -Math.PI / 2) {
-            result += Math.PI;
-        } else if (result > Math.PI / 2) {
-            result -= Math.PI;
-        }
-        return result;
-    }
-}
diff --git a/src/com/android/gallery3d/util/Profile.java b/src/com/android/gallery3d/util/Profile.java
deleted file mode 100644
index 7ed72c9..0000000
--- a/src/com/android/gallery3d/util/Profile.java
+++ /dev/null
@@ -1,226 +0,0 @@
-/*
- * 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.gallery3d.util;
-
-import android.os.Handler;
-import android.os.HandlerThread;
-import android.os.Process;
-
-import java.util.ArrayList;
-import java.util.Random;
-
-// The Profile class is used to collect profiling information for a thread. It
-// samples stack traces for a thread periodically. enable() and disable() is
-// used to enable and disable profiling for the calling thread. The profiling
-// information can then be dumped to a file using the dumpToFile() method.
-//
-// The disableAll() method can be used to disable profiling for all threads and
-// can be called in onPause() to ensure all profiling is disabled when an
-// activity is paused.
-public class Profile {
-    @SuppressWarnings("unused")
-    private static final String TAG = "Profile";
-    private static final int NS_PER_MS = 1000000;
-
-    // This is a watchdog entry for one thread.
-    // For every cycleTime period, we dump the stack of the thread.
-    private static class WatchEntry {
-        Thread thread;
-
-        // Both are in milliseconds
-        int cycleTime;
-        int wakeTime;
-
-        boolean isHolding;
-        ArrayList<String[]> holdingStacks = new ArrayList<String[]>();
-    }
-
-    // This is a watchdog thread which dumps stacks of other threads periodically.
-    private static Watchdog sWatchdog = new Watchdog();
-
-    private static class Watchdog {
-        private ArrayList<WatchEntry> mList = new ArrayList<WatchEntry>();
-        private HandlerThread mHandlerThread;
-        private Handler mHandler;
-        private Runnable mProcessRunnable = new Runnable() {
-            @Override
-            public void run() {
-                synchronized (Watchdog.this) {
-                    processList();
-                }
-            }
-        };
-        private Random mRandom = new Random();
-        private ProfileData mProfileData = new ProfileData();
-
-        public Watchdog() {
-            mHandlerThread = new HandlerThread("Watchdog Handler",
-                    Process.THREAD_PRIORITY_FOREGROUND);
-            mHandlerThread.start();
-            mHandler = new Handler(mHandlerThread.getLooper());
-        }
-
-        public synchronized void addWatchEntry(Thread thread, int cycleTime) {
-            WatchEntry e = new WatchEntry();
-            e.thread = thread;
-            e.cycleTime = cycleTime;
-            int firstDelay = 1 + mRandom.nextInt(cycleTime);
-            e.wakeTime = (int) (System.nanoTime() / NS_PER_MS) + firstDelay;
-            mList.add(e);
-            processList();
-        }
-
-        public synchronized void removeWatchEntry(Thread thread) {
-            for (int i = 0; i < mList.size(); i++) {
-                if (mList.get(i).thread == thread) {
-                    mList.remove(i);
-                    break;
-                }
-            }
-            processList();
-        }
-
-        public synchronized void removeAllWatchEntries() {
-            mList.clear();
-            processList();
-        }
-
-        private void processList() {
-            mHandler.removeCallbacks(mProcessRunnable);
-            if (mList.size() == 0) return;
-
-            int currentTime = (int) (System.nanoTime() / NS_PER_MS);
-            int nextWakeTime = 0;
-
-            for (WatchEntry entry : mList) {
-                if (currentTime > entry.wakeTime) {
-                    entry.wakeTime += entry.cycleTime;
-                    Thread thread = entry.thread;
-                    sampleStack(entry);
-                }
-
-                if (entry.wakeTime > nextWakeTime) {
-                    nextWakeTime = entry.wakeTime;
-                }
-            }
-
-            long delay = nextWakeTime - currentTime;
-            mHandler.postDelayed(mProcessRunnable, delay);
-        }
-
-        private void sampleStack(WatchEntry entry) {
-            Thread thread = entry.thread;
-            StackTraceElement[] stack = thread.getStackTrace();
-            String[] lines = new String[stack.length];
-            for (int i = 0; i < stack.length; i++) {
-                lines[i] = stack[i].toString();
-            }
-            if (entry.isHolding) {
-                entry.holdingStacks.add(lines);
-            } else {
-                mProfileData.addSample(lines);
-            }
-        }
-
-        private WatchEntry findEntry(Thread thread) {
-            for (int i = 0; i < mList.size(); i++) {
-                WatchEntry entry = mList.get(i);
-                if (entry.thread == thread) return entry;
-            }
-            return null;
-        }
-
-        public synchronized void dumpToFile(String filename) {
-            mProfileData.dumpToFile(filename);
-        }
-
-        public synchronized void reset() {
-            mProfileData.reset();
-        }
-
-        public synchronized void hold(Thread t) {
-            WatchEntry entry = findEntry(t);
-
-            // This can happen if the profiling is disabled (probably from
-            // another thread). Same check is applied in commit() and drop()
-            // below.
-            if (entry == null) return;
-
-            entry.isHolding = true;
-        }
-
-        public synchronized void commit(Thread t) {
-            WatchEntry entry = findEntry(t);
-            if (entry == null) return;
-            ArrayList<String[]> stacks = entry.holdingStacks;
-            for (int i = 0; i < stacks.size(); i++) {
-                mProfileData.addSample(stacks.get(i));
-            }
-            entry.isHolding = false;
-            entry.holdingStacks.clear();
-        }
-
-        public synchronized void drop(Thread t) {
-            WatchEntry entry = findEntry(t);
-            if (entry == null) return;
-            entry.isHolding = false;
-            entry.holdingStacks.clear();
-        }
-    }
-
-    // Enable profiling for the calling thread. Periodically (every cycleTimeInMs
-    // milliseconds) sample the stack trace of the calling thread.
-    public static void enable(int cycleTimeInMs) {
-        Thread t = Thread.currentThread();
-        sWatchdog.addWatchEntry(t, cycleTimeInMs);
-    }
-
-    // Disable profiling for the calling thread.
-    public static void disable() {
-        sWatchdog.removeWatchEntry(Thread.currentThread());
-    }
-
-    // Disable profiling for all threads.
-    public static void disableAll() {
-        sWatchdog.removeAllWatchEntries();
-    }
-
-    // Dump the profiling data to a file.
-    public static void dumpToFile(String filename) {
-        sWatchdog.dumpToFile(filename);
-    }
-
-    // Reset the collected profiling data.
-    public static void reset() {
-        sWatchdog.reset();
-    }
-
-    // Hold the future samples coming from current thread until commit() or
-    // drop() is called, and those samples are recorded or ignored as a result.
-    // This must called after enable() to be effective.
-    public static void hold() {
-        sWatchdog.hold(Thread.currentThread());
-    }
-
-    public static void commit() {
-        sWatchdog.commit(Thread.currentThread());
-    }
-
-    public static void drop() {
-        sWatchdog.drop(Thread.currentThread());
-    }
-}
diff --git a/src/com/android/gallery3d/util/ProfileData.java b/src/com/android/gallery3d/util/ProfileData.java
deleted file mode 100644
index a1bb8e1..0000000
--- a/src/com/android/gallery3d/util/ProfileData.java
+++ /dev/null
@@ -1,168 +0,0 @@
-/*
- * 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.gallery3d.util;
-
-import android.util.Log;
-
-import com.android.gallery3d.common.Utils;
-
-import java.io.DataOutputStream;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.Map.Entry;
-
-// ProfileData keeps profiling samples in a tree structure.
-// The addSample() method adds a sample. The dumpToFile() method saves the data
-// to a file. The reset() method clears all samples.
-public class ProfileData {
-    @SuppressWarnings("unused")
-    private static final String TAG = "ProfileData";
-
-    private static class Node {
-        public int id;  // this is the name of this node, mapped from mNameToId
-        public Node parent;
-        public int sampleCount;
-        public ArrayList<Node> children;
-        public Node(Node parent, int id) {
-            this.parent = parent;
-            this.id = id;
-        }
-    }
-
-    private Node mRoot;
-    private int mNextId;
-    private HashMap<String, Integer> mNameToId;
-    private DataOutputStream mOut;
-    private byte mScratch[] = new byte[4];  // scratch space for writeInt()
-
-    public ProfileData() {
-        mRoot = new Node(null, -1);  // The id of the root node is unused.
-        mNameToId = new HashMap<String, Integer>();
-    }
-
-    public void reset() {
-        mRoot = new Node(null, -1);
-        mNameToId.clear();
-        mNextId = 0;
-    }
-
-    private int nameToId(String name) {
-        Integer id = mNameToId.get(name);
-        if (id == null) {
-            id = ++mNextId;  // The tool doesn't want id=0, so we start from 1.
-            mNameToId.put(name, id);
-        }
-        return id;
-    }
-
-    public void addSample(String[] stack) {
-        int[] ids = new int[stack.length];
-        for (int i = 0; i < stack.length; i++) {
-            ids[i] = nameToId(stack[i]);
-        }
-
-        Node node = mRoot;
-        for (int i = stack.length - 1; i >= 0; i--) {
-            if (node.children == null) {
-                node.children = new ArrayList<Node>();
-            }
-
-            int id = ids[i];
-            ArrayList<Node> children = node.children;
-            int j;
-            for (j = 0; j < children.size(); j++) {
-                if (children.get(j).id == id) break;
-            }
-            if (j == children.size()) {
-                children.add(new Node(node, id));
-            }
-
-            node = children.get(j);
-        }
-
-        node.sampleCount++;
-    }
-
-    public void dumpToFile(String filename) {
-        try {
-            mOut = new DataOutputStream(new FileOutputStream(filename));
-            // Start record
-            writeInt(0);
-            writeInt(3);
-            writeInt(1);
-            writeInt(20000);  // Sampling period: 20ms
-            writeInt(0);
-
-            // Samples
-            writeAllStacks(mRoot, 0);
-
-            // End record
-            writeInt(0);
-            writeInt(1);
-            writeInt(0);
-            writeAllSymbols();
-        } catch (IOException ex) {
-            Log.w("Failed to dump to file", ex);
-        } finally {
-            Utils.closeSilently(mOut);
-        }
-    }
-
-    // Writes out one stack, consisting of N+2 words:
-    // first word: sample count
-    // second word: depth of the stack (N)
-    // N words: each word is the id of one address in the stack
-    private void writeOneStack(Node node, int depth) throws IOException {
-        writeInt(node.sampleCount);
-        writeInt(depth);
-        while (depth-- > 0) {
-            writeInt(node.id);
-            node = node.parent;
-        }
-    }
-
-    private void writeAllStacks(Node node, int depth) throws IOException {
-        if (node.sampleCount > 0) {
-            writeOneStack(node, depth);
-        }
-
-        ArrayList<Node> children = node.children;
-        if (children != null) {
-            for (int i = 0; i < children.size(); i++) {
-                writeAllStacks(children.get(i), depth + 1);
-            }
-        }
-    }
-
-    // Writes out the symbol table. Each line is like:
-    // 0x17e java.util.ArrayList.isEmpty(ArrayList.java:319)
-    private void writeAllSymbols() throws IOException {
-        for (Entry<String, Integer> entry : mNameToId.entrySet()) {
-            mOut.writeBytes(String.format("0x%x %s\n", entry.getValue(), entry.getKey()));
-        }
-    }
-
-    private void writeInt(int v) throws IOException {
-        mScratch[0] = (byte) v;
-        mScratch[1] = (byte) (v >> 8);
-        mScratch[2] = (byte) (v >> 16);
-        mScratch[3] = (byte) (v >> 24);
-        mOut.write(mScratch);
-    }
-}
diff --git a/src/com/android/gallery3d/util/RangeArray.java b/src/com/android/gallery3d/util/RangeArray.java
deleted file mode 100644
index 8e61348..0000000
--- a/src/com/android/gallery3d/util/RangeArray.java
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * 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.gallery3d.util;
-
-// This is an array whose index ranges from min to max (inclusive).
-public class RangeArray<T> {
-    private T[] mData;
-    private int mOffset;
-
-    public RangeArray(int min, int max) {
-        mData = (T[]) new Object[max - min + 1];
-        mOffset = min;
-    }
-
-    // Wraps around an existing array
-    public RangeArray(T[] src, int min, int max) {
-        if (max - min + 1 != src.length) {
-            throw new AssertionError();
-        }
-        mData = src;
-        mOffset = min;
-    }
-
-    public void put(int i, T object) {
-        mData[i - mOffset] = object;
-    }
-
-    public T get(int i) {
-        return mData[i - mOffset];
-    }
-
-    public int indexOf(T object) {
-        for (int i = 0; i < mData.length; i++) {
-            if (mData[i] == object) return i + mOffset;
-        }
-        return Integer.MAX_VALUE;
-    }
-}
diff --git a/src/com/android/gallery3d/util/RangeBoolArray.java b/src/com/android/gallery3d/util/RangeBoolArray.java
deleted file mode 100644
index 035fc40..0000000
--- a/src/com/android/gallery3d/util/RangeBoolArray.java
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * 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.gallery3d.util;
-
-// This is an array whose index ranges from min to max (inclusive).
-public class RangeBoolArray {
-    private boolean[] mData;
-    private int mOffset;
-
-    public RangeBoolArray(int min, int max) {
-        mData = new boolean[max - min + 1];
-        mOffset = min;
-    }
-
-    // Wraps around an existing array
-    public RangeBoolArray(boolean[] src, int min, int max) {
-        mData = src;
-        mOffset = min;
-    }
-
-    public void put(int i, boolean object) {
-        mData[i - mOffset] = object;
-    }
-
-    public boolean get(int i) {
-        return mData[i - mOffset];
-    }
-
-    public int indexOf(boolean object) {
-        for (int i = 0; i < mData.length; i++) {
-            if (mData[i] == object) return i + mOffset;
-        }
-        return Integer.MAX_VALUE;
-    }
-}
diff --git a/src/com/android/gallery3d/util/RangeIntArray.java b/src/com/android/gallery3d/util/RangeIntArray.java
deleted file mode 100644
index 9dbb99f..0000000
--- a/src/com/android/gallery3d/util/RangeIntArray.java
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * 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.gallery3d.util;
-
-// This is an array whose index ranges from min to max (inclusive).
-public class RangeIntArray {
-    private int[] mData;
-    private int mOffset;
-
-    public RangeIntArray(int min, int max) {
-        mData = new int[max - min + 1];
-        mOffset = min;
-    }
-
-    // Wraps around an existing array
-    public RangeIntArray(int[] src, int min, int max) {
-        mData = src;
-        mOffset = min;
-    }
-
-    public void put(int i, int object) {
-        mData[i - mOffset] = object;
-    }
-
-    public int get(int i) {
-        return mData[i - mOffset];
-    }
-
-    public int indexOf(int object) {
-        for (int i = 0; i < mData.length; i++) {
-            if (mData[i] == object) return i + mOffset;
-        }
-        return Integer.MAX_VALUE;
-    }
-}
diff --git a/src/com/android/gallery3d/util/ReverseGeocoder.java b/src/com/android/gallery3d/util/ReverseGeocoder.java
deleted file mode 100644
index a8b26d9..0000000
--- a/src/com/android/gallery3d/util/ReverseGeocoder.java
+++ /dev/null
@@ -1,418 +0,0 @@
-/*
- * Copyright (C) 2010 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.gallery3d.util;
-
-import android.content.Context;
-import android.location.Address;
-import android.location.Geocoder;
-import android.location.Location;
-import android.location.LocationManager;
-import android.net.ConnectivityManager;
-import android.net.NetworkInfo;
-
-import com.android.gallery3d.common.BlobCache;
-
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.DataInputStream;
-import java.io.DataOutputStream;
-import java.io.IOException;
-import java.util.List;
-import java.util.Locale;
-
-public class ReverseGeocoder {
-    @SuppressWarnings("unused")
-    private static final String TAG = "ReverseGeocoder";
-    public static final int EARTH_RADIUS_METERS = 6378137;
-    public static final int LAT_MIN = -90;
-    public static final int LAT_MAX = 90;
-    public static final int LON_MIN = -180;
-    public static final int LON_MAX = 180;
-    private static final int MAX_COUNTRY_NAME_LENGTH = 8;
-    // If two points are within 20 miles of each other, use
-    // "Around Palo Alto, CA" or "Around Mountain View, CA".
-    // instead of directly jumping to the next level and saying
-    // "California, US".
-    private static final int MAX_LOCALITY_MILE_RANGE = 20;
-
-    private static final String GEO_CACHE_FILE = "rev_geocoding";
-    private static final int GEO_CACHE_MAX_ENTRIES = 1000;
-    private static final int GEO_CACHE_MAX_BYTES = 500 * 1024;
-    private static final int GEO_CACHE_VERSION = 0;
-
-    public static class SetLatLong {
-        // The latitude and longitude of the min latitude point.
-        public double mMinLatLatitude = LAT_MAX;
-        public double mMinLatLongitude;
-        // The latitude and longitude of the max latitude point.
-        public double mMaxLatLatitude = LAT_MIN;
-        public double mMaxLatLongitude;
-        // The latitude and longitude of the min longitude point.
-        public double mMinLonLatitude;
-        public double mMinLonLongitude = LON_MAX;
-        // The latitude and longitude of the max longitude point.
-        public double mMaxLonLatitude;
-        public double mMaxLonLongitude = LON_MIN;
-    }
-
-    private Context mContext;
-    private Geocoder mGeocoder;
-    private BlobCache mGeoCache;
-    private ConnectivityManager mConnectivityManager;
-    private static Address sCurrentAddress; // last known address
-
-    public ReverseGeocoder(Context context) {
-        mContext = context;
-        mGeocoder = new Geocoder(mContext);
-        mGeoCache = CacheManager.getCache(context, GEO_CACHE_FILE,
-                GEO_CACHE_MAX_ENTRIES, GEO_CACHE_MAX_BYTES,
-                GEO_CACHE_VERSION);
-        mConnectivityManager = (ConnectivityManager)
-                context.getSystemService(Context.CONNECTIVITY_SERVICE);
-    }
-
-    public String computeAddress(SetLatLong set) {
-        // The overall min and max latitudes and longitudes of the set.
-        double setMinLatitude = set.mMinLatLatitude;
-        double setMinLongitude = set.mMinLatLongitude;
-        double setMaxLatitude = set.mMaxLatLatitude;
-        double setMaxLongitude = set.mMaxLatLongitude;
-        if (Math.abs(set.mMaxLatLatitude - set.mMinLatLatitude)
-                < Math.abs(set.mMaxLonLongitude - set.mMinLonLongitude)) {
-            setMinLatitude = set.mMinLonLatitude;
-            setMinLongitude = set.mMinLonLongitude;
-            setMaxLatitude = set.mMaxLonLatitude;
-            setMaxLongitude = set.mMaxLonLongitude;
-        }
-        Address addr1 = lookupAddress(setMinLatitude, setMinLongitude, true);
-        Address addr2 = lookupAddress(setMaxLatitude, setMaxLongitude, true);
-        if (addr1 == null)
-            addr1 = addr2;
-        if (addr2 == null)
-            addr2 = addr1;
-        if (addr1 == null || addr2 == null) {
-            return null;
-        }
-
-        // Get current location, we decide the granularity of the string based
-        // on this.
-        LocationManager locationManager =
-                (LocationManager) mContext.getSystemService(Context.LOCATION_SERVICE);
-        Location location = null;
-        List<String> providers = locationManager.getAllProviders();
-        for (int i = 0; i < providers.size(); ++i) {
-            String provider = providers.get(i);
-            location = (provider != null) ? locationManager.getLastKnownLocation(provider) : null;
-            if (location != null)
-                break;
-        }
-        String currentCity = "";
-        String currentAdminArea = "";
-        String currentCountry = Locale.getDefault().getCountry();
-        if (location != null) {
-            Address currentAddress = lookupAddress(
-                    location.getLatitude(), location.getLongitude(), true);
-            if (currentAddress == null) {
-                currentAddress = sCurrentAddress;
-            } else {
-                sCurrentAddress = currentAddress;
-            }
-            if (currentAddress != null && currentAddress.getCountryCode() != null) {
-                currentCity = checkNull(currentAddress.getLocality());
-                currentCountry = checkNull(currentAddress.getCountryCode());
-                currentAdminArea = checkNull(currentAddress.getAdminArea());
-            }
-        }
-
-        String closestCommonLocation = null;
-        String addr1Locality = checkNull(addr1.getLocality());
-        String addr2Locality = checkNull(addr2.getLocality());
-        String addr1AdminArea = checkNull(addr1.getAdminArea());
-        String addr2AdminArea = checkNull(addr2.getAdminArea());
-        String addr1CountryCode = checkNull(addr1.getCountryCode());
-        String addr2CountryCode = checkNull(addr2.getCountryCode());
-
-        if (currentCity.equals(addr1Locality) || currentCity.equals(addr2Locality)) {
-            String otherCity = currentCity;
-            if (currentCity.equals(addr1Locality)) {
-                otherCity = addr2Locality;
-                if (otherCity.length() == 0) {
-                    otherCity = addr2AdminArea;
-                    if (!currentCountry.equals(addr2CountryCode)) {
-                        otherCity += " " + addr2CountryCode;
-                    }
-                }
-                addr2Locality = addr1Locality;
-                addr2AdminArea = addr1AdminArea;
-                addr2CountryCode = addr1CountryCode;
-            } else {
-                otherCity = addr1Locality;
-                if (otherCity.length() == 0) {
-                    otherCity = addr1AdminArea;
-                    if (!currentCountry.equals(addr1CountryCode)) {
-                        otherCity += " " + addr1CountryCode;
-                    }
-                }
-                addr1Locality = addr2Locality;
-                addr1AdminArea = addr2AdminArea;
-                addr1CountryCode = addr2CountryCode;
-            }
-            closestCommonLocation = valueIfEqual(addr1.getAddressLine(0), addr2.getAddressLine(0));
-            if (closestCommonLocation != null && !("null".equals(closestCommonLocation))) {
-                if (!currentCity.equals(otherCity)) {
-                    closestCommonLocation += " - " + otherCity;
-                }
-                return closestCommonLocation;
-            }
-
-            // Compare thoroughfare (street address) next.
-            closestCommonLocation = valueIfEqual(addr1.getThoroughfare(), addr2.getThoroughfare());
-            if (closestCommonLocation != null && !("null".equals(closestCommonLocation))) {
-                return closestCommonLocation;
-            }
-        }
-
-        // Compare the locality.
-        closestCommonLocation = valueIfEqual(addr1Locality, addr2Locality);
-        if (closestCommonLocation != null && !("".equals(closestCommonLocation))) {
-            String adminArea = addr1AdminArea;
-            String countryCode = addr1CountryCode;
-            if (adminArea != null && adminArea.length() > 0) {
-                if (!countryCode.equals(currentCountry)) {
-                    closestCommonLocation += ", " + adminArea + " " + countryCode;
-                } else {
-                    closestCommonLocation += ", " + adminArea;
-                }
-            }
-            return closestCommonLocation;
-        }
-
-        // If the admin area is the same as the current location, we hide it and
-        // instead show the city name.
-        if (currentAdminArea.equals(addr1AdminArea) && currentAdminArea.equals(addr2AdminArea)) {
-            if ("".equals(addr1Locality)) {
-                addr1Locality = addr2Locality;
-            }
-            if ("".equals(addr2Locality)) {
-                addr2Locality = addr1Locality;
-            }
-            if (!"".equals(addr1Locality)) {
-                if (addr1Locality.equals(addr2Locality)) {
-                    closestCommonLocation = addr1Locality + ", " + currentAdminArea;
-                } else {
-                    closestCommonLocation = addr1Locality + " - " + addr2Locality;
-                }
-                return closestCommonLocation;
-            }
-        }
-
-        // Just choose one of the localities if within a MAX_LOCALITY_MILE_RANGE
-        // mile radius.
-        float[] distanceFloat = new float[1];
-        Location.distanceBetween(setMinLatitude, setMinLongitude,
-                setMaxLatitude, setMaxLongitude, distanceFloat);
-        int distance = (int) GalleryUtils.toMile(distanceFloat[0]);
-        if (distance < MAX_LOCALITY_MILE_RANGE) {
-            // Try each of the points and just return the first one to have a
-            // valid address.
-            closestCommonLocation = getLocalityAdminForAddress(addr1, true);
-            if (closestCommonLocation != null) {
-                return closestCommonLocation;
-            }
-            closestCommonLocation = getLocalityAdminForAddress(addr2, true);
-            if (closestCommonLocation != null) {
-                return closestCommonLocation;
-            }
-        }
-
-        // Check the administrative area.
-        closestCommonLocation = valueIfEqual(addr1AdminArea, addr2AdminArea);
-        if (closestCommonLocation != null && !("".equals(closestCommonLocation))) {
-            String countryCode = addr1CountryCode;
-            if (!countryCode.equals(currentCountry)) {
-                if (countryCode != null && countryCode.length() > 0) {
-                    closestCommonLocation += " " + countryCode;
-                }
-            }
-            return closestCommonLocation;
-        }
-
-        // Check the country codes.
-        closestCommonLocation = valueIfEqual(addr1CountryCode, addr2CountryCode);
-        if (closestCommonLocation != null && !("".equals(closestCommonLocation))) {
-            return closestCommonLocation;
-        }
-        // There is no intersection, let's choose a nicer name.
-        String addr1Country = addr1.getCountryName();
-        String addr2Country = addr2.getCountryName();
-        if (addr1Country == null)
-            addr1Country = addr1CountryCode;
-        if (addr2Country == null)
-            addr2Country = addr2CountryCode;
-        if (addr1Country == null || addr2Country == null)
-            return null;
-        if (addr1Country.length() > MAX_COUNTRY_NAME_LENGTH || addr2Country.length() > MAX_COUNTRY_NAME_LENGTH) {
-            closestCommonLocation = addr1CountryCode + " - " + addr2CountryCode;
-        } else {
-            closestCommonLocation = addr1Country + " - " + addr2Country;
-        }
-        return closestCommonLocation;
-    }
-
-    private String checkNull(String locality) {
-        if (locality == null)
-            return "";
-        if (locality.equals("null"))
-            return "";
-        return locality;
-    }
-
-    private String getLocalityAdminForAddress(final Address addr, final boolean approxLocation) {
-        if (addr == null)
-            return "";
-        String localityAdminStr = addr.getLocality();
-        if (localityAdminStr != null && !("null".equals(localityAdminStr))) {
-            if (approxLocation) {
-                // TODO: Uncomment these lines as soon as we may translations
-                // for Res.string.around.
-                // localityAdminStr =
-                // mContext.getResources().getString(Res.string.around) + " " +
-                // localityAdminStr;
-            }
-            String adminArea = addr.getAdminArea();
-            if (adminArea != null && adminArea.length() > 0) {
-                localityAdminStr += ", " + adminArea;
-            }
-            return localityAdminStr;
-        }
-        return null;
-    }
-
-    public Address lookupAddress(final double latitude, final double longitude,
-            boolean useCache) {
-        try {
-            long locationKey = (long) (((latitude + LAT_MAX) * 2 * LAT_MAX
-                    + (longitude + LON_MAX)) * EARTH_RADIUS_METERS);
-            byte[] cachedLocation = null;
-            if (useCache && mGeoCache != null) {
-                cachedLocation = mGeoCache.lookup(locationKey);
-            }
-            Address address = null;
-            NetworkInfo networkInfo = mConnectivityManager.getActiveNetworkInfo();
-            if (cachedLocation == null || cachedLocation.length == 0) {
-                if (networkInfo == null || !networkInfo.isConnected()) {
-                    return null;
-                }
-                List<Address> addresses = mGeocoder.getFromLocation(latitude, longitude, 1);
-                if (!addresses.isEmpty()) {
-                    address = addresses.get(0);
-                    ByteArrayOutputStream bos = new ByteArrayOutputStream();
-                    DataOutputStream dos = new DataOutputStream(bos);
-                    Locale locale = address.getLocale();
-                    writeUTF(dos, locale.getLanguage());
-                    writeUTF(dos, locale.getCountry());
-                    writeUTF(dos, locale.getVariant());
-
-                    writeUTF(dos, address.getThoroughfare());
-                    int numAddressLines = address.getMaxAddressLineIndex();
-                    dos.writeInt(numAddressLines);
-                    for (int i = 0; i < numAddressLines; ++i) {
-                        writeUTF(dos, address.getAddressLine(i));
-                    }
-                    writeUTF(dos, address.getFeatureName());
-                    writeUTF(dos, address.getLocality());
-                    writeUTF(dos, address.getAdminArea());
-                    writeUTF(dos, address.getSubAdminArea());
-
-                    writeUTF(dos, address.getCountryName());
-                    writeUTF(dos, address.getCountryCode());
-                    writeUTF(dos, address.getPostalCode());
-                    writeUTF(dos, address.getPhone());
-                    writeUTF(dos, address.getUrl());
-
-                    dos.flush();
-                    if (mGeoCache != null) {
-                        mGeoCache.insert(locationKey, bos.toByteArray());
-                    }
-                    dos.close();
-                }
-            } else {
-                // Parsing the address from the byte stream.
-                DataInputStream dis = new DataInputStream(
-                        new ByteArrayInputStream(cachedLocation));
-                String language = readUTF(dis);
-                String country = readUTF(dis);
-                String variant = readUTF(dis);
-                Locale locale = null;
-                if (language != null) {
-                    if (country == null) {
-                        locale = new Locale(language);
-                    } else if (variant == null) {
-                        locale = new Locale(language, country);
-                    } else {
-                        locale = new Locale(language, country, variant);
-                    }
-                }
-                if (!locale.getLanguage().equals(Locale.getDefault().getLanguage())) {
-                    dis.close();
-                    return lookupAddress(latitude, longitude, false);
-                }
-                address = new Address(locale);
-
-                address.setThoroughfare(readUTF(dis));
-                int numAddressLines = dis.readInt();
-                for (int i = 0; i < numAddressLines; ++i) {
-                    address.setAddressLine(i, readUTF(dis));
-                }
-                address.setFeatureName(readUTF(dis));
-                address.setLocality(readUTF(dis));
-                address.setAdminArea(readUTF(dis));
-                address.setSubAdminArea(readUTF(dis));
-
-                address.setCountryName(readUTF(dis));
-                address.setCountryCode(readUTF(dis));
-                address.setPostalCode(readUTF(dis));
-                address.setPhone(readUTF(dis));
-                address.setUrl(readUTF(dis));
-                dis.close();
-            }
-            return address;
-        } catch (Exception e) {
-            // Ignore.
-        }
-        return null;
-    }
-
-    private String valueIfEqual(String a, String b) {
-        return (a != null && b != null && a.equalsIgnoreCase(b)) ? a : null;
-    }
-
-    public static final void writeUTF(DataOutputStream dos, String string) throws IOException {
-        if (string == null) {
-            dos.writeUTF("");
-        } else {
-            dos.writeUTF(string);
-        }
-    }
-
-    public static final String readUTF(DataInputStream dis) throws IOException {
-        String retVal = dis.readUTF();
-        if (retVal.length() == 0)
-            return null;
-        return retVal;
-    }
-}
diff --git a/src/com/android/gallery3d/util/SaveVideoFileInfo.java b/src/com/android/gallery3d/util/SaveVideoFileInfo.java
deleted file mode 100644
index c7e5e85..0000000
--- a/src/com/android/gallery3d/util/SaveVideoFileInfo.java
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * 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.gallery3d.util;
-
-import java.io.File;
-
-public class SaveVideoFileInfo {
-    public File mFile = null;
-    public String mFileName = null;
-    // This the full directory path.
-    public File mDirectory = null;
-    // This is just the folder's name.
-    public String mFolderName = null;
-
-}
diff --git a/src/com/android/gallery3d/util/SaveVideoFileUtils.java b/src/com/android/gallery3d/util/SaveVideoFileUtils.java
deleted file mode 100644
index 10c41de..0000000
--- a/src/com/android/gallery3d/util/SaveVideoFileUtils.java
+++ /dev/null
@@ -1,154 +0,0 @@
-/*
- * 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.gallery3d.util;
-
-import android.content.ContentResolver;
-import android.content.ContentValues;
-import android.database.Cursor;
-import android.media.MediaMetadataRetriever;
-import android.net.Uri;
-import android.os.Environment;
-import android.provider.MediaStore.Video;
-import android.provider.MediaStore.Video.VideoColumns;
-
-import com.android.gallery3d.filtershow.tools.SaveImage.ContentResolverQueryCallback;
-
-import java.io.File;
-import java.sql.Date;
-import java.text.SimpleDateFormat;
-
-public class SaveVideoFileUtils {
-    // This function can decide which folder to save the video file, and generate
-    // the needed information for the video file including filename.
-    public static SaveVideoFileInfo getDstMp4FileInfo(String fileNameFormat,
-            ContentResolver contentResolver, Uri uri, String defaultFolderName) {
-        SaveVideoFileInfo dstFileInfo = new SaveVideoFileInfo();
-        // Use the default save directory if the source directory cannot be
-        // saved.
-        dstFileInfo.mDirectory = getSaveDirectory(contentResolver, uri);
-        if ((dstFileInfo.mDirectory == null) || !dstFileInfo.mDirectory.canWrite()) {
-            dstFileInfo.mDirectory = new File(Environment.getExternalStorageDirectory(),
-                    BucketNames.DOWNLOAD);
-            dstFileInfo.mFolderName = defaultFolderName;
-        } else {
-            dstFileInfo.mFolderName = dstFileInfo.mDirectory.getName();
-        }
-        dstFileInfo.mFileName = new SimpleDateFormat(fileNameFormat).format(
-                new Date(System.currentTimeMillis()));
-
-        dstFileInfo.mFile = new File(dstFileInfo.mDirectory, dstFileInfo.mFileName + ".mp4");
-        return dstFileInfo;
-    }
-
-    private static void querySource(ContentResolver contentResolver, Uri uri,
-            String[] projection, ContentResolverQueryCallback callback) {
-        Cursor cursor = null;
-        try {
-            cursor = contentResolver.query(uri, projection, null, null, null);
-            if ((cursor != null) && cursor.moveToNext()) {
-                callback.onCursorResult(cursor);
-            }
-        } catch (Exception e) {
-            // Ignore error for lacking the data column from the source.
-        } finally {
-            if (cursor != null) {
-                cursor.close();
-            }
-        }
-    }
-
-    private static File getSaveDirectory(ContentResolver contentResolver, Uri uri) {
-        final File[] dir = new File[1];
-        querySource(contentResolver, uri,
-                new String[] { VideoColumns.DATA },
-                new ContentResolverQueryCallback() {
-            @Override
-            public void onCursorResult(Cursor cursor) {
-                dir[0] = new File(cursor.getString(0)).getParentFile();
-            }
-        });
-        return dir[0];
-    }
-
-
-    /**
-     * Insert the content (saved file) with proper video properties.
-     */
-    public static Uri insertContent(SaveVideoFileInfo mDstFileInfo,
-            ContentResolver contentResolver, Uri uri ) {
-        long nowInMs = System.currentTimeMillis();
-        long nowInSec = nowInMs / 1000;
-        final ContentValues values = new ContentValues(13);
-        values.put(Video.Media.TITLE, mDstFileInfo.mFileName);
-        values.put(Video.Media.DISPLAY_NAME, mDstFileInfo.mFile.getName());
-        values.put(Video.Media.MIME_TYPE, "video/mp4");
-        values.put(Video.Media.DATE_TAKEN, nowInMs);
-        values.put(Video.Media.DATE_MODIFIED, nowInSec);
-        values.put(Video.Media.DATE_ADDED, nowInSec);
-        values.put(Video.Media.DATA, mDstFileInfo.mFile.getAbsolutePath());
-        values.put(Video.Media.SIZE, mDstFileInfo.mFile.length());
-        int durationMs = retriveVideoDurationMs(mDstFileInfo.mFile.getPath());
-        values.put(Video.Media.DURATION, durationMs);
-        // Copy the data taken and location info from src.
-        String[] projection = new String[] {
-                VideoColumns.DATE_TAKEN,
-                VideoColumns.LATITUDE,
-                VideoColumns.LONGITUDE,
-                VideoColumns.RESOLUTION,
-        };
-
-        // Copy some info from the source file.
-        querySource(contentResolver, uri, projection,
-                new ContentResolverQueryCallback() {
-                @Override
-                    public void onCursorResult(Cursor cursor) {
-                        long timeTaken = cursor.getLong(0);
-                        if (timeTaken > 0) {
-                            values.put(Video.Media.DATE_TAKEN, timeTaken);
-                        }
-                        double latitude = cursor.getDouble(1);
-                        double longitude = cursor.getDouble(2);
-                        // TODO: Change || to && after the default location
-                        // issue is
-                        // fixed.
-                        if ((latitude != 0f) || (longitude != 0f)) {
-                            values.put(Video.Media.LATITUDE, latitude);
-                            values.put(Video.Media.LONGITUDE, longitude);
-                        }
-                        values.put(Video.Media.RESOLUTION, cursor.getString(3));
-
-                    }
-                });
-
-        return contentResolver.insert(Video.Media.EXTERNAL_CONTENT_URI, values);
-    }
-
-    public static int retriveVideoDurationMs(String path) {
-        int durationMs = 0;
-        // Calculate the duration of the destination file.
-        MediaMetadataRetriever retriever = new MediaMetadataRetriever();
-        retriever.setDataSource(path);
-        String duration = retriever.extractMetadata(
-                MediaMetadataRetriever.METADATA_KEY_DURATION);
-        if (duration != null) {
-            durationMs = Integer.parseInt(duration);
-        }
-        retriever.release();
-        return durationMs;
-    }
-
-}
diff --git a/src/com/android/gallery3d/util/UpdateHelper.java b/src/com/android/gallery3d/util/UpdateHelper.java
deleted file mode 100644
index f76705d..0000000
--- a/src/com/android/gallery3d/util/UpdateHelper.java
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Copyright (C) 2010 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.gallery3d.util;
-
-import com.android.gallery3d.common.Utils;
-
-public class UpdateHelper {
-
-    private boolean mUpdated = false;
-
-    public int update(int original, int update) {
-        if (original != update) {
-            mUpdated = true;
-            original = update;
-        }
-        return original;
-    }
-
-    public long update(long original, long update) {
-        if (original != update) {
-            mUpdated = true;
-            original = update;
-        }
-        return original;
-    }
-
-    public double update(double original, double update) {
-        if (original != update) {
-            mUpdated = true;
-            original = update;
-        }
-        return original;
-    }
-
-    public <T> T update(T original, T update) {
-        if (!Utils.equals(original, update)) {
-            mUpdated = true;
-            original = update;
-        }
-        return original;
-    }
-
-    public boolean isUpdated() {
-        return mUpdated;
-    }
-}
diff --git a/src/com/android/photos/AlbumActivity.java b/src/com/android/photos/AlbumActivity.java
deleted file mode 100644
index c616b99..0000000
--- a/src/com/android/photos/AlbumActivity.java
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Copyright (C) 2013 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.photos;
-
-import android.app.Activity;
-import android.os.Bundle;
-
-public class AlbumActivity extends Activity implements MultiChoiceManager.Provider {
-
-    public static final String KEY_ALBUM_URI = AlbumFragment.KEY_ALBUM_URI;
-    public static final String KEY_ALBUM_TITLE = AlbumFragment.KEY_ALBUM_TITLE;
-
-    private MultiChoiceManager mMultiChoiceManager;
-
-    @Override
-    protected void onCreate(Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-        Bundle intentExtras = getIntent().getExtras();
-        mMultiChoiceManager = new MultiChoiceManager(this);
-        if (savedInstanceState == null) {
-            AlbumFragment albumFragment = new AlbumFragment();
-            mMultiChoiceManager.setDelegate(albumFragment);
-            albumFragment.setArguments(intentExtras);
-            getFragmentManager().beginTransaction().add(android.R.id.content,
-                    albumFragment).commit();
-        }
-        getActionBar().setTitle(intentExtras.getString(KEY_ALBUM_TITLE));
-    }
-
-    @Override
-    public MultiChoiceManager getMultiChoiceManager() {
-        return mMultiChoiceManager;
-    }
-}
diff --git a/src/com/android/photos/AlbumFragment.java b/src/com/android/photos/AlbumFragment.java
deleted file mode 100644
index 406fd2a..0000000
--- a/src/com/android/photos/AlbumFragment.java
+++ /dev/null
@@ -1,168 +0,0 @@
-/*
- * Copyright (C) 2013 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.photos;
-
-import android.app.LoaderManager.LoaderCallbacks;
-import android.content.Context;
-import android.content.Intent;
-import android.content.Loader;
-import android.database.Cursor;
-import android.net.Uri;
-import android.os.Bundle;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.GridView;
-import android.widget.ImageView;
-import android.widget.TextView;
-
-import com.android.gallery3d.R;
-import com.android.gallery3d.app.Gallery;
-import com.android.photos.adapters.PhotoThumbnailAdapter;
-import com.android.photos.data.PhotoSetLoader;
-import com.android.photos.shims.LoaderCompatShim;
-import com.android.photos.shims.MediaItemsLoader;
-import com.android.photos.views.HeaderGridView;
-
-import java.util.ArrayList;
-
-public class AlbumFragment extends MultiSelectGridFragment implements LoaderCallbacks<Cursor> {
-
-    protected static final String KEY_ALBUM_URI = "AlbumUri";
-    protected static final String KEY_ALBUM_TITLE = "AlbumTitle";
-    private static final int LOADER_ALBUM = 1;
-
-    private LoaderCompatShim<Cursor> mLoaderCompatShim;
-    private PhotoThumbnailAdapter mAdapter;
-    private String mAlbumPath;
-    private String mAlbumTitle;
-    private View mHeaderView;
-
-    @Override
-    public void onCreate(Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-        Context context = getActivity();
-        mAdapter = new PhotoThumbnailAdapter(context);
-        Bundle args = getArguments();
-        if (args != null) {
-            mAlbumPath = args.getString(KEY_ALBUM_URI, null);
-            mAlbumTitle = args.getString(KEY_ALBUM_TITLE, null);
-        }
-    }
-
-    @Override
-    public View onCreateView(LayoutInflater inflater, ViewGroup container,
-            Bundle savedInstanceState) {
-        getLoaderManager().initLoader(LOADER_ALBUM, null, this);
-        return inflater.inflate(R.layout.album_content, container, false);
-    }
-
-    @Override
-    public void onViewCreated(View view, Bundle savedInstanceState) {
-        super.onViewCreated(view, savedInstanceState);
-        // TODO: Remove once UI stabilizes
-        getGridView().setColumnWidth(MediaItemsLoader.getThumbnailSize());
-    }
-
-    private void updateHeaderView() {
-        if (mHeaderView == null) {
-            mHeaderView = LayoutInflater.from(getActivity())
-                    .inflate(R.layout.album_header, getGridView(), false);
-            ((HeaderGridView) getGridView()).addHeaderView(mHeaderView, null, false);
-
-            // TODO remove this when the data model stabilizes
-            mHeaderView.setMinimumHeight(200);
-        }
-        ImageView iv = (ImageView) mHeaderView.findViewById(R.id.album_header_image);
-        TextView title = (TextView) mHeaderView.findViewById(R.id.album_header_title);
-        TextView subtitle = (TextView) mHeaderView.findViewById(R.id.album_header_subtitle);
-        title.setText(mAlbumTitle);
-        int count = mAdapter.getCount();
-        subtitle.setText(getActivity().getResources().getQuantityString(
-                R.plurals.number_of_photos, count, count));
-        if (count > 0) {
-            iv.setImageDrawable(mLoaderCompatShim.drawableForItem(mAdapter.getItem(0), null));
-        }
-    }
-
-    @Override
-    public void onGridItemClick(GridView g, View v, int position, long id) {
-        if (mLoaderCompatShim == null) {
-            // Not fully initialized yet, discard
-            return;
-        }
-        Cursor item = (Cursor) getItemAtPosition(position);
-        Uri uri = mLoaderCompatShim.uriForItem(item);
-        Intent intent = new Intent(Intent.ACTION_VIEW, uri);
-        intent.setClass(getActivity(), Gallery.class);
-        startActivity(intent);
-    }
-
-    @Override
-    public Loader<Cursor> onCreateLoader(int id, Bundle args) {
-        // TODO: Switch to PhotoSetLoader
-        MediaItemsLoader loader = new MediaItemsLoader(getActivity(), mAlbumPath);
-        mLoaderCompatShim = loader;
-        mAdapter.setDrawableFactory(mLoaderCompatShim);
-        return loader;
-    }
-
-    @Override
-    public void onLoadFinished(Loader<Cursor> loader,
-            Cursor data) {
-        mAdapter.swapCursor(data);
-        updateHeaderView();
-        setAdapter(mAdapter);
-    }
-
-    @Override
-    public void onLoaderReset(Loader<Cursor> loader) {
-    }
-
-    @Override
-    public int getItemMediaType(Object item) {
-        return ((Cursor) item).getInt(PhotoSetLoader.INDEX_MEDIA_TYPE);
-    }
-
-    @Override
-    public int getItemSupportedOperations(Object item) {
-        return ((Cursor) item).getInt(PhotoSetLoader.INDEX_SUPPORTED_OPERATIONS);
-    }
-
-    private ArrayList<Uri> mSubItemUriTemp = new ArrayList<Uri>(1);
-    @Override
-    public ArrayList<Uri> getSubItemUrisForItem(Object item) {
-        mSubItemUriTemp.clear();
-        mSubItemUriTemp.add(mLoaderCompatShim.uriForItem((Cursor) item));
-        return mSubItemUriTemp;
-    }
-
-    @Override
-    public void deleteItemWithPath(Object itemPath) {
-        mLoaderCompatShim.deleteItemWithPath(itemPath);
-    }
-
-    @Override
-    public Uri getItemUri(Object item) {
-        return mLoaderCompatShim.uriForItem((Cursor) item);
-    }
-
-    @Override
-    public Object getPathForItem(Object item) {
-        return mLoaderCompatShim.getPathForItem((Cursor) item);
-    }
-}
diff --git a/src/com/android/photos/AlbumSetFragment.java b/src/com/android/photos/AlbumSetFragment.java
deleted file mode 100644
index bc5289e..0000000
--- a/src/com/android/photos/AlbumSetFragment.java
+++ /dev/null
@@ -1,135 +0,0 @@
-/*
- * Copyright (C) 2013 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.photos;
-
-import android.app.LoaderManager.LoaderCallbacks;
-import android.content.Context;
-import android.content.Intent;
-import android.content.Loader;
-import android.database.Cursor;
-import android.net.Uri;
-import android.os.Bundle;
-import android.provider.MediaStore.Files.FileColumns;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.GridView;
-
-import com.android.gallery3d.R;
-import com.android.photos.adapters.AlbumSetCursorAdapter;
-import com.android.photos.data.AlbumSetLoader;
-import com.android.photos.shims.LoaderCompatShim;
-import com.android.photos.shims.MediaSetLoader;
-
-import java.util.ArrayList;
-
-
-public class AlbumSetFragment extends MultiSelectGridFragment implements LoaderCallbacks<Cursor> {
-
-    private AlbumSetCursorAdapter mAdapter;
-    private LoaderCompatShim<Cursor> mLoaderCompatShim;
-
-    private static final int LOADER_ALBUMSET = 1;
-
-    @Override
-    public void onCreate(Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-        Context context = getActivity();
-        mAdapter = new AlbumSetCursorAdapter(context);
-    }
-
-    @Override
-    public View onCreateView(LayoutInflater inflater, ViewGroup container,
-            Bundle savedInstanceState) {
-        View root = super.onCreateView(inflater, container, savedInstanceState);
-        getLoaderManager().initLoader(LOADER_ALBUMSET, null, this);
-        return root;
-    }
-
-    @Override
-    public void onViewCreated(View view, Bundle savedInstanceState) {
-        super.onViewCreated(view, savedInstanceState);
-        getGridView().setColumnWidth(getActivity().getResources()
-                .getDimensionPixelSize(R.dimen.album_set_item_width));
-    }
-
-    @Override
-    public Loader<Cursor> onCreateLoader(int id, Bundle args) {
-        // TODO: Switch to AlbumSetLoader
-        MediaSetLoader loader = new MediaSetLoader(getActivity());
-        mAdapter.setDrawableFactory(loader);
-        mLoaderCompatShim = loader;
-        return loader;
-    }
-
-    @Override
-    public void onLoadFinished(Loader<Cursor> loader,
-            Cursor data) {
-        mAdapter.swapCursor(data);
-        setAdapter(mAdapter);
-    }
-
-    @Override
-    public void onLoaderReset(Loader<Cursor> loader) {
-    }
-
-    @Override
-    public void onGridItemClick(GridView g, View v, int position, long id) {
-        if (mLoaderCompatShim == null) {
-            // Not fully initialized yet, discard
-            return;
-        }
-        Cursor item = (Cursor) getItemAtPosition(position);
-        Context context = getActivity();
-        Intent intent = new Intent(context, AlbumActivity.class);
-        intent.putExtra(AlbumActivity.KEY_ALBUM_URI,
-                mLoaderCompatShim.getPathForItem(item).toString());
-        intent.putExtra(AlbumActivity.KEY_ALBUM_TITLE,
-                item.getString(AlbumSetLoader.INDEX_TITLE));
-        context.startActivity(intent);
-    }
-
-    @Override
-    public int getItemMediaType(Object item) {
-        return FileColumns.MEDIA_TYPE_NONE;
-    }
-
-    @Override
-    public int getItemSupportedOperations(Object item) {
-        return ((Cursor) item).getInt(AlbumSetLoader.INDEX_SUPPORTED_OPERATIONS);
-    }
-
-    @Override
-    public ArrayList<Uri> getSubItemUrisForItem(Object item) {
-        return mLoaderCompatShim.urisForSubItems((Cursor) item);
-    }
-
-    @Override
-    public void deleteItemWithPath(Object itemPath) {
-        mLoaderCompatShim.deleteItemWithPath(itemPath);
-    }
-
-    @Override
-    public Uri getItemUri(Object item) {
-        return mLoaderCompatShim.uriForItem((Cursor) item);
-    }
-
-    @Override
-    public Object getPathForItem(Object item) {
-        return mLoaderCompatShim.getPathForItem((Cursor) item);
-    }
-}
diff --git a/src/com/android/photos/BitmapRegionTileSource.java b/src/com/android/photos/BitmapRegionTileSource.java
deleted file mode 100644
index d7d52f6..0000000
--- a/src/com/android/photos/BitmapRegionTileSource.java
+++ /dev/null
@@ -1,183 +0,0 @@
-/*
- * Copyright (C) 2013 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.photos;
-
-import android.content.Context;
-import android.graphics.Bitmap;
-import android.graphics.Bitmap.Config;
-import android.graphics.BitmapFactory;
-import android.graphics.BitmapRegionDecoder;
-import android.graphics.Canvas;
-import android.graphics.Rect;
-import android.os.Build;
-import android.os.Build.VERSION_CODES;
-import android.util.Log;
-
-import com.android.gallery3d.glrenderer.BasicTexture;
-import com.android.gallery3d.glrenderer.BitmapTexture;
-import com.android.photos.views.TiledImageRenderer;
-
-import java.io.IOException;
-
-/**
- * A {@link com.android.photos.views.TiledImageRenderer.TileSource} using
- * {@link BitmapRegionDecoder} to wrap a local file
- */
-public class BitmapRegionTileSource implements TiledImageRenderer.TileSource {
-
-    private static final String TAG = "BitmapRegionTileSource";
-
-    private static final boolean REUSE_BITMAP =
-            Build.VERSION.SDK_INT >= VERSION_CODES.JELLY_BEAN;
-    private static final int MAX_PREVIEW_SIZE = 1024;
-
-    BitmapRegionDecoder mDecoder;
-    int mWidth;
-    int mHeight;
-    int mTileSize;
-    private BasicTexture mPreview;
-    private final int mRotation;
-
-    // For use only by getTile
-    private Rect mWantRegion = new Rect();
-    private Rect mOverlapRegion = new Rect();
-    private BitmapFactory.Options mOptions;
-    private Canvas mCanvas;
-
-    public BitmapRegionTileSource(Context context, String path, int previewSize, int rotation) {
-        mTileSize = TiledImageRenderer.suggestedTileSize(context);
-        mRotation = rotation;
-        try {
-            mDecoder = BitmapRegionDecoder.newInstance(path, true);
-            mWidth = mDecoder.getWidth();
-            mHeight = mDecoder.getHeight();
-        } catch (IOException e) {
-            Log.w("BitmapRegionTileSource", "ctor failed", e);
-        }
-        mOptions = new BitmapFactory.Options();
-        mOptions.inPreferredConfig = Bitmap.Config.ARGB_8888;
-        mOptions.inPreferQualityOverSpeed = true;
-        mOptions.inTempStorage = new byte[16 * 1024];
-        if (previewSize != 0) {
-            previewSize = Math.min(previewSize, MAX_PREVIEW_SIZE);
-            // Although this is the same size as the Bitmap that is likely already
-            // loaded, the lifecycle is different and interactions are on a different
-            // thread. Thus to simplify, this source will decode its own bitmap.
-            int sampleSize = (int) Math.ceil(Math.max(
-                    mWidth / (float) previewSize, mHeight / (float) previewSize));
-            mOptions.inSampleSize = Math.max(sampleSize, 1);
-            Bitmap preview = mDecoder.decodeRegion(
-                    new Rect(0, 0, mWidth, mHeight), mOptions);
-            if (preview.getWidth() <= MAX_PREVIEW_SIZE && preview.getHeight() <= MAX_PREVIEW_SIZE) {
-                mPreview = new BitmapTexture(preview);
-            } else {
-                Log.w(TAG, String.format(
-                        "Failed to create preview of apropriate size! "
-                        + " in: %dx%d, sample: %d, out: %dx%d",
-                        mWidth, mHeight, sampleSize,
-                        preview.getWidth(), preview.getHeight()));
-            }
-        }
-    }
-
-    @Override
-    public int getTileSize() {
-        return mTileSize;
-    }
-
-    @Override
-    public int getImageWidth() {
-        return mWidth;
-    }
-
-    @Override
-    public int getImageHeight() {
-        return mHeight;
-    }
-
-    @Override
-    public BasicTexture getPreview() {
-        return mPreview;
-    }
-
-    @Override
-    public int getRotation() {
-        return mRotation;
-    }
-
-    @Override
-    public Bitmap getTile(int level, int x, int y, Bitmap bitmap) {
-        int tileSize = getTileSize();
-        if (!REUSE_BITMAP) {
-            return getTileWithoutReusingBitmap(level, x, y, tileSize);
-        }
-
-        int t = tileSize << level;
-        mWantRegion.set(x, y, x + t, y + t);
-
-        if (bitmap == null) {
-            bitmap = Bitmap.createBitmap(tileSize, tileSize, Bitmap.Config.ARGB_8888);
-        }
-
-        mOptions.inSampleSize = (1 << level);
-        mOptions.inBitmap = bitmap;
-
-        try {
-            bitmap = mDecoder.decodeRegion(mWantRegion, mOptions);
-        } finally {
-            if (mOptions.inBitmap != bitmap && mOptions.inBitmap != null) {
-                mOptions.inBitmap = null;
-            }
-        }
-
-        if (bitmap == null) {
-            Log.w("BitmapRegionTileSource", "fail in decoding region");
-        }
-        return bitmap;
-    }
-
-    private Bitmap getTileWithoutReusingBitmap(
-            int level, int x, int y, int tileSize) {
-
-        int t = tileSize << level;
-        mWantRegion.set(x, y, x + t, y + t);
-
-        mOverlapRegion.set(0, 0, mWidth, mHeight);
-
-        mOptions.inSampleSize = (1 << level);
-        Bitmap bitmap = mDecoder.decodeRegion(mOverlapRegion, mOptions);
-
-        if (bitmap == null) {
-            Log.w(TAG, "fail in decoding region");
-        }
-
-        if (mWantRegion.equals(mOverlapRegion)) {
-            return bitmap;
-        }
-
-        Bitmap result = Bitmap.createBitmap(tileSize, tileSize, Config.ARGB_8888);
-        if (mCanvas == null) {
-            mCanvas = new Canvas();
-        }
-        mCanvas.setBitmap(result);
-        mCanvas.drawBitmap(bitmap,
-                (mOverlapRegion.left - mWantRegion.left) >> level,
-                (mOverlapRegion.top - mWantRegion.top) >> level, null);
-        mCanvas.setBitmap(null);
-        return result;
-    }
-}
diff --git a/src/com/android/photos/FullscreenViewer.java b/src/com/android/photos/FullscreenViewer.java
deleted file mode 100644
index a376139..0000000
--- a/src/com/android/photos/FullscreenViewer.java
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Copyright (C) 2013 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.photos;
-
-import android.app.Activity;
-import android.os.Bundle;
-import com.android.photos.views.TiledImageView;
-
-
-public class FullscreenViewer extends Activity {
-
-    private TiledImageView mTextureView;
-
-    @Override
-    protected void onCreate(Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-
-        String path = getIntent().getData().toString();
-        mTextureView = new TiledImageView(this);
-        mTextureView.setTileSource(new BitmapRegionTileSource(this, path, 0, 0), null);
-        setContentView(mTextureView);
-    }
-
-    @Override
-    protected void onDestroy() {
-        super.onDestroy();
-        mTextureView.destroy();
-    }
-
-}
diff --git a/src/com/android/photos/GalleryActivity.java b/src/com/android/photos/GalleryActivity.java
deleted file mode 100644
index 710767d..0000000
--- a/src/com/android/photos/GalleryActivity.java
+++ /dev/null
@@ -1,184 +0,0 @@
-/*
- * Copyright (C) 2013 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.photos;
-
-import android.app.ActionBar;
-import android.app.ActionBar.Tab;
-import android.app.Activity;
-import android.app.Fragment;
-import android.app.FragmentTransaction;
-import android.content.Intent;
-import android.os.Bundle;
-import android.support.v13.app.FragmentPagerAdapter;
-import android.support.v4.view.ViewPager;
-import android.view.Menu;
-import android.view.MenuItem;
-import android.view.ViewGroup;
-
-import com.android.camera.CameraActivity;
-import com.android.gallery3d.R;
-
-import java.util.ArrayList;
-
-public class GalleryActivity extends Activity implements MultiChoiceManager.Provider {
-
-    private MultiChoiceManager mMultiChoiceManager;
-    private ViewPager mViewPager;
-    private TabsAdapter mTabsAdapter;
-
-    @Override
-    protected void onCreate(Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-        mMultiChoiceManager = new MultiChoiceManager(this);
-        mViewPager = new ViewPager(this);
-        mViewPager.setId(R.id.viewpager);
-        setContentView(mViewPager);
-
-        ActionBar ab = getActionBar();
-        ab.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
-        ab.setDisplayShowHomeEnabled(false);
-        ab.setDisplayShowTitleEnabled(false);
-
-        mTabsAdapter = new TabsAdapter(this, mViewPager);
-        mTabsAdapter.addTab(ab.newTab().setText(R.string.tab_photos),
-                PhotoSetFragment.class, null);
-        mTabsAdapter.addTab(ab.newTab().setText(R.string.tab_albums),
-                AlbumSetFragment.class, null);
-
-        if (savedInstanceState != null) {
-            ab.setSelectedNavigationItem(savedInstanceState.getInt("tab", 0));
-        }
-    }
-
-    @Override
-    protected void onSaveInstanceState(Bundle outState) {
-        super.onSaveInstanceState(outState);
-        outState.putInt("tab", getActionBar().getSelectedNavigationIndex());
-    }
-
-    @Override
-    public boolean onCreateOptionsMenu(Menu menu) {
-        getMenuInflater().inflate(R.menu.gallery, menu);
-        return true;
-    }
-
-    @Override
-    public boolean onOptionsItemSelected(MenuItem item) {
-        switch (item.getItemId()) {
-        case R.id.menu_camera:
-            Intent intent = new Intent(this, CameraActivity.class);
-            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
-            startActivity(intent);
-            return true;
-        default:
-            return super.onOptionsItemSelected(item);
-        }
-    }
-
-    public static class TabsAdapter extends FragmentPagerAdapter implements
-            ActionBar.TabListener, ViewPager.OnPageChangeListener {
-
-        private final GalleryActivity mActivity;
-        private final ActionBar mActionBar;
-        private final ViewPager mViewPager;
-        private final ArrayList<TabInfo> mTabs = new ArrayList<TabInfo>();
-
-        static final class TabInfo {
-
-            private final Class<?> clss;
-            private final Bundle args;
-
-            TabInfo(Class<?> _class, Bundle _args) {
-                clss = _class;
-                args = _args;
-            }
-        }
-
-        public TabsAdapter(GalleryActivity activity, ViewPager pager) {
-            super(activity.getFragmentManager());
-            mActivity = activity;
-            mActionBar = activity.getActionBar();
-            mViewPager = pager;
-            mViewPager.setAdapter(this);
-            mViewPager.setOnPageChangeListener(this);
-        }
-
-        public void addTab(ActionBar.Tab tab, Class<?> clss, Bundle args) {
-            TabInfo info = new TabInfo(clss, args);
-            tab.setTag(info);
-            tab.setTabListener(this);
-            mTabs.add(info);
-            mActionBar.addTab(tab);
-            notifyDataSetChanged();
-        }
-
-        @Override
-        public int getCount() {
-            return mTabs.size();
-        }
-
-        @Override
-        public Fragment getItem(int position) {
-            TabInfo info = mTabs.get(position);
-            return Fragment.instantiate(mActivity, info.clss.getName(),
-                    info.args);
-        }
-
-        @Override
-        public void onPageScrolled(int position, float positionOffset,
-                int positionOffsetPixels) {
-        }
-
-        @Override
-        public void onPageSelected(int position) {
-            mActionBar.setSelectedNavigationItem(position);
-        }
-
-        @Override
-        public void setPrimaryItem(ViewGroup container, int position, Object object) {
-            super.setPrimaryItem(container, position, object);
-            mActivity.mMultiChoiceManager.setDelegate((MultiChoiceManager.Delegate) object);
-        }
-
-        @Override
-        public void onPageScrollStateChanged(int state) {
-        }
-
-        @Override
-        public void onTabSelected(Tab tab, FragmentTransaction ft) {
-            Object tag = tab.getTag();
-            for (int i = 0; i < mTabs.size(); i++) {
-                if (mTabs.get(i) == tag) {
-                    mViewPager.setCurrentItem(i);
-                }
-            }
-        }
-
-        @Override
-        public void onTabUnselected(Tab tab, FragmentTransaction ft) {
-        }
-
-        @Override
-        public void onTabReselected(Tab tab, FragmentTransaction ft) {
-        }
-    }
-
-    @Override
-    public MultiChoiceManager getMultiChoiceManager() {
-        return mMultiChoiceManager;
-    }
-}
diff --git a/src/com/android/photos/MultiChoiceManager.java b/src/com/android/photos/MultiChoiceManager.java
deleted file mode 100644
index 49519ca..0000000
--- a/src/com/android/photos/MultiChoiceManager.java
+++ /dev/null
@@ -1,295 +0,0 @@
-/*
- * Copyright (C) 2013 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.photos;
-
-import android.app.Activity;
-import android.content.Context;
-import android.content.Intent;
-import android.net.Uri;
-import android.os.AsyncTask;
-import android.provider.MediaStore.Files.FileColumns;
-import android.util.SparseBooleanArray;
-import android.view.ActionMode;
-import android.view.Menu;
-import android.view.MenuInflater;
-import android.view.MenuItem;
-import android.widget.AbsListView.MultiChoiceModeListener;
-import android.widget.ShareActionProvider;
-import android.widget.ShareActionProvider.OnShareTargetSelectedListener;
-
-import com.android.gallery3d.R;
-import com.android.gallery3d.app.TrimVideo;
-import com.android.gallery3d.data.MediaObject;
-import com.android.gallery3d.filtershow.FilterShowActivity;
-import com.android.gallery3d.filtershow.crop.CropActivity;
-import com.android.gallery3d.util.GalleryUtils;
-
-import java.util.ArrayList;
-import java.util.List;
-
-public class MultiChoiceManager implements MultiChoiceModeListener,
-    OnShareTargetSelectedListener, SelectionManager.SelectedUriSource {
-
-    public interface Provider {
-        public MultiChoiceManager getMultiChoiceManager();
-    }
-
-    public interface Delegate {
-        public SparseBooleanArray getSelectedItemPositions();
-        public int getSelectedItemCount();
-        public int getItemMediaType(Object item);
-        public int getItemSupportedOperations(Object item);
-        public ArrayList<Uri> getSubItemUrisForItem(Object item);
-        public Uri getItemUri(Object item);
-        public Object getItemAtPosition(int position);
-        public Object getPathForItemAtPosition(int position);
-        public void deleteItemWithPath(Object itemPath);
-    }
-
-    private SelectionManager mSelectionManager;
-    private ShareActionProvider mShareActionProvider;
-    private ActionMode mActionMode;
-    private Context mContext;
-    private Delegate mDelegate;
-
-    private ArrayList<Uri> mSelectedShareableUrisArray = new ArrayList<Uri>();
-
-    public MultiChoiceManager(Activity activity) {
-        mContext = activity;
-        mSelectionManager = new SelectionManager(activity);
-    }
-
-    public void setDelegate(Delegate delegate) {
-        if (mDelegate == delegate) {
-            return;
-        }
-        if (mActionMode != null) {
-            mActionMode.finish();
-        }
-        mDelegate = delegate;
-    }
-
-    @Override
-    public ArrayList<Uri> getSelectedShareableUris() {
-        return mSelectedShareableUrisArray;
-    }
-
-    private void updateSelectedTitle(ActionMode mode) {
-        int count = mDelegate.getSelectedItemCount();
-        mode.setTitle(mContext.getResources().getQuantityString(
-                R.plurals.number_of_items_selected, count, count));
-    }
-
-    private String getItemMimetype(Object item) {
-        int type = mDelegate.getItemMediaType(item);
-        if (type == FileColumns.MEDIA_TYPE_IMAGE) {
-            return GalleryUtils.MIME_TYPE_IMAGE;
-        } else if (type == FileColumns.MEDIA_TYPE_VIDEO) {
-            return GalleryUtils.MIME_TYPE_VIDEO;
-        } else {
-            return GalleryUtils.MIME_TYPE_ALL;
-        }
-    }
-
-    @Override
-    public void onItemCheckedStateChanged(ActionMode mode, int position, long id,
-            boolean checked) {
-        updateSelectedTitle(mode);
-        Object item = mDelegate.getItemAtPosition(position);
-
-        int supported = mDelegate.getItemSupportedOperations(item);
-
-        if ((supported & MediaObject.SUPPORT_SHARE) > 0) {
-            ArrayList<Uri> subItems = mDelegate.getSubItemUrisForItem(item);
-            if (checked) {
-                mSelectedShareableUrisArray.addAll(subItems);
-            } else {
-                mSelectedShareableUrisArray.removeAll(subItems);
-            }
-        }
-
-        mSelectionManager.onItemSelectedStateChanged(mShareActionProvider,
-                mDelegate.getItemMediaType(item),
-                supported,
-                checked);
-        updateActionItemVisibilities(mode.getMenu(),
-                mSelectionManager.getSupportedOperations());
-    }
-
-    private void updateActionItemVisibilities(Menu menu, int supportedOperations) {
-        MenuItem editItem = menu.findItem(R.id.menu_edit);
-        MenuItem deleteItem = menu.findItem(R.id.menu_delete);
-        MenuItem shareItem = menu.findItem(R.id.menu_share);
-        MenuItem cropItem = menu.findItem(R.id.menu_crop);
-        MenuItem trimItem = menu.findItem(R.id.menu_trim);
-        MenuItem muteItem = menu.findItem(R.id.menu_mute);
-        MenuItem setAsItem = menu.findItem(R.id.menu_set_as);
-
-        editItem.setVisible((supportedOperations & MediaObject.SUPPORT_EDIT) > 0);
-        deleteItem.setVisible((supportedOperations & MediaObject.SUPPORT_DELETE) > 0);
-        shareItem.setVisible((supportedOperations & MediaObject.SUPPORT_SHARE) > 0);
-        cropItem.setVisible((supportedOperations & MediaObject.SUPPORT_CROP) > 0);
-        trimItem.setVisible((supportedOperations & MediaObject.SUPPORT_TRIM) > 0);
-        muteItem.setVisible((supportedOperations & MediaObject.SUPPORT_MUTE) > 0);
-        setAsItem.setVisible((supportedOperations & MediaObject.SUPPORT_SETAS) > 0);
-    }
-
-    @Override
-    public boolean onCreateActionMode(ActionMode mode, Menu menu) {
-        mSelectionManager.setSelectedUriSource(this);
-        mActionMode = mode;
-        MenuInflater inflater = mode.getMenuInflater();
-        inflater.inflate(R.menu.gallery_multiselect, menu);
-        MenuItem menuItem = menu.findItem(R.id.menu_share);
-        mShareActionProvider = (ShareActionProvider) menuItem.getActionProvider();
-        mShareActionProvider.setOnShareTargetSelectedListener(this);
-        updateSelectedTitle(mode);
-        return true;
-    }
-
-    @Override
-    public void onDestroyActionMode(ActionMode mode) {
-        // onDestroyActionMode gets called when the share target was selected,
-        // but apparently before the ArrayList is serialized in the intent
-        // so we can't clear the old one here.
-        mSelectedShareableUrisArray = new ArrayList<Uri>();
-        mSelectionManager.onClearSelection();
-        mSelectionManager.setSelectedUriSource(null);
-        mShareActionProvider = null;
-        mActionMode = null;
-    }
-
-    @Override
-    public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
-        updateSelectedTitle(mode);
-        return false;
-    }
-
-    @Override
-    public boolean onShareTargetSelected(ShareActionProvider provider, Intent intent) {
-        mActionMode.finish();
-        return false;
-    }
-
-    private static class BulkDeleteTask extends AsyncTask<Void, Void, Void> {
-        private Delegate mDelegate;
-        private List<Object> mPaths;
-
-        public BulkDeleteTask(Delegate delegate, List<Object> paths) {
-            mDelegate = delegate;
-            mPaths = paths;
-        }
-
-        @Override
-        protected Void doInBackground(Void... ignored) {
-            for (Object path : mPaths) {
-                mDelegate.deleteItemWithPath(path);
-            }
-            return null;
-        }
-    }
-
-    @Override
-    public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
-        int actionItemId = item.getItemId();
-        switch (actionItemId) {
-            case R.id.menu_delete:
-                BulkDeleteTask deleteTask = new BulkDeleteTask(mDelegate,
-                        getPathsForSelectedItems());
-                deleteTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
-                mode.finish();
-                return true;
-            case R.id.menu_edit:
-            case R.id.menu_crop:
-            case R.id.menu_trim:
-            case R.id.menu_mute:
-            case R.id.menu_set_as:
-                singleItemAction(getSelectedItem(), actionItemId);
-                mode.finish();
-                return true;
-            default:
-                return false;
-        }
-    }
-
-    private void singleItemAction(Object item, int actionItemId) {
-        Intent intent = new Intent();
-        String mime = getItemMimetype(item);
-        Uri uri = mDelegate.getItemUri(item);
-        switch (actionItemId) {
-            case R.id.menu_edit:
-                intent.setDataAndType(uri, mime)
-                      .setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
-                      .setAction(Intent.ACTION_EDIT);
-                mContext.startActivity(Intent.createChooser(intent, null));
-                return;
-            case R.id.menu_crop:
-                intent.setDataAndType(uri, mime)
-                      .setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
-                      .setAction(CropActivity.CROP_ACTION)
-                      .setClass(mContext, FilterShowActivity.class);
-                mContext.startActivity(intent);
-                return;
-            case R.id.menu_trim:
-                intent.setData(uri)
-                      .setClass(mContext, TrimVideo.class);
-                mContext.startActivity(intent);
-                return;
-            case R.id.menu_mute:
-                /* TODO need a way to get the file path of an item
-                MuteVideo muteVideo = new MuteVideo(filePath,
-                        uri, (Activity) mContext);
-                muteVideo.muteInBackground();
-                */
-                return;
-            case R.id.menu_set_as:
-                intent.setDataAndType(uri, mime)
-                      .setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
-                      .setAction(Intent.ACTION_ATTACH_DATA)
-                      .putExtra("mimeType", mime);
-                mContext.startActivity(Intent.createChooser(
-                        intent, mContext.getString(R.string.set_as)));
-                return;
-            default:
-                return;
-        }
-    }
-
-    private List<Object> getPathsForSelectedItems() {
-        List<Object> paths = new ArrayList<Object>();
-        SparseBooleanArray selected = mDelegate.getSelectedItemPositions();
-        for (int i = 0; i < selected.size(); i++) {
-            if (selected.valueAt(i)) {
-                paths.add(mDelegate.getPathForItemAtPosition(i));
-            }
-        }
-        return paths;
-    }
-
-    public Object getSelectedItem() {
-        if (mDelegate.getSelectedItemCount() != 1) {
-            return null;
-        }
-        SparseBooleanArray selected = mDelegate.getSelectedItemPositions();
-        for (int i = 0; i < selected.size(); i++) {
-            if (selected.valueAt(i)) {
-                return mDelegate.getItemAtPosition(selected.keyAt(i));
-            }
-        }
-        return null;
-    }
-}
diff --git a/src/com/android/photos/MultiSelectGridFragment.java b/src/com/android/photos/MultiSelectGridFragment.java
deleted file mode 100644
index dda9fe4..0000000
--- a/src/com/android/photos/MultiSelectGridFragment.java
+++ /dev/null
@@ -1,348 +0,0 @@
-/*
- * Copyright (C) 2013 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.photos;
-
-import android.app.Activity;
-import android.app.Fragment;
-import android.os.Bundle;
-import android.os.Handler;
-import android.util.SparseBooleanArray;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.view.animation.AnimationUtils;
-import android.widget.AdapterView;
-import android.widget.GridView;
-import android.widget.ListAdapter;
-import android.widget.TextView;
-
-import com.android.gallery3d.R;
-
-public abstract class MultiSelectGridFragment extends Fragment
-        implements MultiChoiceManager.Delegate, AdapterView.OnItemClickListener {
-
-    final private Handler mHandler = new Handler();
-
-    final private Runnable mRequestFocus = new Runnable() {
-        @Override
-        public void run() {
-            mGrid.focusableViewAvailable(mGrid);
-        }
-    };
-
-    ListAdapter mAdapter;
-    GridView mGrid;
-    TextView mEmptyView;
-    View mProgressContainer;
-    View mGridContainer;
-    CharSequence mEmptyText;
-    boolean mGridShown;
-    MultiChoiceManager.Provider mHost;
-
-    public MultiSelectGridFragment() {
-    }
-
-    /**
-     * Provide default implementation to return a simple grid view. Subclasses
-     * can override to replace with their own layout. If doing so, the returned
-     * view hierarchy <em>must</em> have a GridView whose id is
-     * {@link android.R.id#grid android.R.id.list} and can optionally have a
-     * sibling text view id {@link android.R.id#empty android.R.id.empty} that
-     * is to be shown when the grid is empty.
-     */
-    @Override
-    public View onCreateView(LayoutInflater inflater, ViewGroup container,
-            Bundle savedInstanceState) {
-        return inflater.inflate(R.layout.multigrid_content, container, false);
-    }
-
-    @Override
-    public void onAttach(Activity activity) {
-        super.onAttach(activity);
-        mHost = (MultiChoiceManager.Provider) activity;
-        if (mGrid != null) {
-            mGrid.setMultiChoiceModeListener(mHost.getMultiChoiceManager());
-        }
-    }
-
-    @Override
-    public void onDetach() {
-        super.onDetach();
-        mHost = null;
-    }
-
-    /**
-     * Attach to grid view once the view hierarchy has been created.
-     */
-    @Override
-    public void onViewCreated(View view, Bundle savedInstanceState) {
-        super.onViewCreated(view, savedInstanceState);
-        ensureGrid();
-    }
-
-    /**
-     * Detach from grid view.
-     */
-    @Override
-    public void onDestroyView() {
-        mHandler.removeCallbacks(mRequestFocus);
-        mGrid = null;
-        mGridShown = false;
-        mEmptyView = null;
-        mProgressContainer = mGridContainer = null;
-        super.onDestroyView();
-    }
-
-    /**
-     * This method will be called when an item in the grid is selected.
-     * Subclasses should override. Subclasses can call
-     * getGridView().getItemAtPosition(position) if they need to access the data
-     * associated with the selected item.
-     *
-     * @param g The GridView where the click happened
-     * @param v The view that was clicked within the GridView
-     * @param position The position of the view in the grid
-     * @param id The id of the item that was clicked
-     */
-    public void onGridItemClick(GridView g, View v, int position, long id) {
-    }
-
-    /**
-     * Provide the cursor for the grid view.
-     */
-    public void setAdapter(ListAdapter adapter) {
-        boolean hadAdapter = mAdapter != null;
-        mAdapter = adapter;
-        if (mGrid != null) {
-            mGrid.setAdapter(adapter);
-            if (!mGridShown && !hadAdapter) {
-                // The grid was hidden, and previously didn't have an
-                // adapter. It is now time to show it.
-                setGridShown(true, getView().getWindowToken() != null);
-            }
-        }
-    }
-
-    /**
-     * Set the currently selected grid item to the specified position with the
-     * adapter's data
-     *
-     * @param position
-     */
-    public void setSelection(int position) {
-        ensureGrid();
-        mGrid.setSelection(position);
-    }
-
-    /**
-     * Get the position of the currently selected grid item.
-     */
-    public int getSelectedItemPosition() {
-        ensureGrid();
-        return mGrid.getSelectedItemPosition();
-    }
-
-    /**
-     * Get the cursor row ID of the currently selected grid item.
-     */
-    public long getSelectedItemId() {
-        ensureGrid();
-        return mGrid.getSelectedItemId();
-    }
-
-    /**
-     * Get the activity's grid view widget.
-     */
-    public GridView getGridView() {
-        ensureGrid();
-        return mGrid;
-    }
-
-    /**
-     * The default content for a MultiSelectGridFragment has a TextView that can
-     * be shown when the grid is empty. If you would like to have it shown, call
-     * this method to supply the text it should use.
-     */
-    public void setEmptyText(CharSequence text) {
-        ensureGrid();
-        if (mEmptyView == null) {
-            return;
-        }
-        mEmptyView.setText(text);
-        if (mEmptyText == null) {
-            mGrid.setEmptyView(mEmptyView);
-        }
-        mEmptyText = text;
-    }
-
-    /**
-     * Control whether the grid is being displayed. You can make it not
-     * displayed if you are waiting for the initial data to show in it. During
-     * this time an indeterminate progress indicator will be shown instead.
-     * <p>
-     * Applications do not normally need to use this themselves. The default
-     * behavior of MultiSelectGridFragment is to start with the grid not being
-     * shown, only showing it once an adapter is given with
-     * {@link #setAdapter(ListAdapter)}. If the grid at that point had not been
-     * shown, when it does get shown it will be do without the user ever seeing
-     * the hidden state.
-     *
-     * @param shown If true, the grid view is shown; if false, the progress
-     *            indicator. The initial value is true.
-     */
-    public void setGridShown(boolean shown) {
-        setGridShown(shown, true);
-    }
-
-    /**
-     * Like {@link #setGridShown(boolean)}, but no animation is used when
-     * transitioning from the previous state.
-     */
-    public void setGridShownNoAnimation(boolean shown) {
-        setGridShown(shown, false);
-    }
-
-    /**
-     * Control whether the grid is being displayed. You can make it not
-     * displayed if you are waiting for the initial data to show in it. During
-     * this time an indeterminate progress indicator will be shown instead.
-     *
-     * @param shown If true, the grid view is shown; if false, the progress
-     *            indicator. The initial value is true.
-     * @param animate If true, an animation will be used to transition to the
-     *            new state.
-     */
-    private void setGridShown(boolean shown, boolean animate) {
-        ensureGrid();
-        if (mProgressContainer == null) {
-            throw new IllegalStateException("Can't be used with a custom content view");
-        }
-        if (mGridShown == shown) {
-            return;
-        }
-        mGridShown = shown;
-        if (shown) {
-            if (animate) {
-                mProgressContainer.startAnimation(AnimationUtils.loadAnimation(
-                        getActivity(), android.R.anim.fade_out));
-                mGridContainer.startAnimation(AnimationUtils.loadAnimation(
-                        getActivity(), android.R.anim.fade_in));
-            } else {
-                mProgressContainer.clearAnimation();
-                mGridContainer.clearAnimation();
-            }
-            mProgressContainer.setVisibility(View.GONE);
-            mGridContainer.setVisibility(View.VISIBLE);
-        } else {
-            if (animate) {
-                mProgressContainer.startAnimation(AnimationUtils.loadAnimation(
-                        getActivity(), android.R.anim.fade_in));
-                mGridContainer.startAnimation(AnimationUtils.loadAnimation(
-                        getActivity(), android.R.anim.fade_out));
-            } else {
-                mProgressContainer.clearAnimation();
-                mGridContainer.clearAnimation();
-            }
-            mProgressContainer.setVisibility(View.VISIBLE);
-            mGridContainer.setVisibility(View.GONE);
-        }
-    }
-
-    /**
-     * Get the ListAdapter associated with this activity's GridView.
-     */
-    public ListAdapter getAdapter() {
-        return mGrid.getAdapter();
-    }
-
-    private void ensureGrid() {
-        if (mGrid != null) {
-            return;
-        }
-        View root = getView();
-        if (root == null) {
-            throw new IllegalStateException("Content view not yet created");
-        }
-        if (root instanceof GridView) {
-            mGrid = (GridView) root;
-        } else {
-            View empty = root.findViewById(android.R.id.empty);
-            if (empty != null && empty instanceof TextView) {
-                mEmptyView = (TextView) empty;
-            }
-            mProgressContainer = root.findViewById(R.id.progressContainer);
-            mGridContainer = root.findViewById(R.id.gridContainer);
-            View rawGridView = root.findViewById(android.R.id.list);
-            if (!(rawGridView instanceof GridView)) {
-                throw new RuntimeException(
-                        "Content has view with id attribute 'android.R.id.list' "
-                                + "that is not a GridView class");
-            }
-            mGrid = (GridView) rawGridView;
-            if (mGrid == null) {
-                throw new RuntimeException(
-                        "Your content must have a GridView whose id attribute is " +
-                                "'android.R.id.list'");
-            }
-            if (mEmptyView != null) {
-                mGrid.setEmptyView(mEmptyView);
-            }
-        }
-        mGridShown = true;
-        mGrid.setOnItemClickListener(this);
-        mGrid.setMultiChoiceModeListener(mHost.getMultiChoiceManager());
-        if (mAdapter != null) {
-            ListAdapter adapter = mAdapter;
-            mAdapter = null;
-            setAdapter(adapter);
-        } else {
-            // We are starting without an adapter, so assume we won't
-            // have our data right away and start with the progress indicator.
-            if (mProgressContainer != null) {
-                setGridShown(false, false);
-            }
-        }
-        mHandler.post(mRequestFocus);
-    }
-
-    @Override
-    public Object getItemAtPosition(int position) {
-        return getAdapter().getItem(position);
-    }
-
-    @Override
-    public Object getPathForItemAtPosition(int position) {
-        return getPathForItem(getItemAtPosition(position));
-    }
-
-    @Override
-    public SparseBooleanArray getSelectedItemPositions() {
-        return mGrid.getCheckedItemPositions();
-    }
-
-    @Override
-    public int getSelectedItemCount() {
-        return mGrid.getCheckedItemCount();
-    }
-
-    public abstract Object getPathForItem(Object item);
-
-    @Override
-    public void onItemClick(AdapterView<?> parent, View v, int position, long id) {
-        onGridItemClick((GridView) parent, v, position, id);
-    }
-}
diff --git a/src/com/android/photos/PhotoFragment.java b/src/com/android/photos/PhotoFragment.java
deleted file mode 100644
index 3be6313..0000000
--- a/src/com/android/photos/PhotoFragment.java
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * Copyright (C) 2013 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.photos;
-
-import android.app.Fragment;
-
-
-public class PhotoFragment extends Fragment {
-
-}
diff --git a/src/com/android/photos/PhotoSetFragment.java b/src/com/android/photos/PhotoSetFragment.java
deleted file mode 100644
index 961fd0b..0000000
--- a/src/com/android/photos/PhotoSetFragment.java
+++ /dev/null
@@ -1,133 +0,0 @@
-/*
- * Copyright (C) 2013 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.photos;
-
-import android.app.LoaderManager.LoaderCallbacks;
-import android.content.Context;
-import android.content.Intent;
-import android.content.Loader;
-import android.database.Cursor;
-import android.net.Uri;
-import android.os.Bundle;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.GridView;
-
-import com.android.gallery3d.app.Gallery;
-import com.android.photos.adapters.PhotoThumbnailAdapter;
-import com.android.photos.data.PhotoSetLoader;
-import com.android.photos.shims.LoaderCompatShim;
-import com.android.photos.shims.MediaItemsLoader;
-
-import java.util.ArrayList;
-
-public class PhotoSetFragment extends MultiSelectGridFragment implements LoaderCallbacks<Cursor> {
-
-    private static final int LOADER_PHOTOSET = 1;
-
-    private LoaderCompatShim<Cursor> mLoaderCompatShim;
-    private PhotoThumbnailAdapter mAdapter;
-
-    @Override
-    public void onCreate(Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-        Context context = getActivity();
-        mAdapter = new PhotoThumbnailAdapter(context);
-    }
-
-    @Override
-    public View onCreateView(LayoutInflater inflater, ViewGroup container,
-            Bundle savedInstanceState) {
-        View root = super.onCreateView(inflater, container, savedInstanceState);
-        getLoaderManager().initLoader(LOADER_PHOTOSET, null, this);
-        return root;
-    }
-
-    @Override
-    public void onViewCreated(View view, Bundle savedInstanceState) {
-        super.onViewCreated(view, savedInstanceState);
-        // TODO: Remove once UI stabilizes
-        getGridView().setColumnWidth(MediaItemsLoader.getThumbnailSize());
-    }
-
-    @Override
-    public void onGridItemClick(GridView g, View v, int position, long id) {
-        if (mLoaderCompatShim == null) {
-            // Not fully initialized yet, discard
-            return;
-        }
-        Cursor item = (Cursor) getItemAtPosition(position);
-        Uri uri = mLoaderCompatShim.uriForItem(item);
-        Intent intent = new Intent(Intent.ACTION_VIEW, uri);
-        intent.setClass(getActivity(), Gallery.class);
-        startActivity(intent);
-    }
-
-    @Override
-    public Loader<Cursor> onCreateLoader(int id, Bundle args) {
-        // TODO: Switch to PhotoSetLoader
-        MediaItemsLoader loader = new MediaItemsLoader(getActivity());
-        mLoaderCompatShim = loader;
-        mAdapter.setDrawableFactory(mLoaderCompatShim);
-        return loader;
-    }
-
-    @Override
-    public void onLoadFinished(Loader<Cursor> loader,
-            Cursor data) {
-        mAdapter.swapCursor(data);
-        setAdapter(mAdapter);
-    }
-
-    @Override
-    public void onLoaderReset(Loader<Cursor> loader) {
-    }
-
-    @Override
-    public int getItemMediaType(Object item) {
-        return ((Cursor) item).getInt(PhotoSetLoader.INDEX_MEDIA_TYPE);
-    }
-
-    @Override
-    public int getItemSupportedOperations(Object item) {
-        return ((Cursor) item).getInt(PhotoSetLoader.INDEX_SUPPORTED_OPERATIONS);
-    }
-
-    private ArrayList<Uri> mSubItemUriTemp = new ArrayList<Uri>(1);
-    @Override
-    public ArrayList<Uri> getSubItemUrisForItem(Object item) {
-        mSubItemUriTemp.clear();
-        mSubItemUriTemp.add(mLoaderCompatShim.uriForItem((Cursor) item));
-        return mSubItemUriTemp;
-    }
-
-    @Override
-    public void deleteItemWithPath(Object itemPath) {
-        mLoaderCompatShim.deleteItemWithPath(itemPath);
-    }
-
-    @Override
-    public Uri getItemUri(Object item) {
-        return mLoaderCompatShim.uriForItem((Cursor) item);
-    }
-
-    @Override
-    public Object getPathForItem(Object item) {
-        return mLoaderCompatShim.getPathForItem((Cursor) item);
-    }
-}
diff --git a/src/com/android/photos/SelectionManager.java b/src/com/android/photos/SelectionManager.java
deleted file mode 100644
index 9bfb9be..0000000
--- a/src/com/android/photos/SelectionManager.java
+++ /dev/null
@@ -1,184 +0,0 @@
-/*
- * Copyright (C) 2013 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.photos;
-
-import android.app.Activity;
-import android.content.Intent;
-import android.net.Uri;
-import android.nfc.NfcAdapter;
-import android.nfc.NfcAdapter.CreateBeamUrisCallback;
-import android.nfc.NfcEvent;
-import android.provider.MediaStore.Files.FileColumns;
-import android.widget.ShareActionProvider;
-
-import com.android.gallery3d.common.ApiHelper;
-import com.android.gallery3d.data.MediaObject;
-import com.android.gallery3d.util.GalleryUtils;
-
-import java.util.ArrayList;
-
-public class SelectionManager {
-    private Activity mActivity;
-    private NfcAdapter mNfcAdapter;
-    private SelectedUriSource mUriSource;
-    private Intent mShareIntent = new Intent();
-
-    public interface SelectedUriSource {
-        public ArrayList<Uri> getSelectedShareableUris();
-    }
-
-    public SelectionManager(Activity activity) {
-        mActivity = activity;
-        if (ApiHelper.AT_LEAST_16) {
-            mNfcAdapter = NfcAdapter.getDefaultAdapter(mActivity);
-            mNfcAdapter.setBeamPushUrisCallback(new CreateBeamUrisCallback() {
-                @Override
-                public Uri[] createBeamUris(NfcEvent arg0) {
-                 // This will have been preceded by a call to onItemSelectedStateChange
-                    if (mCachedShareableUris == null) return null;
-                    return mCachedShareableUris.toArray(
-                            new Uri[mCachedShareableUris.size()]);
-                }
-            }, mActivity);
-        }
-    }
-
-    public void setSelectedUriSource(SelectedUriSource source) {
-        mUriSource = source;
-    }
-
-    private int mSelectedTotalCount = 0;
-    private int mSelectedShareableCount = 0;
-    private int mSelectedShareableImageCount = 0;
-    private int mSelectedShareableVideoCount = 0;
-    private int mSelectedDeletableCount = 0;
-    private int mSelectedEditableCount = 0;
-    private int mSelectedCroppableCount = 0;
-    private int mSelectedSetableCount = 0;
-    private int mSelectedTrimmableCount = 0;
-    private int mSelectedMuteableCount = 0;
-
-    private ArrayList<Uri> mCachedShareableUris = null;
-
-    public void onItemSelectedStateChanged(ShareActionProvider share,
-            int itemType, int itemSupportedOperations, boolean selected) {
-        int increment = selected ? 1 : -1;
-
-        mSelectedTotalCount += increment;
-        mCachedShareableUris = null;
-
-        if ((itemSupportedOperations & MediaObject.SUPPORT_DELETE) > 0) {
-            mSelectedDeletableCount += increment;
-        }
-        if ((itemSupportedOperations & MediaObject.SUPPORT_EDIT) > 0) {
-            mSelectedEditableCount += increment;
-        }
-        if ((itemSupportedOperations & MediaObject.SUPPORT_CROP) > 0) {
-            mSelectedCroppableCount += increment;
-        }
-        if ((itemSupportedOperations & MediaObject.SUPPORT_SETAS) > 0) {
-            mSelectedSetableCount += increment;
-        }
-        if ((itemSupportedOperations & MediaObject.SUPPORT_TRIM) > 0) {
-            mSelectedTrimmableCount += increment;
-        }
-        if ((itemSupportedOperations & MediaObject.SUPPORT_MUTE) > 0) {
-            mSelectedMuteableCount += increment;
-        }
-        if ((itemSupportedOperations & MediaObject.SUPPORT_SHARE) > 0) {
-            mSelectedShareableCount += increment;
-            if (itemType == FileColumns.MEDIA_TYPE_IMAGE) {
-                mSelectedShareableImageCount += increment;
-            } else if (itemType == FileColumns.MEDIA_TYPE_VIDEO) {
-                mSelectedShareableVideoCount += increment;
-            }
-        }
-
-        mShareIntent.removeExtra(Intent.EXTRA_STREAM);
-        if (mSelectedShareableCount == 0) {
-            mShareIntent.setAction(null).setType(null);
-        } else if (mSelectedShareableCount >= 1) {
-            mCachedShareableUris = mUriSource.getSelectedShareableUris();
-            if (mCachedShareableUris.size() == 0) {
-                mShareIntent.setAction(null).setType(null);
-            } else {
-                if (mSelectedShareableImageCount == mSelectedShareableCount) {
-                    mShareIntent.setType(GalleryUtils.MIME_TYPE_IMAGE);
-                } else if (mSelectedShareableVideoCount == mSelectedShareableCount) {
-                    mShareIntent.setType(GalleryUtils.MIME_TYPE_VIDEO);
-                } else {
-                    mShareIntent.setType(GalleryUtils.MIME_TYPE_ALL);
-                }
-                if (mCachedShareableUris.size() == 1) {
-                    mShareIntent.setAction(Intent.ACTION_SEND);
-                    mShareIntent.putExtra(Intent.EXTRA_STREAM, mCachedShareableUris.get(0));
-                } else {
-                    mShareIntent.setAction(Intent.ACTION_SEND_MULTIPLE);
-                    mShareIntent.putExtra(Intent.EXTRA_STREAM, mCachedShareableUris);
-                }
-            }
-        }
-        share.setShareIntent(mShareIntent);
-    }
-
-    public int getSupportedOperations() {
-        if (mSelectedTotalCount == 0) {
-            return 0;
-        }
-        int supported = 0;
-        if (mSelectedTotalCount == 1) {
-            if (mSelectedCroppableCount == 1) {
-                supported |= MediaObject.SUPPORT_CROP;
-            }
-            if (mSelectedEditableCount == 1) {
-                supported |= MediaObject.SUPPORT_EDIT;
-            }
-            if (mSelectedSetableCount == 1) {
-                supported |= MediaObject.SUPPORT_SETAS;
-            }
-            if (mSelectedTrimmableCount == 1) {
-                supported |= MediaObject.SUPPORT_TRIM;
-            }
-            if (mSelectedMuteableCount == 1) {
-                supported |= MediaObject.SUPPORT_MUTE;
-            }
-        }
-        if (mSelectedDeletableCount == mSelectedTotalCount) {
-            supported |= MediaObject.SUPPORT_DELETE;
-        }
-        if (mSelectedShareableCount > 0) {
-            supported |= MediaObject.SUPPORT_SHARE;
-        }
-        return supported;
-    }
-
-    public void onClearSelection() {
-        mSelectedTotalCount = 0;
-        mSelectedShareableCount = 0;
-        mSelectedShareableImageCount = 0;
-        mSelectedShareableVideoCount = 0;
-        mSelectedDeletableCount = 0;
-        mSelectedEditableCount = 0;
-        mSelectedCroppableCount = 0;
-        mSelectedSetableCount = 0;
-        mSelectedTrimmableCount = 0;
-        mSelectedMuteableCount = 0;
-        mCachedShareableUris = null;
-        mShareIntent.removeExtra(Intent.EXTRA_STREAM);
-        mShareIntent.setAction(null).setType(null);
-    }
-}
diff --git a/src/com/android/photos/adapters/AlbumSetCursorAdapter.java b/src/com/android/photos/adapters/AlbumSetCursorAdapter.java
deleted file mode 100644
index ab99cde..0000000
--- a/src/com/android/photos/adapters/AlbumSetCursorAdapter.java
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * Copyright (C) 2013 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.photos.adapters;
-
-import android.content.Context;
-import android.database.Cursor;
-import android.graphics.drawable.Drawable;
-import android.text.format.DateFormat;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.CursorAdapter;
-import android.widget.ImageView;
-import android.widget.ProgressBar;
-import android.widget.TextView;
-
-import com.android.gallery3d.R;
-import com.android.photos.data.AlbumSetLoader;
-import com.android.photos.shims.LoaderCompatShim;
-
-import java.util.Date;
-
-public class AlbumSetCursorAdapter extends CursorAdapter {
-
-    private LoaderCompatShim<Cursor> mDrawableFactory;
-
-    public void setDrawableFactory(LoaderCompatShim<Cursor> factory) {
-        mDrawableFactory = factory;
-    }
-
-    public AlbumSetCursorAdapter(Context context) {
-        super(context, null, false);
-    }
-
-    @Override
-    public void bindView(View v, Context context, Cursor cursor) {
-        TextView titleTextView = (TextView) v.findViewById(
-                R.id.album_set_item_title);
-        titleTextView.setText(cursor.getString(AlbumSetLoader.INDEX_TITLE));
-
-        TextView countTextView = (TextView) v.findViewById(
-                R.id.album_set_item_count);
-        int count = cursor.getInt(AlbumSetLoader.INDEX_COUNT);
-        countTextView.setText(context.getResources().getQuantityString(
-                R.plurals.number_of_photos, count, count));
-
-        ImageView thumbImageView = (ImageView) v.findViewById(
-                R.id.album_set_item_image);
-        Drawable recycle = thumbImageView.getDrawable();
-        Drawable drawable = mDrawableFactory.drawableForItem(cursor, recycle);
-        if (recycle != drawable) {
-            thumbImageView.setImageDrawable(drawable);
-        }
-    }
-
-    @Override
-    public View newView(Context context, Cursor cursor, ViewGroup parent) {
-        return LayoutInflater.from(context).inflate(
-                R.layout.album_set_item, parent, false);
-    }
-}
diff --git a/src/com/android/photos/adapters/PhotoThumbnailAdapter.java b/src/com/android/photos/adapters/PhotoThumbnailAdapter.java
deleted file mode 100644
index 1190b8c..0000000
--- a/src/com/android/photos/adapters/PhotoThumbnailAdapter.java
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * Copyright (C) 2013 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.photos.adapters;
-
-import android.content.Context;
-import android.database.Cursor;
-import android.graphics.drawable.Drawable;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.CursorAdapter;
-import android.widget.ImageView;
-
-import com.android.gallery3d.R;
-import com.android.photos.data.PhotoSetLoader;
-import com.android.photos.shims.LoaderCompatShim;
-import com.android.photos.views.GalleryThumbnailView.GalleryThumbnailAdapter;
-
-
-public class PhotoThumbnailAdapter extends CursorAdapter implements GalleryThumbnailAdapter {
-    private LayoutInflater mInflater;
-    private LoaderCompatShim<Cursor> mDrawableFactory;
-
-    public PhotoThumbnailAdapter(Context context) {
-        super(context, null, false);
-        mInflater = LayoutInflater.from(context);
-    }
-
-    public void setDrawableFactory(LoaderCompatShim<Cursor> factory) {
-        mDrawableFactory = factory;
-    }
-
-    @Override
-    public void bindView(View view, Context context, Cursor cursor) {
-        ImageView iv = (ImageView) view.findViewById(R.id.thumbnail);
-        Drawable recycle = iv.getDrawable();
-        Drawable drawable = mDrawableFactory.drawableForItem(cursor, recycle);
-        if (recycle != drawable) {
-            iv.setImageDrawable(drawable);
-        }
-    }
-
-    @Override
-    public View newView(Context context, Cursor cursor, ViewGroup parent) {
-        View view = mInflater.inflate(R.layout.photo_set_item, parent, false);
-        return view;
-    }
-
-    @Override
-    public float getIntrinsicAspectRatio(int position) {
-        Cursor cursor = getItem(position);
-        float width = cursor.getInt(PhotoSetLoader.INDEX_WIDTH);
-        float height = cursor.getInt(PhotoSetLoader.INDEX_HEIGHT);
-        return width / height;
-    }
-
-    @Override
-    public Cursor getItem(int position) {
-        return (Cursor) super.getItem(position);
-    }
-}
\ No newline at end of file
diff --git a/src/com/android/photos/data/AlbumSetLoader.java b/src/com/android/photos/data/AlbumSetLoader.java
deleted file mode 100644
index 9404732..0000000
--- a/src/com/android/photos/data/AlbumSetLoader.java
+++ /dev/null
@@ -1,54 +0,0 @@
-package com.android.photos.data;
-
-import android.database.MatrixCursor;
-
-
-public class AlbumSetLoader {
-    public static final int INDEX_ID = 0;
-    public static final int INDEX_TITLE = 1;
-    public static final int INDEX_TIMESTAMP = 2;
-    public static final int INDEX_THUMBNAIL_URI = 3;
-    public static final int INDEX_THUMBNAIL_WIDTH = 4;
-    public static final int INDEX_THUMBNAIL_HEIGHT = 5;
-    public static final int INDEX_COUNT_PENDING_UPLOAD = 6;
-    public static final int INDEX_COUNT = 7;
-    public static final int INDEX_SUPPORTED_OPERATIONS = 8;
-
-    public static final String[] PROJECTION = {
-        "_id",
-        "title",
-        "timestamp",
-        "thumb_uri",
-        "thumb_width",
-        "thumb_height",
-        "count_pending_upload",
-        "_count",
-        "supported_operations"
-    };
-    public static final MatrixCursor MOCK = createRandomCursor(30);
-
-    private static MatrixCursor createRandomCursor(int count) {
-        MatrixCursor c = new MatrixCursor(PROJECTION, count);
-        for (int i = 0; i < count; i++) {
-            c.addRow(createRandomRow());
-        }
-        return c;
-    }
-
-    private static Object[] createRandomRow() {
-        double random = Math.random();
-        int id = (int) (500 * random);
-        Object[] row = {
-            id,
-            "Fun times " + id,
-            (long) (System.currentTimeMillis() * random),
-            null,
-            0,
-            0,
-            (random < .3 ? 1 : 0),
-            1,
-            0
-        };
-        return row;
-    }
-}
\ No newline at end of file
diff --git a/src/com/android/photos/data/BitmapDecoder.java b/src/com/android/photos/data/BitmapDecoder.java
deleted file mode 100644
index 0671e73..0000000
--- a/src/com/android/photos/data/BitmapDecoder.java
+++ /dev/null
@@ -1,224 +0,0 @@
-/*
- * Copyright (C) 2013 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.photos.data;
-
-import android.graphics.Bitmap;
-import android.graphics.Bitmap.Config;
-import android.graphics.BitmapFactory;
-import android.graphics.BitmapFactory.Options;
-import android.util.Log;
-import android.util.Pools.Pool;
-import android.util.Pools.SynchronizedPool;
-
-import com.android.gallery3d.common.BitmapUtils;
-import com.android.gallery3d.common.Utils;
-
-import java.io.BufferedInputStream;
-import java.io.File;
-import java.io.IOException;
-import java.io.InputStream;
-
-/**
- * BitmapDecoder keeps a pool of temporary storage to reuse for decoding
- * bitmaps. It also simplifies the multi-stage decoding required to efficiently
- * use GalleryBitmapPool. The static methods decode and decodeFile can be used
- * to decode a bitmap from GalleryBitmapPool. The bitmap may be returned
- * directly to GalleryBitmapPool or use the put method here when the bitmap is
- * ready to be recycled.
- */
-public class BitmapDecoder {
-    private static final String TAG = BitmapDecoder.class.getSimpleName();
-    private static final int POOL_SIZE = 4;
-    private static final int TEMP_STORAGE_SIZE_BYTES = 16 * 1024;
-    private static final int HEADER_MAX_SIZE = 128 * 1024;
-    private static final int NO_SCALING = -1;
-
-    private static final Pool<BitmapFactory.Options> sOptions =
-            new SynchronizedPool<BitmapFactory.Options>(POOL_SIZE);
-
-    private interface Decoder<T> {
-        Bitmap decode(T input, BitmapFactory.Options options);
-
-        boolean decodeBounds(T input, BitmapFactory.Options options);
-    }
-
-    private static abstract class OnlyDecode<T> implements Decoder<T> {
-        @Override
-        public boolean decodeBounds(T input, BitmapFactory.Options options) {
-            decode(input, options);
-            return true;
-        }
-    }
-
-    private static final Decoder<InputStream> sStreamDecoder = new Decoder<InputStream>() {
-        @Override
-        public Bitmap decode(InputStream is, Options options) {
-            return BitmapFactory.decodeStream(is, null, options);
-        }
-
-        @Override
-        public boolean decodeBounds(InputStream is, Options options) {
-            is.mark(HEADER_MAX_SIZE);
-            BitmapFactory.decodeStream(is, null, options);
-            try {
-                is.reset();
-                return true;
-            } catch (IOException e) {
-                Log.e(TAG, "Could not decode stream to bitmap", e);
-                return false;
-            }
-        }
-    };
-
-    private static final Decoder<String> sFileDecoder = new OnlyDecode<String>() {
-        @Override
-        public Bitmap decode(String filePath, Options options) {
-            return BitmapFactory.decodeFile(filePath, options);
-        }
-    };
-
-    private static final Decoder<byte[]> sByteArrayDecoder = new OnlyDecode<byte[]>() {
-        @Override
-        public Bitmap decode(byte[] data, Options options) {
-            return BitmapFactory.decodeByteArray(data, 0, data.length, options);
-        }
-    };
-
-    private static <T> Bitmap delegateDecode(Decoder<T> decoder, T input, int width, int height) {
-        BitmapFactory.Options options = getOptions();
-        GalleryBitmapPool pool = GalleryBitmapPool.getInstance();
-        try {
-            options.inJustDecodeBounds = true;
-            if (!decoder.decodeBounds(input, options)) {
-                return null;
-            }
-            options.inJustDecodeBounds = false;
-            Bitmap reuseBitmap = null;
-            if (width != NO_SCALING && options.outWidth >= width && options.outHeight >= height) {
-                setScaling(options, width, height);
-            } else {
-                reuseBitmap = pool.get(options.outWidth, options.outHeight);
-            }
-            options.inBitmap = reuseBitmap;
-            Bitmap decodedBitmap = decoder.decode(input, options);
-            if (reuseBitmap != null && decodedBitmap != reuseBitmap) {
-                pool.put(reuseBitmap);
-            }
-            return decodedBitmap;
-        } catch (IllegalArgumentException e) {
-            if (options.inBitmap == null) {
-                throw e;
-            }
-            pool.put(options.inBitmap);
-            options.inBitmap = null;
-            return decoder.decode(input, options);
-        } finally {
-            options.inBitmap = null;
-            options.inJustDecodeBounds = false;
-            sOptions.release(options);
-        }
-    }
-
-    public static Bitmap decode(InputStream in) {
-        try {
-            if (!in.markSupported()) {
-                in = new BufferedInputStream(in);
-            }
-            return delegateDecode(sStreamDecoder, in, NO_SCALING, NO_SCALING);
-        } finally {
-            Utils.closeSilently(in);
-        }
-    }
-
-    public static Bitmap decode(File file) {
-        return decodeFile(file.getPath());
-    }
-
-    public static Bitmap decodeFile(String path) {
-        return delegateDecode(sFileDecoder, path, NO_SCALING, NO_SCALING);
-    }
-
-    public static Bitmap decodeByteArray(byte[] data) {
-        return delegateDecode(sByteArrayDecoder, data, NO_SCALING, NO_SCALING);
-    }
-
-    public static void put(Bitmap bitmap) {
-        GalleryBitmapPool.getInstance().put(bitmap);
-    }
-
-    /**
-     * Decodes to a specific size. If the dimensions of the image don't match
-     * width x height, the resulting image will be in the proportions of the
-     * decoded image, but will be scaled to fill the dimensions. For example, if
-     * width and height are 10x10 and the image is 200x100, the resulting image
-     * will be scaled/sampled to 20x10.
-     */
-    public static Bitmap decodeFile(String path, int width, int height) {
-        return delegateDecode(sFileDecoder, path, width, height);
-    }
-
-    /** @see #decodeFile(String, int, int) */
-    public static Bitmap decodeByteArray(byte[] data, int width, int height) {
-        return delegateDecode(sByteArrayDecoder, data, width, height);
-    }
-
-    /** @see #decodeFile(String, int, int) */
-    public static Bitmap decode(InputStream in, int width, int height) {
-        try {
-            if (!in.markSupported()) {
-                in = new BufferedInputStream(in);
-            }
-            return delegateDecode(sStreamDecoder, in, width, height);
-        } finally {
-            Utils.closeSilently(in);
-        }
-    }
-
-    private static BitmapFactory.Options getOptions() {
-        BitmapFactory.Options opts = sOptions.acquire();
-        if (opts == null) {
-            opts = new BitmapFactory.Options();
-            opts.inMutable = true;
-            opts.inPreferredConfig = Config.ARGB_8888;
-            opts.inTempStorage = new byte[TEMP_STORAGE_SIZE_BYTES];
-        }
-        opts.inSampleSize = 1;
-        opts.inDensity = 1;
-        opts.inTargetDensity = 1;
-
-        return opts;
-    }
-
-    // Sets the options to sample then scale the image so that the image's
-    // minimum dimension will match side.
-    private static void setScaling(BitmapFactory.Options options, int width, int height) {
-        float widthScale = ((float)options.outWidth)/ width;
-        float heightScale = ((float) options.outHeight)/height;
-        int side = (widthScale < heightScale) ? width : height;
-        options.inSampleSize = BitmapUtils.computeSampleSize(options.outWidth, options.outHeight,
-                side, BitmapUtils.UNCONSTRAINED);
-        int constraint;
-        if (options.outWidth < options.outHeight) {
-            // Width is the constraint. Scale so that width = side.
-            constraint = options.outWidth;
-        } else {
-            // Height is the constraint. Scale so that height = side.
-            constraint = options.outHeight;
-        }
-        options.inDensity = constraint / options.inSampleSize;
-        options.inTargetDensity = side;
-    }
-}
diff --git a/src/com/android/photos/data/FileRetriever.java b/src/com/android/photos/data/FileRetriever.java
deleted file mode 100644
index eb7686e..0000000
--- a/src/com/android/photos/data/FileRetriever.java
+++ /dev/null
@@ -1,109 +0,0 @@
-/*
- * Copyright (C) 2013 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.photos.data;
-
-import android.graphics.Bitmap;
-import android.media.ExifInterface;
-import android.net.Uri;
-import android.util.Log;
-import android.webkit.MimeTypeMap;
-
-import com.android.gallery3d.common.BitmapUtils;
-
-import java.io.File;
-import java.io.IOException;
-
-public class FileRetriever implements MediaRetriever {
-    private static final String TAG = FileRetriever.class.getSimpleName();
-
-    @Override
-    public File getLocalFile(Uri contentUri) {
-        return new File(contentUri.getPath());
-    }
-
-    @Override
-    public MediaSize getFastImageSize(Uri contentUri, MediaSize size) {
-        if (isVideo(contentUri)) {
-            return null;
-        }
-        return MediaSize.TemporaryThumbnail;
-    }
-
-    @Override
-    public byte[] getTemporaryImage(Uri contentUri, MediaSize fastImageSize) {
-
-        try {
-            ExifInterface exif = new ExifInterface(contentUri.getPath());
-            if (exif.hasThumbnail()) {
-                return exif.getThumbnail();
-            }
-        } catch (IOException e) {
-            Log.w(TAG, "Unable to load exif for " + contentUri);
-        }
-        return null;
-    }
-
-    @Override
-    public boolean getMedia(Uri contentUri, MediaSize imageSize, File tempFile) {
-        if (imageSize == MediaSize.Original) {
-            return false; // getLocalFile should always return the original.
-        }
-        if (imageSize == MediaSize.Thumbnail) {
-            File preview = MediaCache.getInstance().getCachedFile(contentUri, MediaSize.Preview);
-            if (preview != null) {
-                // Just downsample the preview, it is faster.
-                return MediaCacheUtils.downsample(preview, imageSize, tempFile);
-            }
-        }
-        File highRes = new File(contentUri.getPath());
-        boolean success;
-        if (!isVideo(contentUri)) {
-            success = MediaCacheUtils.downsample(highRes, imageSize, tempFile);
-        } else {
-            // Video needs to extract the bitmap.
-            Bitmap bitmap = BitmapUtils.createVideoThumbnail(highRes.getPath());
-            if (bitmap == null) {
-                return false;
-            } else if (imageSize == MediaSize.Thumbnail
-                    && !MediaCacheUtils.needsDownsample(bitmap, MediaSize.Preview)
-                    && MediaCacheUtils.writeToFile(bitmap, tempFile)) {
-                // Opportunistically save preview
-                MediaCache mediaCache = MediaCache.getInstance();
-                mediaCache.insertIntoCache(contentUri, MediaSize.Preview, tempFile);
-            }
-            // Now scale the image
-            success = MediaCacheUtils.downsample(bitmap, imageSize, tempFile);
-        }
-        return success;
-    }
-
-    @Override
-    public Uri normalizeUri(Uri contentUri, MediaSize size) {
-        return contentUri;
-    }
-
-    @Override
-    public MediaSize normalizeMediaSize(Uri contentUri, MediaSize size) {
-        return size;
-    }
-
-    private static boolean isVideo(Uri uri) {
-        MimeTypeMap mimeTypeMap = MimeTypeMap.getSingleton();
-        String extension = MimeTypeMap.getFileExtensionFromUrl(uri.toString());
-        String mimeType = mimeTypeMap.getMimeTypeFromExtension(extension);
-        return (mimeType != null && mimeType.startsWith("video/"));
-    }
-}
diff --git a/src/com/android/photos/data/GalleryBitmapPool.java b/src/com/android/photos/data/GalleryBitmapPool.java
deleted file mode 100644
index 390a0d4..0000000
--- a/src/com/android/photos/data/GalleryBitmapPool.java
+++ /dev/null
@@ -1,161 +0,0 @@
-/*
- * Copyright (C) 2013 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.photos.data;
-
-import android.graphics.Bitmap;
-import android.graphics.Point;
-import android.util.Pools.Pool;
-import android.util.Pools.SynchronizedPool;
-
-import com.android.photos.data.SparseArrayBitmapPool.Node;
-
-/**
- * Pool allowing the efficient reuse of bitmaps in order to avoid long
- * garbage collection pauses.
- */
-public class GalleryBitmapPool {
-
-    private static final int CAPACITY_BYTES = 20971520;
-
-    // We found that Gallery uses bitmaps that are either square (for example,
-    // tiles of large images or square thumbnails), match one of the common
-    // photo aspect ratios (4x3, 3x2, or 16x9), or, less commonly, are of some
-    // other aspect ratio. Taking advantage of this information, we use 3
-    // SparseArrayBitmapPool instances to back the GalleryBitmapPool, which affords
-    // O(1) lookups for square bitmaps, and average-case - but *not* asymptotically -
-    // O(1) lookups for common photo aspect ratios and other miscellaneous aspect
-    // ratios. Beware of the pathological case where there are many bitmaps added
-    // to the pool with different non-square aspect ratios but the same width, as
-    // performance will degrade and the average case lookup will approach
-    // O(# of different aspect ratios).
-    private static final int POOL_INDEX_NONE = -1;
-    private static final int POOL_INDEX_SQUARE = 0;
-    private static final int POOL_INDEX_PHOTO = 1;
-    private static final int POOL_INDEX_MISC = 2;
-
-    private static final Point[] COMMON_PHOTO_ASPECT_RATIOS =
-        { new Point(4, 3), new Point(3, 2), new Point(16, 9) };
-
-    private int mCapacityBytes;
-    private SparseArrayBitmapPool [] mPools;
-    private Pool<Node> mSharedNodePool = new SynchronizedPool<Node>(128);
-
-    private GalleryBitmapPool(int capacityBytes) {
-        mPools = new SparseArrayBitmapPool[3];
-        mPools[POOL_INDEX_SQUARE] = new SparseArrayBitmapPool(capacityBytes / 3, mSharedNodePool);
-        mPools[POOL_INDEX_PHOTO] = new SparseArrayBitmapPool(capacityBytes / 3, mSharedNodePool);
-        mPools[POOL_INDEX_MISC] = new SparseArrayBitmapPool(capacityBytes / 3, mSharedNodePool);
-        mCapacityBytes = capacityBytes;
-    }
-
-    private static GalleryBitmapPool sInstance = new GalleryBitmapPool(CAPACITY_BYTES);
-
-    public static GalleryBitmapPool getInstance() {
-        return sInstance;
-    }
-
-    private SparseArrayBitmapPool getPoolForDimensions(int width, int height) {
-        int index = getPoolIndexForDimensions(width, height);
-        if (index == POOL_INDEX_NONE) {
-            return null;
-        } else {
-            return mPools[index];
-        }
-    }
-
-    private int getPoolIndexForDimensions(int width, int height) {
-        if (width <= 0 || height <= 0) {
-            return POOL_INDEX_NONE;
-        }
-        if (width == height) {
-            return POOL_INDEX_SQUARE;
-        }
-        int min, max;
-        if (width > height) {
-            min = height;
-            max = width;
-        } else {
-            min = width;
-            max = height;
-        }
-        for (Point ar : COMMON_PHOTO_ASPECT_RATIOS) {
-            if (min * ar.x == max * ar.y) {
-                return POOL_INDEX_PHOTO;
-            }
-        }
-        return POOL_INDEX_MISC;
-    }
-
-    /**
-     * @return Capacity of the pool in bytes.
-     */
-    public synchronized int getCapacity() {
-        return mCapacityBytes;
-    }
-
-    /**
-     * @return Approximate total size in bytes of the bitmaps stored in the pool.
-     */
-    public int getSize() {
-        // Note that this only returns an approximate size, since multiple threads
-        // might be getting and putting Bitmaps from the pool and we lock at the
-        // sub-pool level to avoid unnecessary blocking.
-        int total = 0;
-        for (SparseArrayBitmapPool p : mPools) {
-            total += p.getSize();
-        }
-        return total;
-    }
-
-    /**
-     * @return Bitmap from the pool with the desired height/width or null if none available.
-     */
-    public Bitmap get(int width, int height) {
-        SparseArrayBitmapPool pool = getPoolForDimensions(width, height);
-        if (pool == null) {
-            return null;
-        } else {
-            return pool.get(width, height);
-        }
-    }
-
-    /**
-     * Adds the given bitmap to the pool.
-     * @return Whether the bitmap was added to the pool.
-     */
-    public boolean put(Bitmap b) {
-        if (b == null || b.getConfig() != Bitmap.Config.ARGB_8888) {
-            return false;
-        }
-        SparseArrayBitmapPool pool = getPoolForDimensions(b.getWidth(), b.getHeight());
-        if (pool == null) {
-            b.recycle();
-            return false;
-        } else {
-            return pool.put(b);
-        }
-    }
-
-    /**
-     * Empty the pool, recycling all the bitmaps currently in it.
-     */
-    public void clear() {
-        for (SparseArrayBitmapPool p : mPools) {
-            p.clear();
-        }
-    }
-}
diff --git a/src/com/android/photos/data/MediaCache.java b/src/com/android/photos/data/MediaCache.java
deleted file mode 100644
index 0952a40..0000000
--- a/src/com/android/photos/data/MediaCache.java
+++ /dev/null
@@ -1,676 +0,0 @@
-/*
- * Copyright (C) 2013 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.photos.data;
-
-import android.content.Context;
-import android.database.sqlite.SQLiteDatabase;
-import android.net.Uri;
-import android.os.Environment;
-import android.util.Log;
-
-import com.android.photos.data.MediaCacheDatabase.Action;
-import com.android.photos.data.MediaRetriever.MediaSize;
-
-import java.io.ByteArrayInputStream;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-import java.io.InputStream;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-import java.util.Queue;
-
-/**
- * MediaCache keeps a cache of images, videos, thumbnails and previews. Calls to
- * retrieve a specific media item are executed asynchronously. The caller has an
- * option to receive a notification for lower resolution images that happen to
- * be available prior to the one requested.
- * <p>
- * When an media item has been retrieved, the notification for it is called on a
- * separate notifier thread. This thread should not be held for a long time so
- * that other notifications may happen.
- * </p>
- * <p>
- * Media items are uniquely identified by their content URIs. Each
- * scheme/authority can offer its own MediaRetriever, running in its own thread.
- * </p>
- * <p>
- * The MediaCache is an LRU cache, but does not allow the thumbnail cache to
- * drop below a minimum size. This prevents browsing through original images to
- * wipe out the thumbnails.
- * </p>
- */
-public class MediaCache {
-    static final String TAG = MediaCache.class.getSimpleName();
-    /** Subdirectory containing the image cache. */
-    static final String IMAGE_CACHE_SUBDIR = "image_cache";
-    /** File name extension to use for cached images. */
-    static final String IMAGE_EXTENSION = ".cache";
-    /** File name extension to use for temporary cached images while retrieving. */
-    static final String TEMP_IMAGE_EXTENSION = ".temp";
-
-    public static interface ImageReady {
-        void imageReady(InputStream bitmapInputStream);
-    }
-
-    public static interface OriginalReady {
-        void originalReady(File originalFile);
-    }
-
-    /** A Thread for each MediaRetriever */
-    private class ProcessQueue extends Thread {
-        private Queue<ProcessingJob> mQueue;
-
-        public ProcessQueue(Queue<ProcessingJob> queue) {
-            mQueue = queue;
-        }
-
-        @Override
-        public void run() {
-            while (mRunning) {
-                ProcessingJob status;
-                synchronized (mQueue) {
-                    while (mQueue.isEmpty()) {
-                        try {
-                            mQueue.wait();
-                        } catch (InterruptedException e) {
-                            if (!mRunning) {
-                                return;
-                            }
-                            Log.w(TAG, "Unexpected interruption", e);
-                        }
-                    }
-                    status = mQueue.remove();
-                }
-                processTask(status);
-            }
-        }
-    };
-
-    private interface NotifyReady {
-        void notifyReady();
-
-        void setFile(File file) throws FileNotFoundException;
-
-        boolean isPrefetch();
-    }
-
-    private static class NotifyOriginalReady implements NotifyReady {
-        private final OriginalReady mCallback;
-        private File mFile;
-
-        public NotifyOriginalReady(OriginalReady callback) {
-            mCallback = callback;
-        }
-
-        @Override
-        public void notifyReady() {
-            if (mCallback != null) {
-                mCallback.originalReady(mFile);
-            }
-        }
-
-        @Override
-        public void setFile(File file) {
-            mFile = file;
-        }
-
-        @Override
-        public boolean isPrefetch() {
-            return mCallback == null;
-        }
-    }
-
-    private static class NotifyImageReady implements NotifyReady {
-        private final ImageReady mCallback;
-        private InputStream mInputStream;
-
-        public NotifyImageReady(ImageReady callback) {
-            mCallback = callback;
-        }
-
-        @Override
-        public void notifyReady() {
-            if (mCallback != null) {
-                mCallback.imageReady(mInputStream);
-            }
-        }
-
-        @Override
-        public void setFile(File file) throws FileNotFoundException {
-            mInputStream = new FileInputStream(file);
-        }
-
-        public void setBytes(byte[] bytes) {
-            mInputStream = new ByteArrayInputStream(bytes);
-        }
-
-        @Override
-        public boolean isPrefetch() {
-            return mCallback == null;
-        }
-    }
-
-    /** A media item to be retrieved and its notifications. */
-    private static class ProcessingJob {
-        public ProcessingJob(Uri uri, MediaSize size, NotifyReady complete,
-                NotifyImageReady lowResolution) {
-            this.contentUri = uri;
-            this.size = size;
-            this.complete = complete;
-            this.lowResolution = lowResolution;
-        }
-        public Uri contentUri;
-        public MediaSize size;
-        public NotifyImageReady lowResolution;
-        public NotifyReady complete;
-    }
-
-    private boolean mRunning = true;
-    private static MediaCache sInstance;
-    private File mCacheDir;
-    private Context mContext;
-    private Queue<NotifyReady> mCallbacks = new LinkedList<NotifyReady>();
-    private Map<String, MediaRetriever> mRetrievers = new HashMap<String, MediaRetriever>();
-    private Map<String, List<ProcessingJob>> mTasks = new HashMap<String, List<ProcessingJob>>();
-    private List<ProcessQueue> mProcessingThreads = new ArrayList<ProcessQueue>();
-    private MediaCacheDatabase mDatabaseHelper;
-    private long mTempImageNumber = 1;
-    private Object mTempImageNumberLock = new Object();
-
-    private long mMaxCacheSize = 40 * 1024 * 1024; // 40 MB
-    private long mMinThumbCacheSize = 4 * 1024 * 1024; // 4 MB
-    private long mCacheSize = -1;
-    private long mThumbCacheSize = -1;
-    private Object mCacheSizeLock = new Object();
-
-    private Action mNotifyCachedLowResolution = new Action() {
-        @Override
-        public void execute(Uri uri, long id, MediaSize size, Object parameter) {
-            ProcessingJob job = (ProcessingJob) parameter;
-            File file = createCacheImagePath(id);
-            addNotification(job.lowResolution, file);
-        }
-    };
-
-    private Action mMoveTempToCache = new Action() {
-        @Override
-        public void execute(Uri uri, long id, MediaSize size, Object parameter) {
-            File tempFile = (File) parameter;
-            File cacheFile = createCacheImagePath(id);
-            tempFile.renameTo(cacheFile);
-        }
-    };
-
-    private Action mDeleteFile = new Action() {
-        @Override
-        public void execute(Uri uri, long id, MediaSize size, Object parameter) {
-            File file = createCacheImagePath(id);
-            file.delete();
-            synchronized (mCacheSizeLock) {
-                if (mCacheSize != -1) {
-                    long length = (Long) parameter;
-                    mCacheSize -= length;
-                    if (size == MediaSize.Thumbnail) {
-                        mThumbCacheSize -= length;
-                    }
-                }
-            }
-        }
-    };
-
-    /** The thread used to make ImageReady and OriginalReady callbacks. */
-    private Thread mProcessNotifications = new Thread() {
-        @Override
-        public void run() {
-            while (mRunning) {
-                NotifyReady notifyImage;
-                synchronized (mCallbacks) {
-                    while (mCallbacks.isEmpty()) {
-                        try {
-                            mCallbacks.wait();
-                        } catch (InterruptedException e) {
-                            if (!mRunning) {
-                                return;
-                            }
-                            Log.w(TAG, "Unexpected Interruption, continuing");
-                        }
-                    }
-                    notifyImage = mCallbacks.remove();
-                }
-
-                notifyImage.notifyReady();
-            }
-        }
-    };
-
-    public static synchronized void initialize(Context context) {
-        if (sInstance == null) {
-            sInstance = new MediaCache(context);
-            MediaCacheUtils.initialize(context);
-        }
-    }
-
-    public static MediaCache getInstance() {
-        return sInstance;
-    }
-
-    public static synchronized void shutdown() {
-        sInstance.mRunning = false;
-        sInstance.mProcessNotifications.interrupt();
-        for (ProcessQueue processingThread : sInstance.mProcessingThreads) {
-            processingThread.interrupt();
-        }
-        sInstance = null;
-    }
-
-    private MediaCache(Context context) {
-        mDatabaseHelper = new MediaCacheDatabase(context);
-        mProcessNotifications.start();
-        mContext = context;
-    }
-
-    // This is used for testing.
-    public void setCacheDir(File cacheDir) {
-        cacheDir.mkdirs();
-        mCacheDir = cacheDir;
-    }
-
-    public File getCacheDir() {
-        synchronized (mContext) {
-            if (mCacheDir == null) {
-                String state = Environment.getExternalStorageState();
-                File baseDir;
-                if (Environment.MEDIA_MOUNTED.equals(state)) {
-                    baseDir = mContext.getExternalCacheDir();
-                } else {
-                    // Stored in internal cache
-                    baseDir = mContext.getCacheDir();
-                }
-                mCacheDir = new File(baseDir, IMAGE_CACHE_SUBDIR);
-                mCacheDir.mkdirs();
-            }
-            return mCacheDir;
-        }
-    }
-
-    /**
-     * Invalidates all cached images related to a given contentUri. This call
-     * doesn't complete until the images have been removed from the cache.
-     */
-    public void invalidate(Uri contentUri) {
-        mDatabaseHelper.delete(contentUri, mDeleteFile);
-    }
-
-    public void clearCacheDir() {
-        File[] cachedFiles = getCacheDir().listFiles();
-        if (cachedFiles != null) {
-            for (File cachedFile : cachedFiles) {
-                cachedFile.delete();
-            }
-        }
-    }
-
-    /**
-     * Add a MediaRetriever for a Uri scheme and authority. This MediaRetriever
-     * will be granted its own thread for retrieving images.
-     */
-    public void addRetriever(String scheme, String authority, MediaRetriever retriever) {
-        String differentiator = getDifferentiator(scheme, authority);
-        synchronized (mRetrievers) {
-            mRetrievers.put(differentiator, retriever);
-        }
-        synchronized (mTasks) {
-            LinkedList<ProcessingJob> queue = new LinkedList<ProcessingJob>();
-            mTasks.put(differentiator, queue);
-            new ProcessQueue(queue).start();
-        }
-    }
-
-    /**
-     * Retrieves a thumbnail. complete will be called when the thumbnail is
-     * available. If lowResolution is not null and a lower resolution thumbnail
-     * is available before the thumbnail, lowResolution will be called prior to
-     * complete. All callbacks will be made on a thread other than the calling
-     * thread.
-     *
-     * @param contentUri The URI for the full resolution image to search for.
-     * @param complete Callback for when the image has been retrieved.
-     * @param lowResolution If not null and a lower resolution image is
-     *            available prior to retrieving the thumbnail, this will be
-     *            called with the low resolution bitmap.
-     */
-    public void retrieveThumbnail(Uri contentUri, ImageReady complete, ImageReady lowResolution) {
-        addTask(contentUri, complete, lowResolution, MediaSize.Thumbnail);
-    }
-
-    /**
-     * Retrieves a preview. complete will be called when the preview is
-     * available. If lowResolution is not null and a lower resolution preview is
-     * available before the preview, lowResolution will be called prior to
-     * complete. All callbacks will be made on a thread other than the calling
-     * thread.
-     *
-     * @param contentUri The URI for the full resolution image to search for.
-     * @param complete Callback for when the image has been retrieved.
-     * @param lowResolution If not null and a lower resolution image is
-     *            available prior to retrieving the preview, this will be called
-     *            with the low resolution bitmap.
-     */
-    public void retrievePreview(Uri contentUri, ImageReady complete, ImageReady lowResolution) {
-        addTask(contentUri, complete, lowResolution, MediaSize.Preview);
-    }
-
-    /**
-     * Retrieves the original image or video. complete will be called when the
-     * media is available on the local file system. If lowResolution is not null
-     * and a lower resolution preview is available before the original,
-     * lowResolution will be called prior to complete. All callbacks will be
-     * made on a thread other than the calling thread.
-     *
-     * @param contentUri The URI for the full resolution image to search for.
-     * @param complete Callback for when the image has been retrieved.
-     * @param lowResolution If not null and a lower resolution image is
-     *            available prior to retrieving the preview, this will be called
-     *            with the low resolution bitmap.
-     */
-    public void retrieveOriginal(Uri contentUri, OriginalReady complete, ImageReady lowResolution) {
-        File localFile = getLocalFile(contentUri);
-        if (localFile != null) {
-            addNotification(new NotifyOriginalReady(complete), localFile);
-        } else {
-            NotifyImageReady notifyLowResolution = (lowResolution == null) ? null
-                    : new NotifyImageReady(lowResolution);
-            addTask(contentUri, new NotifyOriginalReady(complete), notifyLowResolution,
-                    MediaSize.Original);
-        }
-    }
-
-    /**
-     * Looks for an already cached media at a specific size.
-     *
-     * @param contentUri The original media item content URI
-     * @param size The target size to search for in the cache
-     * @return The cached file location or null if it is not cached.
-     */
-    public File getCachedFile(Uri contentUri, MediaSize size) {
-        Long cachedId = mDatabaseHelper.getCached(contentUri, size);
-        File file = null;
-        if (cachedId != null) {
-            file = createCacheImagePath(cachedId);
-            if (!file.exists()) {
-                mDatabaseHelper.delete(contentUri, size, mDeleteFile);
-                file = null;
-            }
-        }
-        return file;
-    }
-
-    /**
-     * Inserts a media item into the cache.
-     *
-     * @param contentUri The original media item URI.
-     * @param size The size of the media item to store in the cache.
-     * @param tempFile The temporary file where the image is stored. This file
-     *            will no longer exist after executing this method.
-     * @return The new location, in the cache, of the media item or null if it
-     *         wasn't possible to move into the cache.
-     */
-    public File insertIntoCache(Uri contentUri, MediaSize size, File tempFile) {
-        long fileSize = tempFile.length();
-        if (fileSize == 0) {
-            return null;
-        }
-        File cacheFile = null;
-        SQLiteDatabase db = mDatabaseHelper.getWritableDatabase();
-        // Ensure that this step is atomic
-        db.beginTransaction();
-        try {
-            Long id = mDatabaseHelper.getCached(contentUri, size);
-            if (id != null) {
-                cacheFile = createCacheImagePath(id);
-                if (tempFile.renameTo(cacheFile)) {
-                    mDatabaseHelper.updateLength(id, fileSize);
-                } else {
-                    Log.w(TAG, "Could not update cached file with " + tempFile);
-                    tempFile.delete();
-                    cacheFile = null;
-                }
-            } else {
-                ensureFreeCacheSpace(tempFile.length(), size);
-                id = mDatabaseHelper.insert(contentUri, size, mMoveTempToCache, tempFile);
-                cacheFile = createCacheImagePath(id);
-            }
-            db.setTransactionSuccessful();
-        } finally {
-            db.endTransaction();
-        }
-        return cacheFile;
-    }
-
-    /**
-     * For testing purposes.
-     */
-    public void setMaxCacheSize(long maxCacheSize) {
-        synchronized (mCacheSizeLock) {
-            mMaxCacheSize = maxCacheSize;
-            mMinThumbCacheSize = mMaxCacheSize / 10;
-            mCacheSize = -1;
-            mThumbCacheSize = -1;
-        }
-    }
-
-    private File createCacheImagePath(long id) {
-        return new File(getCacheDir(), String.valueOf(id) + IMAGE_EXTENSION);
-    }
-
-    private void addTask(Uri contentUri, ImageReady complete, ImageReady lowResolution,
-            MediaSize size) {
-        NotifyReady notifyComplete = new NotifyImageReady(complete);
-        NotifyImageReady notifyLowResolution = null;
-        if (lowResolution != null) {
-            notifyLowResolution = new NotifyImageReady(lowResolution);
-        }
-        addTask(contentUri, notifyComplete, notifyLowResolution, size);
-    }
-
-    private void addTask(Uri contentUri, NotifyReady complete, NotifyImageReady lowResolution,
-            MediaSize size) {
-        MediaRetriever retriever = getMediaRetriever(contentUri);
-        Uri uri = retriever.normalizeUri(contentUri, size);
-        if (uri == null) {
-            throw new IllegalArgumentException("No MediaRetriever for " + contentUri);
-        }
-        size = retriever.normalizeMediaSize(uri, size);
-
-        File cachedFile = getCachedFile(uri, size);
-        if (cachedFile != null) {
-            addNotification(complete, cachedFile);
-            return;
-        }
-        String differentiator = getDifferentiator(uri.getScheme(), uri.getAuthority());
-        synchronized (mTasks) {
-            List<ProcessingJob> tasks = mTasks.get(differentiator);
-            if (tasks == null) {
-                throw new IllegalArgumentException("Cannot find retriever for: " + uri);
-            }
-            synchronized (tasks) {
-                ProcessingJob job = new ProcessingJob(uri, size, complete, lowResolution);
-                if (complete.isPrefetch()) {
-                    tasks.add(job);
-                } else {
-                    int index = tasks.size() - 1;
-                    while (index >= 0 && tasks.get(index).complete.isPrefetch()) {
-                        index--;
-                    }
-                    tasks.add(index + 1, job);
-                }
-                tasks.notifyAll();
-            }
-        }
-    }
-
-    private MediaRetriever getMediaRetriever(Uri uri) {
-        String differentiator = getDifferentiator(uri.getScheme(), uri.getAuthority());
-        MediaRetriever retriever;
-        synchronized (mRetrievers) {
-            retriever = mRetrievers.get(differentiator);
-        }
-        if (retriever == null) {
-            throw new IllegalArgumentException("No MediaRetriever for " + uri);
-        }
-        return retriever;
-    }
-
-    private File getLocalFile(Uri uri) {
-        MediaRetriever retriever = getMediaRetriever(uri);
-        File localFile = null;
-        if (retriever != null) {
-            localFile = retriever.getLocalFile(uri);
-        }
-        return localFile;
-    }
-
-    private MediaSize getFastImageSize(Uri uri, MediaSize size) {
-        MediaRetriever retriever = getMediaRetriever(uri);
-        return retriever.getFastImageSize(uri, size);
-    }
-
-    private boolean isFastImageBetter(MediaSize fastImageType, MediaSize size) {
-        if (fastImageType == null) {
-            return false;
-        }
-        if (size == null) {
-            return true;
-        }
-        return fastImageType.isBetterThan(size);
-    }
-
-    private byte[] getTemporaryImage(Uri uri, MediaSize fastImageType) {
-        MediaRetriever retriever = getMediaRetriever(uri);
-        return retriever.getTemporaryImage(uri, fastImageType);
-    }
-
-    private void processTask(ProcessingJob job) {
-        File cachedFile = getCachedFile(job.contentUri, job.size);
-        if (cachedFile != null) {
-            addNotification(job.complete, cachedFile);
-            return;
-        }
-
-        boolean hasLowResolution = job.lowResolution != null;
-        if (hasLowResolution) {
-            MediaSize cachedSize = mDatabaseHelper.executeOnBestCached(job.contentUri, job.size,
-                    mNotifyCachedLowResolution);
-            MediaSize fastImageSize = getFastImageSize(job.contentUri, job.size);
-            if (isFastImageBetter(fastImageSize, cachedSize)) {
-                if (fastImageSize.isTemporary()) {
-                    byte[] bytes = getTemporaryImage(job.contentUri, fastImageSize);
-                    if (bytes != null) {
-                        addNotification(job.lowResolution, bytes);
-                    }
-                } else {
-                    File lowFile = getMedia(job.contentUri, fastImageSize);
-                    if (lowFile != null) {
-                        addNotification(job.lowResolution, lowFile);
-                    }
-                }
-            }
-        }
-
-        // Now get the full size desired
-        File fullSizeFile = getMedia(job.contentUri, job.size);
-        if (fullSizeFile != null) {
-            addNotification(job.complete, fullSizeFile);
-        }
-    }
-
-    private void addNotification(NotifyReady callback, File file) {
-        try {
-            callback.setFile(file);
-            synchronized (mCallbacks) {
-                mCallbacks.add(callback);
-                mCallbacks.notifyAll();
-            }
-        } catch (FileNotFoundException e) {
-            Log.e(TAG, "Unable to read file " + file, e);
-        }
-    }
-
-    private void addNotification(NotifyImageReady callback, byte[] bytes) {
-        callback.setBytes(bytes);
-        synchronized (mCallbacks) {
-            mCallbacks.add(callback);
-            mCallbacks.notifyAll();
-        }
-    }
-
-    private File getMedia(Uri uri, MediaSize size) {
-        long imageNumber;
-        synchronized (mTempImageNumberLock) {
-            imageNumber = mTempImageNumber++;
-        }
-        File tempFile = new File(getCacheDir(), String.valueOf(imageNumber) + TEMP_IMAGE_EXTENSION);
-        MediaRetriever retriever = getMediaRetriever(uri);
-        boolean retrieved = retriever.getMedia(uri, size, tempFile);
-        File cachedFile = null;
-        if (retrieved) {
-            ensureFreeCacheSpace(tempFile.length(), size);
-            long id = mDatabaseHelper.insert(uri, size, mMoveTempToCache, tempFile);
-            cachedFile = createCacheImagePath(id);
-        }
-        return cachedFile;
-    }
-
-    private static String getDifferentiator(String scheme, String authority) {
-        if (authority == null) {
-            return scheme;
-        }
-        StringBuilder differentiator = new StringBuilder(scheme);
-        differentiator.append(':');
-        differentiator.append(authority);
-        return differentiator.toString();
-    }
-
-    private void ensureFreeCacheSpace(long size, MediaSize mediaSize) {
-        synchronized (mCacheSizeLock) {
-            if (mCacheSize == -1 || mThumbCacheSize == -1) {
-                mCacheSize = mDatabaseHelper.getCacheSize();
-                mThumbCacheSize = mDatabaseHelper.getThumbnailCacheSize();
-                if (mCacheSize == -1 || mThumbCacheSize == -1) {
-                    Log.e(TAG, "Can't determine size of the image cache");
-                    return;
-                }
-            }
-            mCacheSize += size;
-            if (mediaSize == MediaSize.Thumbnail) {
-                mThumbCacheSize += size;
-            }
-            if (mCacheSize > mMaxCacheSize) {
-                shrinkCacheLocked();
-            }
-        }
-    }
-
-    private void shrinkCacheLocked() {
-        long deleteSize = mMinThumbCacheSize;
-        boolean includeThumbnails = (mThumbCacheSize - deleteSize) > mMinThumbCacheSize;
-        mDatabaseHelper.deleteOldCached(includeThumbnails, deleteSize, mDeleteFile);
-    }
-}
diff --git a/src/com/android/photos/data/MediaCacheDatabase.java b/src/com/android/photos/data/MediaCacheDatabase.java
deleted file mode 100644
index c92ac0f..0000000
--- a/src/com/android/photos/data/MediaCacheDatabase.java
+++ /dev/null
@@ -1,286 +0,0 @@
-/*
- * Copyright (C) 2013 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.photos.data;
-
-import android.content.ContentValues;
-import android.content.Context;
-import android.database.Cursor;
-import android.database.sqlite.SQLiteDatabase;
-import android.database.sqlite.SQLiteOpenHelper;
-import android.net.Uri;
-import android.provider.BaseColumns;
-
-import com.android.photos.data.MediaRetriever.MediaSize;
-
-import java.io.File;
-
-class MediaCacheDatabase extends SQLiteOpenHelper {
-    public static final int DB_VERSION = 1;
-    public static final String DB_NAME = "mediacache.db";
-
-    /** Internal database table used for the media cache */
-    public static final String TABLE = "media_cache";
-
-    private static interface Columns extends BaseColumns {
-        /** The Content URI of the original image. */
-        public static final String URI = "uri";
-        /** MediaSize.getValue() values. */
-        public static final String MEDIA_SIZE = "media_size";
-        /** The last time this image was queried. */
-        public static final String LAST_ACCESS = "last_access";
-        /** The image size in bytes. */
-        public static final String SIZE_IN_BYTES = "size";
-    }
-
-    static interface Action {
-        void execute(Uri uri, long id, MediaSize size, Object parameter);
-    }
-
-    private static final String[] PROJECTION_ID = {
-        Columns._ID,
-    };
-
-    private static final String[] PROJECTION_CACHED = {
-        Columns._ID, Columns.MEDIA_SIZE, Columns.SIZE_IN_BYTES,
-    };
-
-    private static final String[] PROJECTION_CACHE_SIZE = {
-        "SUM(" + Columns.SIZE_IN_BYTES + ")"
-    };
-
-    private static final String[] PROJECTION_DELETE_OLD = {
-        Columns._ID, Columns.URI, Columns.MEDIA_SIZE, Columns.SIZE_IN_BYTES, Columns.LAST_ACCESS,
-    };
-
-    public static final String CREATE_TABLE = "CREATE TABLE " + TABLE + "("
-            + Columns._ID + " INTEGER PRIMARY KEY AUTOINCREMENT, "
-            + Columns.URI + " TEXT NOT NULL,"
-            + Columns.MEDIA_SIZE + " INTEGER NOT NULL,"
-            + Columns.LAST_ACCESS + " INTEGER NOT NULL,"
-            + Columns.SIZE_IN_BYTES + " INTEGER NOT NULL,"
-            + "UNIQUE(" + Columns.URI + ", " + Columns.MEDIA_SIZE + "))";
-
-    public static final String DROP_TABLE = "DROP TABLE IF EXISTS " + TABLE;
-
-    public static final String WHERE_THUMBNAIL = Columns.MEDIA_SIZE + " = "
-            + MediaSize.Thumbnail.getValue();
-
-    public static final String WHERE_NOT_THUMBNAIL = Columns.MEDIA_SIZE + " <> "
-            + MediaSize.Thumbnail.getValue();
-
-    public static final String WHERE_CLEAR_CACHE = Columns.LAST_ACCESS + " <= ?";
-
-    public static final String WHERE_CLEAR_CACHE_LARGE = WHERE_CLEAR_CACHE + " AND "
-            + WHERE_NOT_THUMBNAIL;
-
-    static class QueryCacheResults {
-        public QueryCacheResults(long id, int sizeVal) {
-            this.id = id;
-            this.size = MediaSize.fromInteger(sizeVal);
-        }
-        public long id;
-        public MediaSize size;
-    }
-
-    public MediaCacheDatabase(Context context) {
-        super(context, DB_NAME, null, DB_VERSION);
-    }
-
-    @Override
-    public void onCreate(SQLiteDatabase db) {
-        db.execSQL(CREATE_TABLE);
-    }
-
-    @Override
-    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
-        db.execSQL(DROP_TABLE);
-        onCreate(db);
-        MediaCache.getInstance().clearCacheDir();
-    }
-
-    public Long getCached(Uri uri, MediaSize size) {
-        String where = Columns.URI + " = ? AND " + Columns.MEDIA_SIZE + " = ?";
-        SQLiteDatabase db = getWritableDatabase();
-        String[] whereArgs = {
-                uri.toString(), String.valueOf(size.getValue()),
-        };
-        Cursor cursor = db.query(TABLE, PROJECTION_ID, where, whereArgs, null, null, null);
-        Long id = null;
-        if (cursor.moveToNext()) {
-            id = cursor.getLong(0);
-        }
-        cursor.close();
-        if (id != null) {
-            String[] updateArgs = {
-                id.toString()
-            };
-            ContentValues values = new ContentValues();
-            values.put(Columns.LAST_ACCESS, System.currentTimeMillis());
-            db.beginTransaction();
-            try {
-                db.update(TABLE, values, Columns._ID + " = ?", updateArgs);
-                db.setTransactionSuccessful();
-            } finally {
-                db.endTransaction();
-            }
-        }
-        return id;
-    }
-
-    public MediaSize executeOnBestCached(Uri uri, MediaSize size, Action action) {
-        String where = Columns.URI + " = ? AND " + Columns.MEDIA_SIZE + " < ?";
-        String orderBy = Columns.MEDIA_SIZE + " DESC";
-        SQLiteDatabase db = getReadableDatabase();
-        String[] whereArgs = {
-                uri.toString(), String.valueOf(size.getValue()),
-        };
-        Cursor cursor = db.query(TABLE, PROJECTION_CACHED, where, whereArgs, null, null, orderBy);
-        MediaSize bestSize = null;
-        if (cursor.moveToNext()) {
-            long id = cursor.getLong(0);
-            bestSize = MediaSize.fromInteger(cursor.getInt(1));
-            long fileSize = cursor.getLong(2);
-            action.execute(uri, id, bestSize, fileSize);
-        }
-        cursor.close();
-        return bestSize;
-    }
-
-    public long insert(Uri uri, MediaSize size, Action action, File tempFile) {
-        SQLiteDatabase db = getWritableDatabase();
-        db.beginTransaction();
-        try {
-            ContentValues values = new ContentValues();
-            values.put(Columns.LAST_ACCESS, System.currentTimeMillis());
-            values.put(Columns.MEDIA_SIZE, size.getValue());
-            values.put(Columns.URI, uri.toString());
-            values.put(Columns.SIZE_IN_BYTES, tempFile.length());
-            long id = db.insert(TABLE, null, values);
-            if (id != -1) {
-                action.execute(uri, id, size, tempFile);
-                db.setTransactionSuccessful();
-            }
-            return id;
-        } finally {
-            db.endTransaction();
-        }
-    }
-
-    public void updateLength(long id, long fileSize) {
-        ContentValues values = new ContentValues();
-        values.put(Columns.SIZE_IN_BYTES, fileSize);
-        String[] whereArgs = {
-            String.valueOf(id)
-        };
-        SQLiteDatabase db = getWritableDatabase();
-        db.beginTransaction();
-        try {
-            db.update(TABLE, values, Columns._ID + " = ?", whereArgs);
-            db.setTransactionSuccessful();
-        } finally {
-            db.endTransaction();
-        }
-    }
-
-    public void delete(Uri uri, MediaSize size, Action action) {
-        String where = Columns.URI + " = ? AND " + Columns.MEDIA_SIZE + " = ?";
-        String[] whereArgs = {
-                uri.toString(), String.valueOf(size.getValue()),
-        };
-        deleteRows(uri, where, whereArgs, action);
-    }
-
-    public void delete(Uri uri, Action action) {
-        String where = Columns.URI + " = ?";
-        String[] whereArgs = {
-            uri.toString()
-        };
-        deleteRows(uri, where, whereArgs, action);
-    }
-
-    private void deleteRows(Uri uri, String where, String[] whereArgs, Action action) {
-        SQLiteDatabase db = getWritableDatabase();
-        // Make this an atomic operation
-        db.beginTransaction();
-        Cursor cursor = db.query(TABLE, PROJECTION_CACHED, where, whereArgs, null, null, null);
-        while (cursor.moveToNext()) {
-            long id = cursor.getLong(0);
-            MediaSize size = MediaSize.fromInteger(cursor.getInt(1));
-            long length = cursor.getLong(2);
-            action.execute(uri, id, size, length);
-        }
-        cursor.close();
-        try {
-            db.delete(TABLE, where, whereArgs);
-            db.setTransactionSuccessful();
-        } finally {
-            db.endTransaction();
-        }
-    }
-
-    public void deleteOldCached(boolean includeThumbnails, long deleteSize, Action action) {
-        String where = includeThumbnails ? null : WHERE_NOT_THUMBNAIL;
-        long lastAccess = 0;
-        SQLiteDatabase db = getWritableDatabase();
-        db.beginTransaction();
-        try {
-            Cursor cursor = db.query(TABLE, PROJECTION_DELETE_OLD, where, null, null, null,
-                    Columns.LAST_ACCESS);
-            while (cursor.moveToNext()) {
-                long id = cursor.getLong(0);
-                String uri = cursor.getString(1);
-                MediaSize size = MediaSize.fromInteger(cursor.getInt(2));
-                long length = cursor.getLong(3);
-                long imageLastAccess = cursor.getLong(4);
-
-                if (imageLastAccess != lastAccess && deleteSize < 0) {
-                    break; // We've deleted enough.
-                }
-                lastAccess = imageLastAccess;
-                action.execute(Uri.parse(uri), id, size, length);
-                deleteSize -= length;
-            }
-            cursor.close();
-            String[] whereArgs = {
-                String.valueOf(lastAccess),
-            };
-            String whereDelete = includeThumbnails ? WHERE_CLEAR_CACHE : WHERE_CLEAR_CACHE_LARGE;
-            db.delete(TABLE, whereDelete, whereArgs);
-            db.setTransactionSuccessful();
-        } finally {
-            db.endTransaction();
-        }
-    }
-
-    public long getCacheSize() {
-        return getCacheSize(null);
-    }
-
-    public long getThumbnailCacheSize() {
-        return getCacheSize(WHERE_THUMBNAIL);
-    }
-
-    private long getCacheSize(String where) {
-        SQLiteDatabase db = getReadableDatabase();
-        Cursor cursor = db.query(TABLE, PROJECTION_CACHE_SIZE, where, null, null, null, null);
-        long size = -1;
-        if (cursor.moveToNext()) {
-            size = cursor.getLong(0);
-        }
-        cursor.close();
-        return size;
-    }
-}
diff --git a/src/com/android/photos/data/MediaCacheUtils.java b/src/com/android/photos/data/MediaCacheUtils.java
deleted file mode 100644
index e3ccd14..0000000
--- a/src/com/android/photos/data/MediaCacheUtils.java
+++ /dev/null
@@ -1,167 +0,0 @@
-/*
- * Copyright (C) 2013 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.photos.data;
-
-import android.content.Context;
-import android.content.res.Resources;
-import android.graphics.Bitmap;
-import android.graphics.Bitmap.CompressFormat;
-import android.graphics.BitmapFactory;
-import android.util.Log;
-import android.util.Pools.SimplePool;
-import android.util.Pools.SynchronizedPool;
-
-import com.android.gallery3d.R;
-import com.android.gallery3d.common.BitmapUtils;
-import com.android.gallery3d.common.Utils;
-import com.android.gallery3d.data.DecodeUtils;
-import com.android.gallery3d.data.MediaItem;
-import com.android.gallery3d.util.ThreadPool.CancelListener;
-import com.android.gallery3d.util.ThreadPool.JobContext;
-import com.android.photos.data.MediaRetriever.MediaSize;
-
-import java.io.File;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-
-public class MediaCacheUtils {
-    private static final String TAG = MediaCacheUtils.class.getSimpleName();
-    private static int QUALITY = 80;
-    private static final int BUFFER_SIZE = 4096;
-    private static final SimplePool<byte[]> mBufferPool = new SynchronizedPool<byte[]>(5);
-
-    private static final JobContext sJobStub = new JobContext() {
-
-        @Override
-        public boolean isCancelled() {
-            return false;
-        }
-
-        @Override
-        public void setCancelListener(CancelListener listener) {
-        }
-
-        @Override
-        public boolean setMode(int mode) {
-            return true;
-        }
-    };
-
-    private static int mTargetThumbnailSize;
-    private static int mTargetPreviewSize;
-
-    public static void initialize(Context context) {
-        Resources resources = context.getResources();
-        mTargetThumbnailSize = resources.getDimensionPixelSize(R.dimen.size_thumbnail);
-        mTargetPreviewSize = resources.getDimensionPixelSize(R.dimen.size_preview);
-    }
-
-    public static int getTargetSize(MediaSize size) {
-        return (size == MediaSize.Thumbnail) ? mTargetThumbnailSize : mTargetPreviewSize;
-    }
-
-    public static boolean downsample(File inBitmap, MediaSize targetSize, File outBitmap) {
-        if (MediaSize.Original == targetSize) {
-            return false; // MediaCache should use the local path for this.
-        }
-        int size = getTargetSize(targetSize);
-        BitmapFactory.Options options = new BitmapFactory.Options();
-        options.inPreferredConfig = Bitmap.Config.ARGB_8888;
-        // TODO: remove unnecessary job context from DecodeUtils.
-        Bitmap bitmap = DecodeUtils.decodeThumbnail(sJobStub, inBitmap.getPath(), options, size,
-                MediaItem.TYPE_THUMBNAIL);
-        boolean success = (bitmap != null);
-        if (success) {
-            success = writeAndRecycle(bitmap, outBitmap);
-        }
-        return success;
-    }
-
-    public static boolean downsample(Bitmap inBitmap, MediaSize size, File outBitmap) {
-        if (MediaSize.Original == size) {
-            return false; // MediaCache should use the local path for this.
-        }
-        int targetSize = getTargetSize(size);
-        boolean success;
-        if (!needsDownsample(inBitmap, size)) {
-            success = writeAndRecycle(inBitmap, outBitmap);
-        } else {
-            float maxDimension = Math.max(inBitmap.getWidth(), inBitmap.getHeight());
-            float scale = targetSize / maxDimension;
-            int targetWidth = Math.round(scale * inBitmap.getWidth());
-            int targetHeight = Math.round(scale * inBitmap.getHeight());
-            Bitmap scaled = Bitmap.createScaledBitmap(inBitmap, targetWidth, targetHeight, false);
-            success = writeAndRecycle(scaled, outBitmap);
-            inBitmap.recycle();
-        }
-        return success;
-    }
-
-    public static boolean extractImageFromVideo(File inVideo, File outBitmap) {
-        Bitmap bitmap = BitmapUtils.createVideoThumbnail(inVideo.getPath());
-        return writeAndRecycle(bitmap, outBitmap);
-    }
-
-    public static boolean needsDownsample(Bitmap bitmap, MediaSize size) {
-        if (size == MediaSize.Original) {
-            return false;
-        }
-        int targetSize = getTargetSize(size);
-        int maxDimension = Math.max(bitmap.getWidth(), bitmap.getHeight());
-        return maxDimension > (targetSize * 4 / 3);
-    }
-
-    public static boolean writeAndRecycle(Bitmap bitmap, File outBitmap) {
-        boolean success = writeToFile(bitmap, outBitmap);
-        bitmap.recycle();
-        return success;
-    }
-
-    public static boolean writeToFile(Bitmap bitmap, File outBitmap) {
-        boolean success = false;
-        try {
-            FileOutputStream out = new FileOutputStream(outBitmap);
-            success = bitmap.compress(CompressFormat.JPEG, QUALITY, out);
-            out.close();
-        } catch (IOException e) {
-            Log.w(TAG, "Couldn't write bitmap to cache", e);
-            // success is already false
-        }
-        return success;
-    }
-
-    public static int copyStream(InputStream in, OutputStream out) throws IOException {
-        byte[] buffer = mBufferPool.acquire();
-        if (buffer == null) {
-            buffer = new byte[BUFFER_SIZE];
-        }
-        try {
-            int totalWritten = 0;
-            int bytesRead;
-            while ((bytesRead = in.read(buffer)) >= 0) {
-                out.write(buffer, 0, bytesRead);
-                totalWritten += bytesRead;
-            }
-            return totalWritten;
-        } finally {
-            Utils.closeSilently(in);
-            Utils.closeSilently(out);
-            mBufferPool.release(buffer);
-        }
-    }
-}
diff --git a/src/com/android/photos/data/MediaRetriever.java b/src/com/android/photos/data/MediaRetriever.java
deleted file mode 100644
index f383e5f..0000000
--- a/src/com/android/photos/data/MediaRetriever.java
+++ /dev/null
@@ -1,129 +0,0 @@
-/*
- * Copyright (C) 2013 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.photos.data;
-
-import android.net.Uri;
-
-import java.io.File;
-
-public interface MediaRetriever {
-    public enum MediaSize {
-        TemporaryThumbnail(5), Thumbnail(10), TemporaryPreview(15), Preview(20), Original(30);
-
-        private final int mValue;
-
-        private MediaSize(int value) {
-            mValue = value;
-        }
-
-        public int getValue() {
-            return mValue;
-        }
-
-        static MediaSize fromInteger(int value) {
-            switch (value) {
-                case 10:
-                    return MediaSize.Thumbnail;
-                case 20:
-                    return MediaSize.Preview;
-                case 30:
-                    return MediaSize.Original;
-                default:
-                    throw new IllegalArgumentException();
-            }
-        }
-
-        public boolean isBetterThan(MediaSize that) {
-            return mValue > that.mValue;
-        }
-
-        public boolean isTemporary() {
-            return this == TemporaryThumbnail || this == TemporaryPreview;
-        }
-    }
-
-    /**
-     * Returns the local File for the given Uri. If the image is not stored
-     * locally, null should be returned. The image should not be retrieved if it
-     * isn't already available.
-     *
-     * @param contentUri The media URI to search for.
-     * @return The local File of the image if it is available or null if it
-     *         isn't.
-     */
-    File getLocalFile(Uri contentUri);
-
-    /**
-     * Returns the fast access image type for a given image size, if supported.
-     * This image should be smaller than size and should be quick to retrieve.
-     * It does not have to obey the expected aspect ratio.
-     *
-     * @param contentUri The original media Uri.
-     * @param size The target size to search for a fast-access image.
-     * @return The fast image type supported for the given image size or null of
-     *         no fast image is supported.
-     */
-    MediaSize getFastImageSize(Uri contentUri, MediaSize size);
-
-    /**
-     * Returns a byte array containing the contents of the fast temporary image
-     * for a given image size. For example, a thumbnail may be smaller or of a
-     * different aspect ratio than the generated thumbnail.
-     *
-     * @param contentUri The original media Uri.
-     * @param temporarySize The target media size. Guaranteed to be a MediaSize
-     *            for which isTemporary() returns true.
-     * @return A byte array of contents for for the given contentUri and
-     *         fastImageType. null can be retrieved if the quick retrieval
-     *         fails.
-     */
-    byte[] getTemporaryImage(Uri contentUri, MediaSize temporarySize);
-
-    /**
-     * Retrieves an image and saves it to a file.
-     *
-     * @param contentUri The original media Uri.
-     * @param size The target media size.
-     * @param tempFile The file to write the bitmap to.
-     * @return <code>true</code> on success.
-     */
-    boolean getMedia(Uri contentUri, MediaSize imageSize, File tempFile);
-
-    /**
-     * Normalizes a URI that may have additional parameters. It is fine to
-     * return contentUri. This is executed on the calling thread, so it must be
-     * a fast access operation and cannot depend, for example, on I/O.
-     *
-     * @param contentUri The URI to normalize
-     * @param size The size of the image being requested
-     * @return The normalized URI representation of contentUri.
-     */
-    Uri normalizeUri(Uri contentUri, MediaSize size);
-
-    /**
-     * Normalize the MediaSize for a given URI. Typically the size returned
-     * would be the passed-in size. Some URIs may only have one size used and
-     * should be treaded as Thumbnails, for example. This is executed on the
-     * calling thread, so it must be a fast access operation and cannot depend,
-     * for example, on I/O.
-     *
-     * @param contentUri The URI for the size being normalized.
-     * @param size The size to be normalized.
-     * @return The normalized size of the given URI.
-     */
-    MediaSize normalizeMediaSize(Uri contentUri, MediaSize size);
-}
diff --git a/src/com/android/photos/data/NotificationWatcher.java b/src/com/android/photos/data/NotificationWatcher.java
deleted file mode 100644
index 9041c23..0000000
--- a/src/com/android/photos/data/NotificationWatcher.java
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Copyright (C) 2013 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.photos.data;
-
-import android.net.Uri;
-
-import com.android.photos.data.PhotoProvider.ChangeNotification;
-
-import java.util.ArrayList;
-
-/**
- * Used for capturing notifications from PhotoProvider without relying on
- * ContentResolver. MockContentResolver does not allow sending notification to
- * ContentObservers, so PhotoProvider allows this alternative for testing.
- */
-public class NotificationWatcher implements ChangeNotification {
-    private ArrayList<Uri> mUris = new ArrayList<Uri>();
-    private boolean mSyncToNetwork = false;
-
-    @Override
-    public void notifyChange(Uri uri, boolean syncToNetwork) {
-        mUris.add(uri);
-        mSyncToNetwork = mSyncToNetwork || syncToNetwork;
-    }
-
-    public boolean isNotified(Uri uri) {
-        return mUris.contains(uri);
-    }
-
-    public int notificationCount() {
-        return mUris.size();
-    }
-
-    public boolean syncToNetwork() {
-        return mSyncToNetwork;
-    }
-
-    public void reset() {
-        mUris.clear();
-        mSyncToNetwork = false;
-    }
-}
diff --git a/src/com/android/photos/data/PhotoDatabase.java b/src/com/android/photos/data/PhotoDatabase.java
deleted file mode 100644
index 0c7b227..0000000
--- a/src/com/android/photos/data/PhotoDatabase.java
+++ /dev/null
@@ -1,195 +0,0 @@
-/*
- * Copyright (C) 2013 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.photos.data;
-
-import android.content.Context;
-import android.database.sqlite.SQLiteDatabase;
-import android.database.sqlite.SQLiteOpenHelper;
-
-import com.android.photos.data.PhotoProvider.Accounts;
-import com.android.photos.data.PhotoProvider.Albums;
-import com.android.photos.data.PhotoProvider.Metadata;
-import com.android.photos.data.PhotoProvider.Photos;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * Used in PhotoProvider to create and access the database containing
- * information about photo and video information stored on the server.
- */
-public class PhotoDatabase extends SQLiteOpenHelper {
-    @SuppressWarnings("unused")
-    private static final String TAG = PhotoDatabase.class.getSimpleName();
-    static final int DB_VERSION = 3;
-
-    private static final String SQL_CREATE_TABLE = "CREATE TABLE ";
-
-    private static final String[][] CREATE_PHOTO = {
-        { Photos._ID, "INTEGER PRIMARY KEY AUTOINCREMENT" },
-        // Photos.ACCOUNT_ID is a foreign key to Accounts._ID
-        { Photos.ACCOUNT_ID, "INTEGER NOT NULL" },
-        { Photos.WIDTH, "INTEGER NOT NULL" },
-        { Photos.HEIGHT, "INTEGER NOT NULL" },
-        { Photos.DATE_TAKEN, "INTEGER NOT NULL" },
-        // Photos.ALBUM_ID is a foreign key to Albums._ID
-        { Photos.ALBUM_ID, "INTEGER" },
-        { Photos.MIME_TYPE, "TEXT NOT NULL" },
-        { Photos.TITLE, "TEXT" },
-        { Photos.DATE_MODIFIED, "INTEGER" },
-        { Photos.ROTATION, "INTEGER" },
-    };
-
-    private static final String[][] CREATE_ALBUM = {
-        { Albums._ID, "INTEGER PRIMARY KEY AUTOINCREMENT" },
-        // Albums.ACCOUNT_ID is a foreign key to Accounts._ID
-        { Albums.ACCOUNT_ID, "INTEGER NOT NULL" },
-        // Albums.PARENT_ID is a foreign key to Albums._ID
-        { Albums.PARENT_ID, "INTEGER" },
-        { Albums.ALBUM_TYPE, "TEXT" },
-        { Albums.VISIBILITY, "INTEGER NOT NULL" },
-        { Albums.LOCATION_STRING, "TEXT" },
-        { Albums.TITLE, "TEXT NOT NULL" },
-        { Albums.SUMMARY, "TEXT" },
-        { Albums.DATE_PUBLISHED, "INTEGER" },
-        { Albums.DATE_MODIFIED, "INTEGER" },
-        createUniqueConstraint(Albums.PARENT_ID, Albums.TITLE),
-    };
-
-    private static final String[][] CREATE_METADATA = {
-        { Metadata._ID, "INTEGER PRIMARY KEY AUTOINCREMENT" },
-        // Metadata.PHOTO_ID is a foreign key to Photos._ID
-        { Metadata.PHOTO_ID, "INTEGER NOT NULL" },
-        { Metadata.KEY, "TEXT NOT NULL" },
-        { Metadata.VALUE, "TEXT NOT NULL" },
-        createUniqueConstraint(Metadata.PHOTO_ID, Metadata.KEY),
-    };
-
-    private static final String[][] CREATE_ACCOUNT = {
-        { Accounts._ID, "INTEGER PRIMARY KEY AUTOINCREMENT" },
-        { Accounts.ACCOUNT_NAME, "TEXT UNIQUE NOT NULL" },
-    };
-
-    @Override
-    public void onCreate(SQLiteDatabase db) {
-        createTable(db, Accounts.TABLE, getAccountTableDefinition());
-        createTable(db, Albums.TABLE, getAlbumTableDefinition());
-        createTable(db, Photos.TABLE, getPhotoTableDefinition());
-        createTable(db, Metadata.TABLE, getMetadataTableDefinition());
-    }
-
-    public PhotoDatabase(Context context, String dbName, int dbVersion) {
-        super(context, dbName, null, dbVersion);
-    }
-
-    public PhotoDatabase(Context context, String dbName) {
-        super(context, dbName, null, DB_VERSION);
-    }
-
-    @Override
-    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
-        recreate(db);
-    }
-
-    @Override
-    public void onDowngrade(SQLiteDatabase db, int oldVersion, int newVersion) {
-        recreate(db);
-    }
-
-    private void recreate(SQLiteDatabase db) {
-        dropTable(db, Metadata.TABLE);
-        dropTable(db, Photos.TABLE);
-        dropTable(db, Albums.TABLE);
-        dropTable(db, Accounts.TABLE);
-        onCreate(db);
-    }
-
-    protected List<String[]> getAlbumTableDefinition() {
-        return tableCreationStrings(CREATE_ALBUM);
-    }
-
-    protected List<String[]> getPhotoTableDefinition() {
-        return tableCreationStrings(CREATE_PHOTO);
-    }
-
-    protected List<String[]> getMetadataTableDefinition() {
-        return tableCreationStrings(CREATE_METADATA);
-    }
-
-    protected List<String[]> getAccountTableDefinition() {
-        return tableCreationStrings(CREATE_ACCOUNT);
-    }
-
-    protected static void createTable(SQLiteDatabase db, String table, List<String[]> columns) {
-        StringBuilder create = new StringBuilder(SQL_CREATE_TABLE);
-        create.append(table).append('(');
-        boolean first = true;
-        for (String[] column : columns) {
-            if (!first) {
-                create.append(',');
-            }
-            first = false;
-            for (String val: column) {
-                create.append(val).append(' ');
-            }
-        }
-        create.append(')');
-        db.beginTransaction();
-        try {
-            db.execSQL(create.toString());
-            db.setTransactionSuccessful();
-        } finally {
-            db.endTransaction();
-        }
-    }
-
-    protected static String[] createUniqueConstraint(String column1, String column2) {
-        return new String[] {
-                "UNIQUE(", column1, ",", column2, ")"
-        };
-    }
-
-    protected static List<String[]> tableCreationStrings(String[][] createTable) {
-        ArrayList<String[]> create = new ArrayList<String[]>(createTable.length);
-        for (String[] line: createTable) {
-            create.add(line);
-        }
-        return create;
-    }
-
-    protected static void addToTable(List<String[]> createTable, String[][] columns, String[][] constraints) {
-        if (columns != null) {
-            for (String[] column: columns) {
-                createTable.add(0, column);
-            }
-        }
-        if (constraints != null) {
-            for (String[] constraint: constraints) {
-                createTable.add(constraint);
-            }
-        }
-    }
-
-    protected static void dropTable(SQLiteDatabase db, String table) {
-        db.beginTransaction();
-        try {
-            db.execSQL("drop table if exists " + table);
-            db.setTransactionSuccessful();
-        } finally {
-            db.endTransaction();
-        }
-    }
-}
diff --git a/src/com/android/photos/data/PhotoProvider.java b/src/com/android/photos/data/PhotoProvider.java
deleted file mode 100644
index d4310ca..0000000
--- a/src/com/android/photos/data/PhotoProvider.java
+++ /dev/null
@@ -1,536 +0,0 @@
-/*
- * Copyright (C) 2013 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.photos.data;
-
-import android.content.ContentResolver;
-import android.content.ContentUris;
-import android.content.ContentValues;
-import android.content.Context;
-import android.content.UriMatcher;
-import android.database.Cursor;
-import android.database.DatabaseUtils;
-import android.database.sqlite.SQLiteDatabase;
-import android.database.sqlite.SQLiteOpenHelper;
-import android.database.sqlite.SQLiteQueryBuilder;
-import android.media.ExifInterface;
-import android.net.Uri;
-import android.os.CancellationSignal;
-import android.provider.BaseColumns;
-
-import com.android.gallery3d.common.ApiHelper;
-
-import java.util.List;
-
-/**
- * A provider that gives access to photo and video information for media stored
- * on the server. Only media that is or will be put on the server will be
- * accessed by this provider. Use Photos.CONTENT_URI to query all photos and
- * videos. Use Albums.CONTENT_URI to query all albums. Use Metadata.CONTENT_URI
- * to query metadata about a photo or video, based on the ID of the media. Use
- * ImageCache.THUMBNAIL_CONTENT_URI, ImageCache.PREVIEW_CONTENT_URI, or
- * ImageCache.ORIGINAL_CONTENT_URI to query the path of the thumbnail, preview,
- * or original-sized image respectfully. <br/>
- * To add or update metadata, use the update function rather than insert. All
- * values for the metadata must be in the ContentValues, even if they are also
- * in the selection. The selection and selectionArgs are not used when updating
- * metadata. If the metadata values are null, the row will be deleted.
- */
-public class PhotoProvider extends SQLiteContentProvider {
-    @SuppressWarnings("unused")
-    private static final String TAG = PhotoProvider.class.getSimpleName();
-
-    protected static final String DB_NAME = "photo.db";
-    public static final String AUTHORITY = PhotoProviderAuthority.AUTHORITY;
-    static final Uri BASE_CONTENT_URI = new Uri.Builder().scheme("content").authority(AUTHORITY)
-            .build();
-
-    // Used to allow mocking out the change notification because
-    // MockContextResolver disallows system-wide notification.
-    public static interface ChangeNotification {
-        void notifyChange(Uri uri, boolean syncToNetwork);
-    }
-
-    /**
-     * Contains columns that can be accessed via Accounts.CONTENT_URI
-     */
-    public static interface Accounts extends BaseColumns {
-        /**
-         * Internal database table used for account information
-         */
-        public static final String TABLE = "accounts";
-        /**
-         * Content URI for account information
-         */
-        public static final Uri CONTENT_URI = Uri.withAppendedPath(BASE_CONTENT_URI, TABLE);
-        /**
-         * User name for this account.
-         */
-        public static final String ACCOUNT_NAME = "name";
-    }
-
-    /**
-     * Contains columns that can be accessed via Photos.CONTENT_URI.
-     */
-    public static interface Photos extends BaseColumns {
-        /**
-         * The image_type query parameter required for requesting a specific
-         * size of image.
-         */
-        public static final String MEDIA_SIZE_QUERY_PARAMETER = "media_size";
-
-        /** Internal database table used for basic photo information. */
-        public static final String TABLE = "photos";
-        /** Content URI for basic photo and video information. */
-        public static final Uri CONTENT_URI = Uri.withAppendedPath(BASE_CONTENT_URI, TABLE);
-
-        /** Long foreign key to Accounts._ID */
-        public static final String ACCOUNT_ID = "account_id";
-        /** Column name for the width of the original image. Integer value. */
-        public static final String WIDTH = "width";
-        /** Column name for the height of the original image. Integer value. */
-        public static final String HEIGHT = "height";
-        /**
-         * Column name for the date that the original image was taken. Long
-         * value indicating the milliseconds since epoch in the GMT time zone.
-         */
-        public static final String DATE_TAKEN = "date_taken";
-        /**
-         * Column name indicating the long value of the album id that this image
-         * resides in. Will be NULL if it it has not been uploaded to the
-         * server.
-         */
-        public static final String ALBUM_ID = "album_id";
-        /** The column name for the mime-type String. */
-        public static final String MIME_TYPE = "mime_type";
-        /** The title of the photo. String value. */
-        public static final String TITLE = "title";
-        /** The date the photo entry was last updated. Long value. */
-        public static final String DATE_MODIFIED = "date_modified";
-        /**
-         * The rotation of the photo in degrees, if rotation has not already
-         * been applied. Integer value.
-         */
-        public static final String ROTATION = "rotation";
-    }
-
-    /**
-     * Contains columns and Uri for accessing album information.
-     */
-    public static interface Albums extends BaseColumns {
-        /** Internal database table used album information. */
-        public static final String TABLE = "albums";
-        /** Content URI for album information. */
-        public static final Uri CONTENT_URI = Uri.withAppendedPath(BASE_CONTENT_URI, TABLE);
-
-        /** Long foreign key to Accounts._ID */
-        public static final String ACCOUNT_ID = "account_id";
-        /** Parent directory or null if this is in the root. */
-        public static final String PARENT_ID = "parent_id";
-        /** The type of album. Non-null, if album is auto-generated. String value. */
-        public static final String ALBUM_TYPE = "album_type";
-        /**
-         * Column name for the visibility level of the album. Can be any of the
-         * VISIBILITY_* values.
-         */
-        public static final String VISIBILITY = "visibility";
-        /** The user-specified location associated with the album. String value. */
-        public static final String LOCATION_STRING = "location_string";
-        /** The title of the album. String value. */
-        public static final String TITLE = "title";
-        /** A short summary of the contents of the album. String value. */
-        public static final String SUMMARY = "summary";
-        /** The date the album was created. Long value */
-        public static final String DATE_PUBLISHED = "date_published";
-        /** The date the album entry was last updated. Long value. */
-        public static final String DATE_MODIFIED = "date_modified";
-
-        // Privacy values for Albums.VISIBILITY
-        public static final int VISIBILITY_PRIVATE = 1;
-        public static final int VISIBILITY_SHARED = 2;
-        public static final int VISIBILITY_PUBLIC = 3;
-    }
-
-    /**
-     * Contains columns and Uri for accessing photo and video metadata
-     */
-    public static interface Metadata extends BaseColumns {
-        /** Internal database table used metadata information. */
-        public static final String TABLE = "metadata";
-        /** Content URI for photo and video metadata. */
-        public static final Uri CONTENT_URI = Uri.withAppendedPath(BASE_CONTENT_URI, TABLE);
-        /** Foreign key to photo_id. Long value. */
-        public static final String PHOTO_ID = "photo_id";
-        /** Metadata key. String value */
-        public static final String KEY = "key";
-        /**
-         * Metadata value. Type is based on key.
-         */
-        public static final String VALUE = "value";
-
-        /** A short summary of the photo. String value. */
-        public static final String KEY_SUMMARY = "summary";
-        /** The date the photo was added. Long value. */
-        public static final String KEY_PUBLISHED = "date_published";
-        /** The date the photo was last updated. Long value. */
-        public static final String KEY_DATE_UPDATED = "date_updated";
-        /** The size of the photo is bytes. Integer value. */
-        public static final String KEY_SIZE_IN_BTYES = "size";
-        /** The latitude associated with the photo. Double value. */
-        public static final String KEY_LATITUDE = "latitude";
-        /** The longitude associated with the photo. Double value. */
-        public static final String KEY_LONGITUDE = "longitude";
-
-        /** The make of the camera used. String value. */
-        public static final String KEY_EXIF_MAKE = ExifInterface.TAG_MAKE;
-        /** The model of the camera used. String value. */
-        public static final String KEY_EXIF_MODEL = ExifInterface.TAG_MODEL;;
-        /** The exposure time used. Float value. */
-        public static final String KEY_EXIF_EXPOSURE = ExifInterface.TAG_EXPOSURE_TIME;
-        /** Whether the flash was used. Boolean value. */
-        public static final String KEY_EXIF_FLASH = ExifInterface.TAG_FLASH;
-        /** The focal length used. Float value. */
-        public static final String KEY_EXIF_FOCAL_LENGTH = ExifInterface.TAG_FOCAL_LENGTH;
-        /** The fstop value used. Float value. */
-        public static final String KEY_EXIF_FSTOP = ExifInterface.TAG_APERTURE;
-        /** The ISO equivalent value used. Integer value. */
-        public static final String KEY_EXIF_ISO = ExifInterface.TAG_ISO;
-    }
-
-    // SQL used within this class.
-    protected static final String WHERE_ID = BaseColumns._ID + " = ?";
-    protected static final String WHERE_METADATA_ID = Metadata.PHOTO_ID + " = ? AND "
-            + Metadata.KEY + " = ?";
-
-    protected static final String SELECT_ALBUM_ID = "SELECT " + Albums._ID + " FROM "
-            + Albums.TABLE;
-    protected static final String SELECT_PHOTO_ID = "SELECT " + Photos._ID + " FROM "
-            + Photos.TABLE;
-    protected static final String SELECT_PHOTO_COUNT = "SELECT COUNT(*) FROM " + Photos.TABLE;
-    protected static final String DELETE_PHOTOS = "DELETE FROM " + Photos.TABLE;
-    protected static final String DELETE_METADATA = "DELETE FROM " + Metadata.TABLE;
-    protected static final String SELECT_METADATA_COUNT = "SELECT COUNT(*) FROM " + Metadata.TABLE;
-    protected static final String WHERE = " WHERE ";
-    protected static final String IN = " IN ";
-    protected static final String NESTED_SELECT_START = "(";
-    protected static final String NESTED_SELECT_END = ")";
-    protected static final String[] PROJECTION_COUNT = {
-        "COUNT(*)"
-    };
-
-    /**
-     * For selecting the mime-type for an image.
-     */
-    private static final String[] PROJECTION_MIME_TYPE = {
-        Photos.MIME_TYPE,
-    };
-
-    protected static final String[] BASE_COLUMNS_ID = {
-        BaseColumns._ID,
-    };
-
-    protected ChangeNotification mNotifier = null;
-    protected static final UriMatcher sUriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
-
-    protected static final int MATCH_PHOTO = 1;
-    protected static final int MATCH_PHOTO_ID = 2;
-    protected static final int MATCH_ALBUM = 3;
-    protected static final int MATCH_ALBUM_ID = 4;
-    protected static final int MATCH_METADATA = 5;
-    protected static final int MATCH_METADATA_ID = 6;
-    protected static final int MATCH_ACCOUNT = 7;
-    protected static final int MATCH_ACCOUNT_ID = 8;
-
-    static {
-        sUriMatcher.addURI(AUTHORITY, Photos.TABLE, MATCH_PHOTO);
-        // match against Photos._ID
-        sUriMatcher.addURI(AUTHORITY, Photos.TABLE + "/#", MATCH_PHOTO_ID);
-        sUriMatcher.addURI(AUTHORITY, Albums.TABLE, MATCH_ALBUM);
-        // match against Albums._ID
-        sUriMatcher.addURI(AUTHORITY, Albums.TABLE + "/#", MATCH_ALBUM_ID);
-        sUriMatcher.addURI(AUTHORITY, Metadata.TABLE, MATCH_METADATA);
-        // match against metadata/<Metadata._ID>
-        sUriMatcher.addURI(AUTHORITY, Metadata.TABLE + "/#", MATCH_METADATA_ID);
-        sUriMatcher.addURI(AUTHORITY, Accounts.TABLE, MATCH_ACCOUNT);
-        // match against Accounts._ID
-        sUriMatcher.addURI(AUTHORITY, Accounts.TABLE + "/#", MATCH_ACCOUNT_ID);
-    }
-
-    @Override
-    public int deleteInTransaction(Uri uri, String selection, String[] selectionArgs,
-            boolean callerIsSyncAdapter) {
-        int match = matchUri(uri);
-        selection = addIdToSelection(match, selection);
-        selectionArgs = addIdToSelectionArgs(match, uri, selectionArgs);
-        return deleteCascade(uri, match, selection, selectionArgs);
-    }
-
-    @Override
-    public String getType(Uri uri) {
-        Cursor cursor = query(uri, PROJECTION_MIME_TYPE, null, null, null);
-        String mimeType = null;
-        if (cursor.moveToNext()) {
-            mimeType = cursor.getString(0);
-        }
-        cursor.close();
-        return mimeType;
-    }
-
-    @Override
-    public Uri insertInTransaction(Uri uri, ContentValues values, boolean callerIsSyncAdapter) {
-        int match = matchUri(uri);
-        validateMatchTable(match);
-        String table = getTableFromMatch(match, uri);
-        SQLiteDatabase db = getDatabaseHelper().getWritableDatabase();
-        Uri insertedUri = null;
-        long id = db.insert(table, null, values);
-        if (id != -1) {
-            // uri already matches the table.
-            insertedUri = ContentUris.withAppendedId(uri, id);
-            postNotifyUri(insertedUri);
-        }
-        return insertedUri;
-    }
-
-    @Override
-    public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,
-            String sortOrder) {
-        return query(uri, projection, selection, selectionArgs, sortOrder, null);
-    }
-
-    @Override
-    public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,
-            String sortOrder, CancellationSignal cancellationSignal) {
-        projection = replaceCount(projection);
-        int match = matchUri(uri);
-        selection = addIdToSelection(match, selection);
-        selectionArgs = addIdToSelectionArgs(match, uri, selectionArgs);
-        String table = getTableFromMatch(match, uri);
-        Cursor c = query(table, projection, selection, selectionArgs, sortOrder, cancellationSignal);
-        if (c != null) {
-            c.setNotificationUri(getContext().getContentResolver(), uri);
-        }
-        return c;
-    }
-
-    @Override
-    public int updateInTransaction(Uri uri, ContentValues values, String selection,
-            String[] selectionArgs, boolean callerIsSyncAdapter) {
-        int match = matchUri(uri);
-        int rowsUpdated = 0;
-        SQLiteDatabase db = getDatabaseHelper().getWritableDatabase();
-        if (match == MATCH_METADATA) {
-            rowsUpdated = modifyMetadata(db, values);
-        } else {
-            selection = addIdToSelection(match, selection);
-            selectionArgs = addIdToSelectionArgs(match, uri, selectionArgs);
-            String table = getTableFromMatch(match, uri);
-            rowsUpdated = db.update(table, values, selection, selectionArgs);
-        }
-        postNotifyUri(uri);
-        return rowsUpdated;
-    }
-
-    public void setMockNotification(ChangeNotification notification) {
-        mNotifier = notification;
-    }
-
-    protected static String addIdToSelection(int match, String selection) {
-        String where;
-        switch (match) {
-            case MATCH_PHOTO_ID:
-            case MATCH_ALBUM_ID:
-            case MATCH_METADATA_ID:
-                where = WHERE_ID;
-                break;
-            default:
-                return selection;
-        }
-        return DatabaseUtils.concatenateWhere(selection, where);
-    }
-
-    protected static String[] addIdToSelectionArgs(int match, Uri uri, String[] selectionArgs) {
-        String[] whereArgs;
-        switch (match) {
-            case MATCH_PHOTO_ID:
-            case MATCH_ALBUM_ID:
-            case MATCH_METADATA_ID:
-                whereArgs = new String[] {
-                    uri.getPathSegments().get(1),
-                };
-                break;
-            default:
-                return selectionArgs;
-        }
-        return DatabaseUtils.appendSelectionArgs(selectionArgs, whereArgs);
-    }
-
-    protected static String[] addMetadataKeysToSelectionArgs(String[] selectionArgs, Uri uri) {
-        List<String> segments = uri.getPathSegments();
-        String[] additionalArgs = {
-                segments.get(1),
-                segments.get(2),
-        };
-
-        return DatabaseUtils.appendSelectionArgs(selectionArgs, additionalArgs);
-    }
-
-    protected static String getTableFromMatch(int match, Uri uri) {
-        String table;
-        switch (match) {
-            case MATCH_PHOTO:
-            case MATCH_PHOTO_ID:
-                table = Photos.TABLE;
-                break;
-            case MATCH_ALBUM:
-            case MATCH_ALBUM_ID:
-                table = Albums.TABLE;
-                break;
-            case MATCH_METADATA:
-            case MATCH_METADATA_ID:
-                table = Metadata.TABLE;
-                break;
-            case MATCH_ACCOUNT:
-            case MATCH_ACCOUNT_ID:
-                table = Accounts.TABLE;
-                break;
-            default:
-                throw unknownUri(uri);
-        }
-        return table;
-    }
-
-    @Override
-    public SQLiteOpenHelper getDatabaseHelper(Context context) {
-        return new PhotoDatabase(context, DB_NAME);
-    }
-
-    private int modifyMetadata(SQLiteDatabase db, ContentValues values) {
-        int rowCount;
-        if (values.get(Metadata.VALUE) == null) {
-            String[] selectionArgs = {
-                    values.getAsString(Metadata.PHOTO_ID), values.getAsString(Metadata.KEY),
-            };
-            rowCount = db.delete(Metadata.TABLE, WHERE_METADATA_ID, selectionArgs);
-        } else {
-            long rowId = db.replace(Metadata.TABLE, null, values);
-            rowCount = (rowId == -1) ? 0 : 1;
-        }
-        return rowCount;
-    }
-
-    private int matchUri(Uri uri) {
-        int match = sUriMatcher.match(uri);
-        if (match == UriMatcher.NO_MATCH) {
-            throw unknownUri(uri);
-        }
-        return match;
-    }
-
-    @Override
-    protected void notifyChange(ContentResolver resolver, Uri uri, boolean syncToNetwork) {
-        if (mNotifier != null) {
-            mNotifier.notifyChange(uri, syncToNetwork);
-        } else {
-            super.notifyChange(resolver, uri, syncToNetwork);
-        }
-    }
-
-    protected static IllegalArgumentException unknownUri(Uri uri) {
-        return new IllegalArgumentException("Unknown Uri format: " + uri);
-    }
-
-    protected static String nestWhere(String matchColumn, String table, String nestedWhere) {
-        String query = SQLiteQueryBuilder.buildQueryString(false, table, BASE_COLUMNS_ID,
-                nestedWhere, null, null, null, null);
-        return matchColumn + IN + NESTED_SELECT_START + query + NESTED_SELECT_END;
-    }
-
-    protected static String metadataSelectionFromPhotos(String where) {
-        return nestWhere(Metadata.PHOTO_ID, Photos.TABLE, where);
-    }
-
-    protected static String photoSelectionFromAlbums(String where) {
-        return nestWhere(Photos.ALBUM_ID, Albums.TABLE, where);
-    }
-
-    protected static String photoSelectionFromAccounts(String where) {
-        return nestWhere(Photos.ACCOUNT_ID, Accounts.TABLE, where);
-    }
-
-    protected static String albumSelectionFromAccounts(String where) {
-        return nestWhere(Albums.ACCOUNT_ID, Accounts.TABLE, where);
-    }
-
-    protected int deleteCascade(Uri uri, int match, String selection, String[] selectionArgs) {
-        switch (match) {
-            case MATCH_PHOTO:
-            case MATCH_PHOTO_ID:
-                deleteCascade(Metadata.CONTENT_URI, MATCH_METADATA,
-                        metadataSelectionFromPhotos(selection), selectionArgs);
-                break;
-            case MATCH_ALBUM:
-            case MATCH_ALBUM_ID:
-                deleteCascade(Photos.CONTENT_URI, MATCH_PHOTO,
-                        photoSelectionFromAlbums(selection), selectionArgs);
-                break;
-            case MATCH_ACCOUNT:
-            case MATCH_ACCOUNT_ID:
-                deleteCascade(Photos.CONTENT_URI, MATCH_PHOTO,
-                        photoSelectionFromAccounts(selection), selectionArgs);
-                deleteCascade(Albums.CONTENT_URI, MATCH_ALBUM,
-                        albumSelectionFromAccounts(selection), selectionArgs);
-                break;
-        }
-        SQLiteDatabase db = getDatabaseHelper().getWritableDatabase();
-        String table = getTableFromMatch(match, uri);
-        int deleted = db.delete(table, selection, selectionArgs);
-        if (deleted > 0) {
-            postNotifyUri(uri);
-        }
-        return deleted;
-    }
-
-    private static void validateMatchTable(int match) {
-        switch (match) {
-            case MATCH_PHOTO:
-            case MATCH_ALBUM:
-            case MATCH_METADATA:
-            case MATCH_ACCOUNT:
-                break;
-            default:
-                throw new IllegalArgumentException("Operation not allowed on an existing row.");
-        }
-    }
-
-    protected Cursor query(String table, String[] columns, String selection,
-            String[] selectionArgs, String orderBy, CancellationSignal cancellationSignal) {
-        SQLiteDatabase db = getDatabaseHelper().getReadableDatabase();
-        if (ApiHelper.HAS_CANCELLATION_SIGNAL) {
-            return db.query(false, table, columns, selection, selectionArgs, null, null,
-                    orderBy, null, cancellationSignal);
-        } else {
-            return db.query(table, columns, selection, selectionArgs, null, null, orderBy);
-        }
-    }
-
-    protected static String[] replaceCount(String[] projection) {
-        if (projection != null && projection.length == 1
-                && BaseColumns._COUNT.equals(projection[0])) {
-            return PROJECTION_COUNT;
-        }
-        return projection;
-    }
-}
diff --git a/src/com/android/photos/data/PhotoSetLoader.java b/src/com/android/photos/data/PhotoSetLoader.java
deleted file mode 100644
index 56c82c4..0000000
--- a/src/com/android/photos/data/PhotoSetLoader.java
+++ /dev/null
@@ -1,115 +0,0 @@
-/*
- * Copyright (C) 2013 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.photos.data;
-
-import android.content.Context;
-import android.content.CursorLoader;
-import android.database.ContentObserver;
-import android.database.Cursor;
-import android.graphics.drawable.Drawable;
-import android.net.Uri;
-import android.provider.MediaStore;
-import android.provider.MediaStore.Files;
-import android.provider.MediaStore.Files.FileColumns;
-
-import com.android.photos.drawables.DataUriThumbnailDrawable;
-import com.android.photos.shims.LoaderCompatShim;
-
-import java.util.ArrayList;
-
-public class PhotoSetLoader extends CursorLoader implements LoaderCompatShim<Cursor> {
-
-    public static final String SUPPORTED_OPERATIONS = "supported_operations";
-
-    private static final Uri CONTENT_URI = Files.getContentUri("external");
-    public static final String[] PROJECTION = new String[] {
-        FileColumns._ID,
-        FileColumns.DATA,
-        FileColumns.WIDTH,
-        FileColumns.HEIGHT,
-        FileColumns.DATE_ADDED,
-        FileColumns.MEDIA_TYPE,
-        SUPPORTED_OPERATIONS,
-    };
-
-    private static final String SORT_ORDER = FileColumns.DATE_ADDED + " DESC";
-    private static final String SELECTION =
-            FileColumns.MEDIA_TYPE + " == " + FileColumns.MEDIA_TYPE_IMAGE
-            + " OR "
-            + FileColumns.MEDIA_TYPE + " == " + FileColumns.MEDIA_TYPE_VIDEO;
-
-    public static final int INDEX_ID = 0;
-    public static final int INDEX_DATA = 1;
-    public static final int INDEX_WIDTH = 2;
-    public static final int INDEX_HEIGHT = 3;
-    public static final int INDEX_DATE_ADDED = 4;
-    public static final int INDEX_MEDIA_TYPE = 5;
-    public static final int INDEX_SUPPORTED_OPERATIONS = 6;
-
-    private static final Uri GLOBAL_CONTENT_URI = Uri.parse("content://" + MediaStore.AUTHORITY + "/external/");
-    private final ContentObserver mGlobalObserver = new ForceLoadContentObserver();
-
-    public PhotoSetLoader(Context context) {
-        super(context, CONTENT_URI, PROJECTION, SELECTION, null, SORT_ORDER);
-    }
-
-    @Override
-    protected void onStartLoading() {
-        super.onStartLoading();
-        getContext().getContentResolver().registerContentObserver(GLOBAL_CONTENT_URI,
-                true, mGlobalObserver);
-    }
-
-    @Override
-    protected void onReset() {
-        super.onReset();
-        getContext().getContentResolver().unregisterContentObserver(mGlobalObserver);
-    }
-
-    @Override
-    public Drawable drawableForItem(Cursor item, Drawable recycle) {
-        DataUriThumbnailDrawable drawable = null;
-        if (recycle == null || !(recycle instanceof DataUriThumbnailDrawable)) {
-            drawable = new DataUriThumbnailDrawable();
-        } else {
-            drawable = (DataUriThumbnailDrawable) recycle;
-        }
-        drawable.setImage(item.getString(INDEX_DATA),
-                item.getInt(INDEX_WIDTH), item.getInt(INDEX_HEIGHT));
-        return drawable;
-    }
-
-    @Override
-    public Uri uriForItem(Cursor item) {
-        return null;
-    }
-
-    @Override
-    public ArrayList<Uri> urisForSubItems(Cursor item) {
-        return null;
-    }
-
-    @Override
-    public void deleteItemWithPath(Object path) {
-
-    }
-
-    @Override
-    public Object getPathForItem(Cursor item) {
-        return null;
-    }
-}
diff --git a/src/com/android/photos/data/SQLiteContentProvider.java b/src/com/android/photos/data/SQLiteContentProvider.java
deleted file mode 100644
index daffa6e..0000000
--- a/src/com/android/photos/data/SQLiteContentProvider.java
+++ /dev/null
@@ -1,265 +0,0 @@
-/*
- * Copyright (C) 2013 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.photos.data;
-
-import android.content.ContentProvider;
-import android.content.ContentProviderOperation;
-import android.content.ContentProviderResult;
-import android.content.ContentResolver;
-import android.content.ContentValues;
-import android.content.Context;
-import android.content.OperationApplicationException;
-import android.database.sqlite.SQLiteDatabase;
-import android.database.sqlite.SQLiteOpenHelper;
-import android.net.Uri;
-
-import java.util.ArrayList;
-import java.util.HashSet;
-import java.util.Set;
-
-/**
- * General purpose {@link ContentProvider} base class that uses SQLiteDatabase
- * for storage.
- */
-public abstract class SQLiteContentProvider extends ContentProvider {
-
-    @SuppressWarnings("unused")
-    private static final String TAG = "SQLiteContentProvider";
-
-    private SQLiteOpenHelper mOpenHelper;
-    private Set<Uri> mChangedUris;
-
-    private final ThreadLocal<Boolean> mApplyingBatch = new ThreadLocal<Boolean>();
-    private static final int SLEEP_AFTER_YIELD_DELAY = 4000;
-
-    /**
-     * Maximum number of operations allowed in a batch between yield points.
-     */
-    private static final int MAX_OPERATIONS_PER_YIELD_POINT = 500;
-
-    @Override
-    public boolean onCreate() {
-        Context context = getContext();
-        mOpenHelper = getDatabaseHelper(context);
-        mChangedUris = new HashSet<Uri>();
-        return true;
-    }
-
-    @Override
-    public void shutdown() {
-        getDatabaseHelper().close();
-    }
-
-    /**
-     * Returns a {@link SQLiteOpenHelper} that can open the database.
-     */
-    public abstract SQLiteOpenHelper getDatabaseHelper(Context context);
-
-    /**
-     * The equivalent of the {@link #insert} method, but invoked within a
-     * transaction.
-     */
-    public abstract Uri insertInTransaction(Uri uri, ContentValues values,
-            boolean callerIsSyncAdapter);
-
-    /**
-     * The equivalent of the {@link #update} method, but invoked within a
-     * transaction.
-     */
-    public abstract int updateInTransaction(Uri uri, ContentValues values, String selection,
-            String[] selectionArgs, boolean callerIsSyncAdapter);
-
-    /**
-     * The equivalent of the {@link #delete} method, but invoked within a
-     * transaction.
-     */
-    public abstract int deleteInTransaction(Uri uri, String selection, String[] selectionArgs,
-            boolean callerIsSyncAdapter);
-
-    /**
-     * Call this to add a URI to the list of URIs to be notified when the
-     * transaction is committed.
-     */
-    protected void postNotifyUri(Uri uri) {
-        synchronized (mChangedUris) {
-            mChangedUris.add(uri);
-        }
-    }
-
-    public boolean isCallerSyncAdapter(Uri uri) {
-        return false;
-    }
-
-    public SQLiteOpenHelper getDatabaseHelper() {
-        return mOpenHelper;
-    }
-
-    private boolean applyingBatch() {
-        return mApplyingBatch.get() != null && mApplyingBatch.get();
-    }
-
-    @Override
-    public Uri insert(Uri uri, ContentValues values) {
-        Uri result = null;
-        boolean callerIsSyncAdapter = isCallerSyncAdapter(uri);
-        boolean applyingBatch = applyingBatch();
-        if (!applyingBatch) {
-            SQLiteDatabase db = mOpenHelper.getWritableDatabase();
-            db.beginTransaction();
-            try {
-                result = insertInTransaction(uri, values, callerIsSyncAdapter);
-                db.setTransactionSuccessful();
-            } finally {
-                db.endTransaction();
-            }
-
-            onEndTransaction(callerIsSyncAdapter);
-        } else {
-            result = insertInTransaction(uri, values, callerIsSyncAdapter);
-        }
-        return result;
-    }
-
-    @Override
-    public int bulkInsert(Uri uri, ContentValues[] values) {
-        int numValues = values.length;
-        boolean callerIsSyncAdapter = isCallerSyncAdapter(uri);
-        SQLiteDatabase db = mOpenHelper.getWritableDatabase();
-        db.beginTransaction();
-        try {
-            for (int i = 0; i < numValues; i++) {
-                @SuppressWarnings("unused")
-                Uri result = insertInTransaction(uri, values[i], callerIsSyncAdapter);
-                db.yieldIfContendedSafely();
-            }
-            db.setTransactionSuccessful();
-        } finally {
-            db.endTransaction();
-        }
-
-        onEndTransaction(callerIsSyncAdapter);
-        return numValues;
-    }
-
-    @Override
-    public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
-        int count = 0;
-        boolean callerIsSyncAdapter = isCallerSyncAdapter(uri);
-        boolean applyingBatch = applyingBatch();
-        if (!applyingBatch) {
-            SQLiteDatabase db = mOpenHelper.getWritableDatabase();
-            db.beginTransaction();
-            try {
-                count = updateInTransaction(uri, values, selection, selectionArgs,
-                        callerIsSyncAdapter);
-                db.setTransactionSuccessful();
-            } finally {
-                db.endTransaction();
-            }
-
-            onEndTransaction(callerIsSyncAdapter);
-        } else {
-            count = updateInTransaction(uri, values, selection, selectionArgs, callerIsSyncAdapter);
-        }
-
-        return count;
-    }
-
-    @Override
-    public int delete(Uri uri, String selection, String[] selectionArgs) {
-        int count = 0;
-        boolean callerIsSyncAdapter = isCallerSyncAdapter(uri);
-        boolean applyingBatch = applyingBatch();
-        if (!applyingBatch) {
-            SQLiteDatabase db = mOpenHelper.getWritableDatabase();
-            db.beginTransaction();
-            try {
-                count = deleteInTransaction(uri, selection, selectionArgs, callerIsSyncAdapter);
-                db.setTransactionSuccessful();
-            } finally {
-                db.endTransaction();
-            }
-
-            onEndTransaction(callerIsSyncAdapter);
-        } else {
-            count = deleteInTransaction(uri, selection, selectionArgs, callerIsSyncAdapter);
-        }
-        return count;
-    }
-
-    @Override
-    public ContentProviderResult[] applyBatch(ArrayList<ContentProviderOperation> operations)
-            throws OperationApplicationException {
-        int ypCount = 0;
-        int opCount = 0;
-        boolean callerIsSyncAdapter = false;
-        SQLiteDatabase db = mOpenHelper.getWritableDatabase();
-        db.beginTransaction();
-        try {
-            mApplyingBatch.set(true);
-            final int numOperations = operations.size();
-            final ContentProviderResult[] results = new ContentProviderResult[numOperations];
-            for (int i = 0; i < numOperations; i++) {
-                if (++opCount >= MAX_OPERATIONS_PER_YIELD_POINT) {
-                    throw new OperationApplicationException(
-                            "Too many content provider operations between yield points. "
-                                    + "The maximum number of operations per yield point is "
-                                    + MAX_OPERATIONS_PER_YIELD_POINT, ypCount);
-                }
-                final ContentProviderOperation operation = operations.get(i);
-                if (!callerIsSyncAdapter && isCallerSyncAdapter(operation.getUri())) {
-                    callerIsSyncAdapter = true;
-                }
-                if (i > 0 && operation.isYieldAllowed()) {
-                    opCount = 0;
-                    if (db.yieldIfContendedSafely(SLEEP_AFTER_YIELD_DELAY)) {
-                        ypCount++;
-                    }
-                }
-                results[i] = operation.apply(this, results, i);
-            }
-            db.setTransactionSuccessful();
-            return results;
-        } finally {
-            mApplyingBatch.set(false);
-            db.endTransaction();
-            onEndTransaction(callerIsSyncAdapter);
-        }
-    }
-
-    protected Set<Uri> onEndTransaction(boolean callerIsSyncAdapter) {
-        Set<Uri> changed;
-        synchronized (mChangedUris) {
-            changed = new HashSet<Uri>(mChangedUris);
-            mChangedUris.clear();
-        }
-        ContentResolver resolver = getContext().getContentResolver();
-        for (Uri uri : changed) {
-            boolean syncToNetwork = !callerIsSyncAdapter && syncToNetwork(uri);
-            notifyChange(resolver, uri, syncToNetwork);
-        }
-        return changed;
-    }
-
-    protected void notifyChange(ContentResolver resolver, Uri uri, boolean syncToNetwork) {
-        resolver.notifyChange(uri, null, syncToNetwork);
-    }
-
-    protected boolean syncToNetwork(Uri uri) {
-        return false;
-    }
-}
\ No newline at end of file
diff --git a/src/com/android/photos/data/SparseArrayBitmapPool.java b/src/com/android/photos/data/SparseArrayBitmapPool.java
deleted file mode 100644
index 95e1026..0000000
--- a/src/com/android/photos/data/SparseArrayBitmapPool.java
+++ /dev/null
@@ -1,212 +0,0 @@
-/*
- * Copyright (C) 2013 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.photos.data;
-
-import android.graphics.Bitmap;
-import android.util.SparseArray;
-
-import android.util.Pools.Pool;
-import android.util.Pools.SimplePool;
-
-/**
- * Bitmap pool backed by a sparse array indexing linked lists of bitmaps
- * sharing the same width. Performance will degrade if using this to store
- * many bitmaps with the same width but many different heights.
- */
-public class SparseArrayBitmapPool {
-
-    private int mCapacityBytes;
-    private SparseArray<Node> mStore = new SparseArray<Node>();
-    private int mSizeBytes = 0;
-
-    private Pool<Node> mNodePool;
-    private Node mPoolNodesHead = null;
-    private Node mPoolNodesTail = null;
-
-    protected static class Node {
-        Bitmap bitmap;
-
-        // Each node is part of two doubly linked lists:
-        // - A pool-level list (accessed by mPoolNodesHead and mPoolNodesTail)
-        //   that is used for FIFO eviction of nodes when the pool gets full.
-        // - A bucket-level list for each index of the sparse array, so that
-        //   each index can store more than one item.
-        Node prevInBucket;
-        Node nextInBucket;
-        Node nextInPool;
-        Node prevInPool;
-    }
-
-    /**
-     * @param capacityBytes Maximum capacity of the pool in bytes.
-     * @param nodePool Shared pool to use for recycling linked list nodes, or null.
-     */
-    public SparseArrayBitmapPool(int capacityBytes, Pool<Node> nodePool) {
-        mCapacityBytes = capacityBytes;
-        if (nodePool == null) {
-            mNodePool = new SimplePool<Node>(32);
-        } else {
-            mNodePool = nodePool;
-        }
-    }
-
-    /**
-     * Set the maximum capacity of the pool, and if necessary trim it down to size.
-     */
-    public synchronized void setCapacity(int capacityBytes) {
-        mCapacityBytes = capacityBytes;
-
-        // No-op unless current size exceeds the new capacity.
-        freeUpCapacity(0);
-    }
-
-    private void freeUpCapacity(int bytesNeeded) {
-        int targetSize = mCapacityBytes - bytesNeeded;
-        // Repeatedly remove the oldest node until we have freed up at least bytesNeeded.
-        while (mPoolNodesTail != null && mSizeBytes > targetSize) {
-            unlinkAndRecycleNode(mPoolNodesTail, true);
-        }
-    }
-
-    private void unlinkAndRecycleNode(Node n, boolean recycleBitmap) {
-        // Unlink the node from its sparse array bucket list.
-        if (n.prevInBucket != null) {
-            // This wasn't the head, update the previous node.
-            n.prevInBucket.nextInBucket = n.nextInBucket;
-        } else {
-            // This was the head of the bucket, replace it with the next node.
-            mStore.put(n.bitmap.getWidth(), n.nextInBucket);
-        }
-        if (n.nextInBucket != null) {
-            // This wasn't the tail, update the next node.
-            n.nextInBucket.prevInBucket = n.prevInBucket;
-        }
-
-        // Unlink the node from the pool-wide list.
-        if (n.prevInPool != null) {
-            // This wasn't the head, update the previous node.
-            n.prevInPool.nextInPool = n.nextInPool;
-        } else {
-            // This was the head of the pool-wide list, update the head pointer.
-            mPoolNodesHead = n.nextInPool;
-        }
-        if (n.nextInPool != null) {
-            // This wasn't the tail, update the next node.
-            n.nextInPool.prevInPool = n.prevInPool;
-        } else {
-            // This was the tail, update the tail pointer.
-            mPoolNodesTail = n.prevInPool;
-        }
-
-        // Recycle the node.
-        n.nextInBucket = null;
-        n.nextInPool = null;
-        n.prevInBucket = null;
-        n.prevInPool = null;
-        mSizeBytes -= n.bitmap.getByteCount();
-        if (recycleBitmap) n.bitmap.recycle();
-        n.bitmap = null;
-        mNodePool.release(n);
-    }
-
-    /**
-     * @return Capacity of the pool in bytes.
-     */
-    public synchronized int getCapacity() {
-        return mCapacityBytes;
-    }
-
-    /**
-     * @return Total size in bytes of the bitmaps stored in the pool.
-     */
-    public synchronized int getSize() {
-        return mSizeBytes;
-    }
-
-    /**
-     * @return Bitmap from the pool with the desired height/width or null if none available.
-     */
-    public synchronized Bitmap get(int width, int height) {
-        Node cur = mStore.get(width);
-
-        // Traverse the list corresponding to the width bucket in the
-        // sparse array, and unlink and return the first bitmap that
-        // also has the correct height.
-        while (cur != null) {
-            if (cur.bitmap.getHeight() == height) {
-                Bitmap b = cur.bitmap;
-                unlinkAndRecycleNode(cur, false);
-                return b;
-            }
-            cur = cur.nextInBucket;
-        }
-        return null;
-    }
-
-    /**
-     * Adds the given bitmap to the pool.
-     * @return Whether the bitmap was added to the pool.
-     */
-    public synchronized boolean put(Bitmap b) {
-        if (b == null) {
-            return false;
-        }
-
-        // Ensure there is enough room to contain the new bitmap.
-        int bytes = b.getByteCount();
-        freeUpCapacity(bytes);
-
-        Node newNode = mNodePool.acquire();
-        if (newNode == null) {
-            newNode = new Node();
-        }
-        newNode.bitmap = b;
-
-        // We append to the head, and freeUpCapacity clears from the tail,
-        // resulting in FIFO eviction.
-        newNode.prevInBucket = null;
-        newNode.prevInPool = null;
-        newNode.nextInPool = mPoolNodesHead;
-        mPoolNodesHead = newNode;
-
-        // Insert the node into its appropriate bucket based on width.
-        int key = b.getWidth();
-        newNode.nextInBucket = mStore.get(key);
-        if (newNode.nextInBucket != null) {
-            // The bucket already had nodes, update the old head.
-            newNode.nextInBucket.prevInBucket = newNode;
-        }
-        mStore.put(key, newNode);
-
-        if (newNode.nextInPool == null) {
-            // This is the only node in the list, update the tail pointer.
-            mPoolNodesTail = newNode;
-        } else {
-            newNode.nextInPool.prevInPool = newNode;
-        }
-        mSizeBytes += bytes;
-        return true;
-    }
-
-    /**
-     * Empty the pool, recycling all the bitmaps currently in it.
-     */
-    public synchronized void clear() {
-        // Clearing is equivalent to ensuring all the capacity is available.
-        freeUpCapacity(mCapacityBytes);
-    }
-}
diff --git a/src/com/android/photos/drawables/AutoThumbnailDrawable.java b/src/com/android/photos/drawables/AutoThumbnailDrawable.java
deleted file mode 100644
index b51b670..0000000
--- a/src/com/android/photos/drawables/AutoThumbnailDrawable.java
+++ /dev/null
@@ -1,309 +0,0 @@
-/*
- * Copyright (C) 2013 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.photos.drawables;
-
-import android.graphics.Bitmap;
-import android.graphics.BitmapFactory;
-import android.graphics.Canvas;
-import android.graphics.ColorFilter;
-import android.graphics.Matrix;
-import android.graphics.Paint;
-import android.graphics.PixelFormat;
-import android.graphics.Rect;
-import android.graphics.drawable.Drawable;
-import android.util.Log;
-
-import com.android.photos.data.GalleryBitmapPool;
-
-import java.io.InputStream;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
-
-public abstract class AutoThumbnailDrawable<T> extends Drawable {
-
-    private static final String TAG = "AutoThumbnailDrawable";
-
-    private static ExecutorService sThreadPool = Executors.newSingleThreadExecutor();
-    private static GalleryBitmapPool sBitmapPool = GalleryBitmapPool.getInstance();
-    private static byte[] sTempStorage = new byte[64 * 1024];
-
-    // UI thread only
-    private Paint mPaint = new Paint();
-    private Matrix mDrawMatrix = new Matrix();
-
-    // Decoder thread only
-    private BitmapFactory.Options mOptions = new BitmapFactory.Options();
-
-    // Shared, guarded by mLock
-    private Object mLock = new Object();
-    private Bitmap mBitmap;
-    protected T mData;
-    private boolean mIsQueued;
-    private int mImageWidth, mImageHeight;
-    private Rect mBounds = new Rect();
-    private int mSampleSize = 1;
-
-    public AutoThumbnailDrawable() {
-        mPaint.setAntiAlias(true);
-        mPaint.setFilterBitmap(true);
-        mDrawMatrix.reset();
-        mOptions.inTempStorage = sTempStorage;
-    }
-
-    protected abstract byte[] getPreferredImageBytes(T data);
-    protected abstract InputStream getFallbackImageStream(T data);
-    protected abstract boolean dataChangedLocked(T data);
-
-    public void setImage(T data, int width, int height) {
-        if (!dataChangedLocked(data)) return;
-        synchronized (mLock) {
-            mImageWidth = width;
-            mImageHeight = height;
-            mData = data;
-            setBitmapLocked(null);
-            refreshSampleSizeLocked();
-        }
-        invalidateSelf();
-    }
-
-    private void setBitmapLocked(Bitmap b) {
-        if (b == mBitmap) {
-            return;
-        }
-        if (mBitmap != null) {
-            sBitmapPool.put(mBitmap);
-        }
-        mBitmap = b;
-    }
-
-    @Override
-    protected void onBoundsChange(Rect bounds) {
-        super.onBoundsChange(bounds);
-        synchronized (mLock) {
-            mBounds.set(bounds);
-            if (mBounds.isEmpty()) {
-                mBitmap = null;
-            } else {
-                refreshSampleSizeLocked();
-                updateDrawMatrixLocked();
-            }
-        }
-        invalidateSelf();
-    }
-
-    @Override
-    public void draw(Canvas canvas) {
-        if (mBitmap != null) {
-            canvas.save();
-            canvas.clipRect(mBounds);
-            canvas.concat(mDrawMatrix);
-            canvas.drawBitmap(mBitmap, 0, 0, mPaint);
-            canvas.restore();
-        } else {
-            // TODO: Draw placeholder...?
-        }
-    }
-
-    private void updateDrawMatrixLocked() {
-        if (mBitmap == null || mBounds.isEmpty()) {
-            mDrawMatrix.reset();
-            return;
-        }
-
-        float scale;
-        float dx = 0, dy = 0;
-
-        int dwidth = mBitmap.getWidth();
-        int dheight = mBitmap.getHeight();
-        int vwidth = mBounds.width();
-        int vheight = mBounds.height();
-
-        // Calculates a matrix similar to ScaleType.CENTER_CROP
-        if (dwidth * vheight > vwidth * dheight) {
-            scale = (float) vheight / (float) dheight;
-            dx = (vwidth - dwidth * scale) * 0.5f;
-        } else {
-            scale = (float) vwidth / (float) dwidth;
-            dy = (vheight - dheight * scale) * 0.5f;
-        }
-        if (scale < .8f) {
-            Log.w(TAG, "sample size was too small! Overdrawing! " + scale + ", " + mSampleSize);
-        } else if (scale > 1.5f) {
-            Log.w(TAG, "Potential quality loss! " + scale + ", " + mSampleSize);
-        }
-
-        mDrawMatrix.setScale(scale, scale);
-        mDrawMatrix.postTranslate((int) (dx + 0.5f), (int) (dy + 0.5f));
-    }
-
-    private int calculateSampleSizeLocked(int dwidth, int dheight) {
-        float scale;
-
-        int vwidth = mBounds.width();
-        int vheight = mBounds.height();
-
-        // Inverse of updateDrawMatrixLocked
-        if (dwidth * vheight > vwidth * dheight) {
-            scale = (float) dheight / (float) vheight;
-        } else {
-            scale = (float) dwidth / (float) vwidth;
-        }
-        int result = Math.round(scale);
-        return result > 0 ? result : 1;
-    }
-
-    private void refreshSampleSizeLocked() {
-        if (mBounds.isEmpty() || mImageWidth == 0 || mImageHeight == 0) {
-            return;
-        }
-
-        int sampleSize = calculateSampleSizeLocked(mImageWidth, mImageHeight);
-        if (sampleSize != mSampleSize || mBitmap == null) {
-            mSampleSize = sampleSize;
-            loadBitmapLocked();
-        }
-    }
-
-    private void loadBitmapLocked() {
-        if (!mIsQueued && !mBounds.isEmpty()) {
-            unscheduleSelf(mUpdateBitmap);
-            sThreadPool.execute(mLoadBitmap);
-            mIsQueued = true;
-        }
-    }
-
-    public float getAspectRatio() {
-        return (float) mImageWidth / (float) mImageHeight;
-    }
-
-    @Override
-    public int getIntrinsicWidth() {
-        return -1;
-    }
-
-    @Override
-    public int getIntrinsicHeight() {
-        return -1;
-    }
-
-    @Override
-    public int getOpacity() {
-        Bitmap bm = mBitmap;
-        return (bm == null || bm.hasAlpha() || mPaint.getAlpha() < 255) ?
-                PixelFormat.TRANSLUCENT : PixelFormat.OPAQUE;
-    }
-
-    @Override
-    public void setAlpha(int alpha) {
-        int oldAlpha = mPaint.getAlpha();
-        if (alpha != oldAlpha) {
-            mPaint.setAlpha(alpha);
-            invalidateSelf();
-        }
-    }
-
-    @Override
-    public void setColorFilter(ColorFilter cf) {
-        mPaint.setColorFilter(cf);
-        invalidateSelf();
-    }
-
-    private final Runnable mLoadBitmap = new Runnable() {
-        @Override
-        public void run() {
-            T data;
-            synchronized (mLock) {
-                data = mData;
-            }
-            int preferredSampleSize = 1;
-            byte[] preferred = getPreferredImageBytes(data);
-            boolean hasPreferred = (preferred != null && preferred.length > 0);
-            if (hasPreferred) {
-                mOptions.inJustDecodeBounds = true;
-                BitmapFactory.decodeByteArray(preferred, 0, preferred.length, mOptions);
-                mOptions.inJustDecodeBounds = false;
-            }
-            int sampleSize, width, height;
-            synchronized (mLock) {
-                if (dataChangedLocked(data)) {
-                    return;
-                }
-                width = mImageWidth;
-                height = mImageHeight;
-                if (hasPreferred) {
-                    preferredSampleSize = calculateSampleSizeLocked(
-                            mOptions.outWidth, mOptions.outHeight);
-                }
-                sampleSize = calculateSampleSizeLocked(width, height);
-                mIsQueued = false;
-            }
-            Bitmap b = null;
-            InputStream is = null;
-            try {
-                if (hasPreferred) {
-                    mOptions.inSampleSize = preferredSampleSize;
-                    mOptions.inBitmap = sBitmapPool.get(
-                            mOptions.outWidth / preferredSampleSize,
-                            mOptions.outHeight / preferredSampleSize);
-                    b = BitmapFactory.decodeByteArray(preferred, 0, preferred.length, mOptions);
-                    if (mOptions.inBitmap != null && b != mOptions.inBitmap) {
-                        sBitmapPool.put(mOptions.inBitmap);
-                        mOptions.inBitmap = null;
-                    }
-                }
-                if (b == null) {
-                    is = getFallbackImageStream(data);
-                    mOptions.inSampleSize = sampleSize;
-                    mOptions.inBitmap = sBitmapPool.get(width / sampleSize, height / sampleSize);
-                    b = BitmapFactory.decodeStream(is, null, mOptions);
-                    if (mOptions.inBitmap != null && b != mOptions.inBitmap) {
-                        sBitmapPool.put(mOptions.inBitmap);
-                        mOptions.inBitmap = null;
-                    }
-                }
-            } catch (Exception e) {
-                Log.d(TAG, "Failed to fetch bitmap", e);
-                return;
-            } finally {
-                try {
-                    if (is != null) {
-                        is.close();
-                    }
-                } catch (Exception e) {}
-                if (b != null) {
-                    synchronized (mLock) {
-                        if (!dataChangedLocked(data)) {
-                            setBitmapLocked(b);
-                            scheduleSelf(mUpdateBitmap, 0);
-                        }
-                    }
-                }
-            }
-        }
-    };
-
-    private final Runnable mUpdateBitmap = new Runnable() {
-        @Override
-        public void run() {
-            synchronized (AutoThumbnailDrawable.this) {
-                updateDrawMatrixLocked();
-                invalidateSelf();
-            }
-        }
-    };
-
-}
diff --git a/src/com/android/photos/drawables/DataUriThumbnailDrawable.java b/src/com/android/photos/drawables/DataUriThumbnailDrawable.java
deleted file mode 100644
index c83b0c8..0000000
--- a/src/com/android/photos/drawables/DataUriThumbnailDrawable.java
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Copyright (C) 2013 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.photos.drawables;
-
-import android.media.ExifInterface;
-import android.text.TextUtils;
-
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.io.InputStream;
-
-public class DataUriThumbnailDrawable extends AutoThumbnailDrawable<String> {
-
-    @Override
-    protected byte[] getPreferredImageBytes(String data) {
-        byte[] thumbnail = null;
-        try {
-            ExifInterface exif = new ExifInterface(data);
-            if (exif.hasThumbnail()) {
-                thumbnail = exif.getThumbnail();
-             }
-        } catch (IOException e) { }
-        return thumbnail;
-    }
-
-    @Override
-    protected InputStream getFallbackImageStream(String data) {
-        try {
-            return new FileInputStream(data);
-        } catch (FileNotFoundException e) {
-            return null;
-        }
-    }
-
-    @Override
-    protected boolean dataChangedLocked(String data) {
-        return !TextUtils.equals(mData, data);
-    }
-}
diff --git a/src/com/android/photos/shims/BitmapJobDrawable.java b/src/com/android/photos/shims/BitmapJobDrawable.java
deleted file mode 100644
index 32dbc80..0000000
--- a/src/com/android/photos/shims/BitmapJobDrawable.java
+++ /dev/null
@@ -1,180 +0,0 @@
-/*
- * Copyright (C) 2013 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.photos.shims;
-
-import android.graphics.Bitmap;
-import android.graphics.Canvas;
-import android.graphics.ColorFilter;
-import android.graphics.Matrix;
-import android.graphics.Paint;
-import android.graphics.PixelFormat;
-import android.graphics.Rect;
-import android.graphics.drawable.Drawable;
-
-import com.android.gallery3d.data.MediaItem;
-import com.android.gallery3d.ui.BitmapLoader;
-import com.android.gallery3d.util.Future;
-import com.android.gallery3d.util.FutureListener;
-import com.android.gallery3d.util.ThreadPool;
-import com.android.photos.data.GalleryBitmapPool;
-
-
-public class BitmapJobDrawable extends Drawable implements Runnable {
-
-    private ThumbnailLoader mLoader;
-    private MediaItem mItem;
-    private Bitmap mBitmap;
-    private Paint mPaint = new Paint();
-    private Matrix mDrawMatrix = new Matrix();
-    private int mRotation = 0;
-
-    public BitmapJobDrawable() {
-    }
-
-    public void setMediaItem(MediaItem item) {
-        if (mItem == item) return;
-
-        if (mLoader != null) {
-            mLoader.cancelLoad();
-        }
-        mItem = item;
-        if (mBitmap != null) {
-            GalleryBitmapPool.getInstance().put(mBitmap);
-            mBitmap = null;
-        }
-        if (mItem != null) {
-            // TODO: Figure out why ThumbnailLoader doesn't like to be re-used
-            mLoader = new ThumbnailLoader(this);
-            mLoader.startLoad();
-            mRotation = mItem.getRotation();
-        }
-        invalidateSelf();
-    }
-
-    @Override
-    public void run() {
-        Bitmap bitmap = mLoader.getBitmap();
-        if (bitmap != null) {
-            mBitmap = bitmap;
-            updateDrawMatrix();
-        }
-    }
-
-    @Override
-    protected void onBoundsChange(Rect bounds) {
-        super.onBoundsChange(bounds);
-        updateDrawMatrix();
-    }
-
-    @Override
-    public void draw(Canvas canvas) {
-        Rect bounds = getBounds();
-        if (mBitmap != null) {
-            canvas.save();
-            canvas.clipRect(bounds);
-            canvas.concat(mDrawMatrix);
-            canvas.rotate(mRotation, bounds.centerX(), bounds.centerY());
-            canvas.drawBitmap(mBitmap, 0, 0, mPaint);
-            canvas.restore();
-        } else {
-            mPaint.setColor(0xFFCCCCCC);
-            canvas.drawRect(bounds, mPaint);
-        }
-    }
-
-    private void updateDrawMatrix() {
-        Rect bounds = getBounds();
-        if (mBitmap == null || bounds.isEmpty()) {
-            mDrawMatrix.reset();
-            return;
-        }
-
-        float scale;
-        float dx = 0, dy = 0;
-
-        int dwidth = mBitmap.getWidth();
-        int dheight = mBitmap.getHeight();
-        int vwidth = bounds.width();
-        int vheight = bounds.height();
-
-        // Calculates a matrix similar to ScaleType.CENTER_CROP
-        if (dwidth * vheight > vwidth * dheight) {
-            scale = (float) vheight / (float) dheight;
-            dx = (vwidth - dwidth * scale) * 0.5f;
-        } else {
-            scale = (float) vwidth / (float) dwidth;
-            dy = (vheight - dheight * scale) * 0.5f;
-        }
-
-        mDrawMatrix.setScale(scale, scale);
-        mDrawMatrix.postTranslate((int) (dx + 0.5f), (int) (dy + 0.5f));
-        invalidateSelf();
-    }
-
-    @Override
-    public int getIntrinsicWidth() {
-        return MediaItem.getTargetSize(MediaItem.TYPE_MICROTHUMBNAIL);
-    }
-
-    @Override
-    public int getIntrinsicHeight() {
-        return MediaItem.getTargetSize(MediaItem.TYPE_MICROTHUMBNAIL);
-    }
-
-    @Override
-    public int getOpacity() {
-        Bitmap bm = mBitmap;
-        return (bm == null || bm.hasAlpha() || mPaint.getAlpha() < 255) ?
-                PixelFormat.TRANSLUCENT : PixelFormat.OPAQUE;
-    }
-
-    @Override
-    public void setAlpha(int alpha) {
-        int oldAlpha = mPaint.getAlpha();
-        if (alpha != oldAlpha) {
-            mPaint.setAlpha(alpha);
-            invalidateSelf();
-        }
-    }
-
-    @Override
-    public void setColorFilter(ColorFilter cf) {
-        mPaint.setColorFilter(cf);
-        invalidateSelf();
-    }
-
-    private static class ThumbnailLoader extends BitmapLoader {
-        private static final ThreadPool sThreadPool = new ThreadPool(0, 2);
-        private BitmapJobDrawable mParent;
-
-        public ThumbnailLoader(BitmapJobDrawable parent) {
-            mParent = parent;
-        }
-
-        @Override
-        protected Future<Bitmap> submitBitmapTask(FutureListener<Bitmap> l) {
-            return sThreadPool.submit(
-                    mParent.mItem.requestImage(MediaItem.TYPE_MICROTHUMBNAIL), this);
-        }
-
-        @Override
-        protected void onLoadComplete(Bitmap bitmap) {
-            mParent.scheduleSelf(mParent, 0);
-        }
-    }
-
-}
diff --git a/src/com/android/photos/shims/LoaderCompatShim.java b/src/com/android/photos/shims/LoaderCompatShim.java
deleted file mode 100644
index d5bf710..0000000
--- a/src/com/android/photos/shims/LoaderCompatShim.java
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright (C) 2013 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.photos.shims;
-
-import android.graphics.drawable.Drawable;
-import android.net.Uri;
-
-import java.util.ArrayList;
-
-
-public interface LoaderCompatShim<T> {
-    Drawable drawableForItem(T item, Drawable recycle);
-    Uri uriForItem(T item);
-    ArrayList<Uri> urisForSubItems(T item);
-    void deleteItemWithPath(Object path);
-    Object getPathForItem(T item);
-}
diff --git a/src/com/android/photos/shims/MediaItemsLoader.java b/src/com/android/photos/shims/MediaItemsLoader.java
deleted file mode 100644
index 6142355..0000000
--- a/src/com/android/photos/shims/MediaItemsLoader.java
+++ /dev/null
@@ -1,190 +0,0 @@
-/*
- * Copyright (C) 2013 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.photos.shims;
-
-import android.content.AsyncTaskLoader;
-import android.content.Context;
-import android.database.Cursor;
-import android.database.MatrixCursor;
-import android.graphics.drawable.Drawable;
-import android.net.Uri;
-import android.provider.MediaStore.Files.FileColumns;
-import android.util.SparseArray;
-
-import com.android.gallery3d.data.ContentListener;
-import com.android.gallery3d.data.DataManager;
-import com.android.gallery3d.data.MediaItem;
-import com.android.gallery3d.data.MediaObject;
-import com.android.gallery3d.data.MediaSet;
-import com.android.gallery3d.data.MediaSet.ItemConsumer;
-import com.android.gallery3d.data.MediaSet.SyncListener;
-import com.android.gallery3d.data.Path;
-import com.android.gallery3d.util.Future;
-import com.android.photos.data.PhotoSetLoader;
-
-import java.util.ArrayList;
-
-/**
- * Returns all MediaItems in a MediaSet, wrapping them in a cursor to appear
- * like a PhotoSetLoader
- */
-public class MediaItemsLoader extends AsyncTaskLoader<Cursor> implements LoaderCompatShim<Cursor> {
-
-    private static final SyncListener sNullListener = new SyncListener() {
-        @Override
-        public void onSyncDone(MediaSet mediaSet, int resultCode) {
-        }
-    };
-
-    private final MediaSet mMediaSet;
-    private final DataManager mDataManager;
-    private Future<Integer> mSyncTask = null;
-    private ContentListener mObserver = new ContentListener() {
-        @Override
-        public void onContentDirty() {
-            onContentChanged();
-        }
-    };
-    private SparseArray<MediaItem> mMediaItems;
-
-    public MediaItemsLoader(Context context) {
-        super(context);
-        mDataManager = DataManager.from(context);
-        String path = mDataManager.getTopSetPath(DataManager.INCLUDE_ALL);
-        mMediaSet = mDataManager.getMediaSet(path);
-    }
-
-    public MediaItemsLoader(Context context, String parentPath) {
-        super(context);
-        mDataManager = DataManager.from(getContext());
-        mMediaSet = mDataManager.getMediaSet(parentPath);
-    }
-
-    @Override
-    protected void onStartLoading() {
-        super.onStartLoading();
-        mMediaSet.addContentListener(mObserver);
-        mSyncTask = mMediaSet.requestSync(sNullListener);
-        forceLoad();
-    }
-
-    @Override
-    protected boolean onCancelLoad() {
-        if (mSyncTask != null) {
-            mSyncTask.cancel();
-            mSyncTask = null;
-        }
-        return super.onCancelLoad();
-    }
-
-    @Override
-    protected void onStopLoading() {
-        super.onStopLoading();
-        cancelLoad();
-        mMediaSet.removeContentListener(mObserver);
-    }
-
-    @Override
-    protected void onReset() {
-        super.onReset();
-        onStopLoading();
-    }
-
-    @Override
-    public Cursor loadInBackground() {
-        // TODO: This probably doesn't work
-        mMediaSet.reload();
-        final MatrixCursor cursor = new MatrixCursor(PhotoSetLoader.PROJECTION);
-        final Object[] row = new Object[PhotoSetLoader.PROJECTION.length];
-        final SparseArray<MediaItem> mediaItems = new SparseArray<MediaItem>();
-        mMediaSet.enumerateTotalMediaItems(new ItemConsumer() {
-            @Override
-            public void consume(int index, MediaItem item) {
-                row[PhotoSetLoader.INDEX_ID] = index;
-                row[PhotoSetLoader.INDEX_DATA] = item.getContentUri().toString();
-                row[PhotoSetLoader.INDEX_DATE_ADDED] = item.getDateInMs();
-                row[PhotoSetLoader.INDEX_HEIGHT] = item.getHeight();
-                row[PhotoSetLoader.INDEX_WIDTH] = item.getWidth();
-                row[PhotoSetLoader.INDEX_WIDTH] = item.getWidth();
-                int rawMediaType = item.getMediaType();
-                int mappedMediaType = FileColumns.MEDIA_TYPE_NONE;
-                if (rawMediaType == MediaItem.MEDIA_TYPE_IMAGE) {
-                    mappedMediaType = FileColumns.MEDIA_TYPE_IMAGE;
-                } else if (rawMediaType == MediaItem.MEDIA_TYPE_VIDEO) {
-                    mappedMediaType = FileColumns.MEDIA_TYPE_VIDEO;
-                }
-                row[PhotoSetLoader.INDEX_MEDIA_TYPE] = mappedMediaType;
-                row[PhotoSetLoader.INDEX_SUPPORTED_OPERATIONS] =
-                        item.getSupportedOperations();
-                cursor.addRow(row);
-                mediaItems.append(index, item);
-            }
-        });
-        synchronized (mMediaSet) {
-            mMediaItems = mediaItems;
-        }
-        return cursor;
-    }
-
-    @Override
-    public Drawable drawableForItem(Cursor item, Drawable recycle) {
-        BitmapJobDrawable drawable = null;
-        if (recycle == null || !(recycle instanceof BitmapJobDrawable)) {
-            drawable = new BitmapJobDrawable();
-        } else {
-            drawable = (BitmapJobDrawable) recycle;
-        }
-        int index = item.getInt(PhotoSetLoader.INDEX_ID);
-        drawable.setMediaItem(mMediaItems.get(index));
-        return drawable;
-    }
-
-    public static int getThumbnailSize() {
-        return MediaItem.getTargetSize(MediaItem.TYPE_MICROTHUMBNAIL);
-    }
-
-    @Override
-    public Uri uriForItem(Cursor item) {
-        int index = item.getInt(PhotoSetLoader.INDEX_ID);
-        MediaItem mi = mMediaItems.get(index);
-        return mi == null ? null : mi.getContentUri();
-    }
-
-    @Override
-    public ArrayList<Uri> urisForSubItems(Cursor item) {
-        return null;
-    }
-
-    @Override
-    public void deleteItemWithPath(Object path) {
-        MediaObject o = mDataManager.getMediaObject((Path) path);
-        if (o != null) {
-            o.delete();
-        }
-    }
-
-    @Override
-    public Object getPathForItem(Cursor item) {
-        int index = item.getInt(PhotoSetLoader.INDEX_ID);
-        MediaItem mi = mMediaItems.get(index);
-        if (mi != null) {
-            return mi.getPath();
-        }
-        return null;
-    }
-
-}
diff --git a/src/com/android/photos/shims/MediaSetLoader.java b/src/com/android/photos/shims/MediaSetLoader.java
deleted file mode 100644
index 9093bc1..0000000
--- a/src/com/android/photos/shims/MediaSetLoader.java
+++ /dev/null
@@ -1,191 +0,0 @@
-/*
- * Copyright (C) 2013 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.photos.shims;
-
-import android.content.AsyncTaskLoader;
-import android.content.Context;
-import android.database.Cursor;
-import android.database.MatrixCursor;
-import android.graphics.drawable.Drawable;
-import android.net.Uri;
-
-import com.android.gallery3d.data.ContentListener;
-import com.android.gallery3d.data.DataManager;
-import com.android.gallery3d.data.MediaItem;
-import com.android.gallery3d.data.MediaObject;
-import com.android.gallery3d.data.MediaSet;
-import com.android.gallery3d.data.Path;
-import com.android.gallery3d.data.MediaSet.SyncListener;
-import com.android.gallery3d.util.Future;
-import com.android.photos.data.AlbumSetLoader;
-
-import java.util.ArrayList;
-
-/**
- * Returns all MediaSets in a MediaSet, wrapping them in a cursor to appear
- * like a AlbumSetLoader.
- */
-public class MediaSetLoader extends AsyncTaskLoader<Cursor> implements LoaderCompatShim<Cursor>{
-
-    private static final SyncListener sNullListener = new SyncListener() {
-        @Override
-        public void onSyncDone(MediaSet mediaSet, int resultCode) {
-        }
-    };
-
-    private final MediaSet mMediaSet;
-    private final DataManager mDataManager;
-    private Future<Integer> mSyncTask = null;
-    private ContentListener mObserver = new ContentListener() {
-        @Override
-        public void onContentDirty() {
-            onContentChanged();
-        }
-    };
-
-    private ArrayList<MediaItem> mCoverItems;
-
-    public MediaSetLoader(Context context) {
-        super(context);
-        mDataManager = DataManager.from(context);
-        String path = mDataManager.getTopSetPath(DataManager.INCLUDE_ALL);
-        mMediaSet = mDataManager.getMediaSet(path);
-    }
-
-    public MediaSetLoader(Context context, String path) {
-        super(context);
-        mDataManager = DataManager.from(getContext());
-        mMediaSet = mDataManager.getMediaSet(path);
-    }
-
-    @Override
-    protected void onStartLoading() {
-        super.onStartLoading();
-        mMediaSet.addContentListener(mObserver);
-        mSyncTask = mMediaSet.requestSync(sNullListener);
-        forceLoad();
-    }
-
-    @Override
-    protected boolean onCancelLoad() {
-        if (mSyncTask != null) {
-            mSyncTask.cancel();
-            mSyncTask = null;
-        }
-        return super.onCancelLoad();
-    }
-
-    @Override
-    protected void onStopLoading() {
-        super.onStopLoading();
-        cancelLoad();
-        mMediaSet.removeContentListener(mObserver);
-    }
-
-    @Override
-    protected void onReset() {
-        super.onReset();
-        onStopLoading();
-    }
-
-    @Override
-    public Cursor loadInBackground() {
-        // TODO: This probably doesn't work
-        mMediaSet.reload();
-        final MatrixCursor cursor = new MatrixCursor(AlbumSetLoader.PROJECTION);
-        final Object[] row = new Object[AlbumSetLoader.PROJECTION.length];
-        int count = mMediaSet.getSubMediaSetCount();
-        ArrayList<MediaItem> coverItems = new ArrayList<MediaItem>(count);
-        for (int i = 0; i < count; i++) {
-            MediaSet m = mMediaSet.getSubMediaSet(i);
-            m.reload();
-            row[AlbumSetLoader.INDEX_ID] = i;
-            row[AlbumSetLoader.INDEX_TITLE] = m.getName();
-            row[AlbumSetLoader.INDEX_COUNT] = m.getMediaItemCount();
-            row[AlbumSetLoader.INDEX_SUPPORTED_OPERATIONS] = m.getSupportedOperations();
-            MediaItem coverItem = m.getCoverMediaItem();
-            if (coverItem != null) {
-                row[AlbumSetLoader.INDEX_TIMESTAMP] = coverItem.getDateInMs();
-            }
-            coverItems.add(coverItem);
-            cursor.addRow(row);
-        }
-        synchronized (mMediaSet) {
-            mCoverItems = coverItems;
-        }
-        return cursor;
-    }
-
-    @Override
-    public Drawable drawableForItem(Cursor item, Drawable recycle) {
-        BitmapJobDrawable drawable = null;
-        if (recycle == null || !(recycle instanceof BitmapJobDrawable)) {
-            drawable = new BitmapJobDrawable();
-        } else {
-            drawable = (BitmapJobDrawable) recycle;
-        }
-        int index = item.getInt(AlbumSetLoader.INDEX_ID);
-        drawable.setMediaItem(mCoverItems.get(index));
-        return drawable;
-    }
-
-    public static int getThumbnailSize() {
-        return MediaItem.getTargetSize(MediaItem.TYPE_MICROTHUMBNAIL);
-    }
-
-    @Override
-    public Uri uriForItem(Cursor item) {
-        int index = item.getInt(AlbumSetLoader.INDEX_ID);
-        MediaSet ms = mMediaSet.getSubMediaSet(index);
-        return ms == null ? null : ms.getContentUri();
-    }
-
-    @Override
-    public ArrayList<Uri> urisForSubItems(Cursor item) {
-        int index = item.getInt(AlbumSetLoader.INDEX_ID);
-        MediaSet ms = mMediaSet.getSubMediaSet(index);
-        if (ms == null) return null;
-        final ArrayList<Uri> result = new ArrayList<Uri>();
-        ms.enumerateMediaItems(new MediaSet.ItemConsumer() {
-            @Override
-            public void consume(int index, MediaItem item) {
-                if (item != null) {
-                    result.add(item.getContentUri());
-                }
-            }
-        });
-        return result;
-    }
-
-    @Override
-    public void deleteItemWithPath(Object path) {
-        MediaObject o = mDataManager.getMediaObject((Path) path);
-        if (o != null) {
-            o.delete();
-        }
-    }
-
-    @Override
-    public Object getPathForItem(Cursor item) {
-        int index = item.getInt(AlbumSetLoader.INDEX_ID);
-        MediaSet ms = mMediaSet.getSubMediaSet(index);
-        if (ms != null) {
-            return ms.getPath();
-        }
-        return null;
-    }
-}
diff --git a/src/com/android/photos/views/BlockingGLTextureView.java b/src/com/android/photos/views/BlockingGLTextureView.java
deleted file mode 100644
index 8a05051..0000000
--- a/src/com/android/photos/views/BlockingGLTextureView.java
+++ /dev/null
@@ -1,438 +0,0 @@
-/*
- * Copyright (C) 2013 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.photos.views;
-
-import android.content.Context;
-import android.graphics.SurfaceTexture;
-import android.opengl.GLSurfaceView.Renderer;
-import android.opengl.GLUtils;
-import android.util.Log;
-import android.view.TextureView;
-import android.view.TextureView.SurfaceTextureListener;
-
-import javax.microedition.khronos.egl.EGL10;
-import javax.microedition.khronos.egl.EGLConfig;
-import javax.microedition.khronos.egl.EGLContext;
-import javax.microedition.khronos.egl.EGLDisplay;
-import javax.microedition.khronos.egl.EGLSurface;
-import javax.microedition.khronos.opengles.GL10;
-
-/**
- * A TextureView that supports blocking rendering for synchronous drawing
- */
-public class BlockingGLTextureView extends TextureView
-        implements SurfaceTextureListener {
-
-    private RenderThread mRenderThread;
-
-    public BlockingGLTextureView(Context context) {
-        super(context);
-        setSurfaceTextureListener(this);
-    }
-
-    public void setRenderer(Renderer renderer) {
-        if (mRenderThread != null) {
-            throw new IllegalArgumentException("Renderer already set");
-        }
-        mRenderThread = new RenderThread(renderer);
-    }
-
-    public void render() {
-        mRenderThread.render();
-    }
-
-    public void destroy() {
-        if (mRenderThread != null) {
-            mRenderThread.finish();
-            mRenderThread = null;
-        }
-    }
-
-    @Override
-    public void onSurfaceTextureAvailable(SurfaceTexture surface, int width,
-            int height) {
-        mRenderThread.setSurface(surface);
-        mRenderThread.setSize(width, height);
-    }
-
-    @Override
-    public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width,
-            int height) {
-        mRenderThread.setSize(width, height);
-    }
-
-    @Override
-    public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
-        if (mRenderThread != null) {
-            mRenderThread.setSurface(null);
-        }
-        return false;
-    }
-
-    @Override
-    public void onSurfaceTextureUpdated(SurfaceTexture surface) {
-    }
-
-    @Override
-    protected void finalize() throws Throwable {
-        try {
-            destroy();
-        } catch (Throwable t) {
-            // Ignore
-        }
-        super.finalize();
-    }
-
-    /**
-     * An EGL helper class.
-     */
-
-    private static class EglHelper {
-        private static final int EGL_CONTEXT_CLIENT_VERSION = 0x3098;
-        private static final int EGL_OPENGL_ES2_BIT = 4;
-
-        EGL10 mEgl;
-        EGLDisplay mEglDisplay;
-        EGLSurface mEglSurface;
-        EGLConfig mEglConfig;
-        EGLContext mEglContext;
-
-        private EGLConfig chooseEglConfig() {
-            int[] configsCount = new int[1];
-            EGLConfig[] configs = new EGLConfig[1];
-            int[] configSpec = getConfig();
-            if (!mEgl.eglChooseConfig(mEglDisplay, configSpec, configs, 1, configsCount)) {
-                throw new IllegalArgumentException("eglChooseConfig failed " +
-                        GLUtils.getEGLErrorString(mEgl.eglGetError()));
-            } else if (configsCount[0] > 0) {
-                return configs[0];
-            }
-            return null;
-        }
-
-        private static int[] getConfig() {
-            return new int[] {
-                    EGL10.EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
-                    EGL10.EGL_RED_SIZE, 8,
-                    EGL10.EGL_GREEN_SIZE, 8,
-                    EGL10.EGL_BLUE_SIZE, 8,
-                    EGL10.EGL_ALPHA_SIZE, 8,
-                    EGL10.EGL_DEPTH_SIZE, 0,
-                    EGL10.EGL_STENCIL_SIZE, 0,
-                    EGL10.EGL_NONE
-            };
-        }
-
-        EGLContext createContext(EGL10 egl, EGLDisplay eglDisplay, EGLConfig eglConfig) {
-            int[] attribList = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL10.EGL_NONE };
-            return egl.eglCreateContext(eglDisplay, eglConfig, EGL10.EGL_NO_CONTEXT, attribList);
-        }
-
-        /**
-         * Initialize EGL for a given configuration spec.
-         */
-        public void start() {
-            /*
-             * Get an EGL instance
-             */
-            mEgl = (EGL10) EGLContext.getEGL();
-
-            /*
-             * Get to the default display.
-             */
-            mEglDisplay = mEgl.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY);
-
-            if (mEglDisplay == EGL10.EGL_NO_DISPLAY) {
-                throw new RuntimeException("eglGetDisplay failed");
-            }
-
-            /*
-             * We can now initialize EGL for that display
-             */
-            int[] version = new int[2];
-            if (!mEgl.eglInitialize(mEglDisplay, version)) {
-                throw new RuntimeException("eglInitialize failed");
-            }
-            mEglConfig = chooseEglConfig();
-
-            /*
-            * Create an EGL context. We want to do this as rarely as we can, because an
-            * EGL context is a somewhat heavy object.
-            */
-            mEglContext = createContext(mEgl, mEglDisplay, mEglConfig);
-
-            if (mEglContext == null || mEglContext == EGL10.EGL_NO_CONTEXT) {
-                mEglContext = null;
-                throwEglException("createContext");
-            }
-
-            mEglSurface = null;
-        }
-
-        /**
-         * Create an egl surface for the current SurfaceTexture surface. If a surface
-         * already exists, destroy it before creating the new surface.
-         *
-         * @return true if the surface was created successfully.
-         */
-        public boolean createSurface(SurfaceTexture surface) {
-            /*
-             * Check preconditions.
-             */
-            if (mEgl == null) {
-                throw new RuntimeException("egl not initialized");
-            }
-            if (mEglDisplay == null) {
-                throw new RuntimeException("eglDisplay not initialized");
-            }
-            if (mEglConfig == null) {
-                throw new RuntimeException("mEglConfig not initialized");
-            }
-
-            /*
-             *  The window size has changed, so we need to create a new
-             *  surface.
-             */
-            destroySurfaceImp();
-
-            /*
-             * Create an EGL surface we can render into.
-             */
-            if (surface != null) {
-                mEglSurface = mEgl.eglCreateWindowSurface(mEglDisplay, mEglConfig, surface, null);
-            } else {
-                mEglSurface = null;
-            }
-
-            if (mEglSurface == null || mEglSurface == EGL10.EGL_NO_SURFACE) {
-                int error = mEgl.eglGetError();
-                if (error == EGL10.EGL_BAD_NATIVE_WINDOW) {
-                    Log.e("EglHelper", "createWindowSurface returned EGL_BAD_NATIVE_WINDOW.");
-                }
-                return false;
-            }
-
-            /*
-             * Before we can issue GL commands, we need to make sure
-             * the context is current and bound to a surface.
-             */
-            if (!mEgl.eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface, mEglContext)) {
-                /*
-                 * Could not make the context current, probably because the underlying
-                 * SurfaceView surface has been destroyed.
-                 */
-                logEglErrorAsWarning("EGLHelper", "eglMakeCurrent", mEgl.eglGetError());
-                return false;
-            }
-
-            return true;
-        }
-
-        /**
-         * Create a GL object for the current EGL context.
-         */
-        public GL10 createGL() {
-            return (GL10) mEglContext.getGL();
-        }
-
-        /**
-         * Display the current render surface.
-         * @return the EGL error code from eglSwapBuffers.
-         */
-        public int swap() {
-            if (!mEgl.eglSwapBuffers(mEglDisplay, mEglSurface)) {
-                return mEgl.eglGetError();
-            }
-            return EGL10.EGL_SUCCESS;
-        }
-
-        public void destroySurface() {
-            destroySurfaceImp();
-        }
-
-        private void destroySurfaceImp() {
-            if (mEglSurface != null && mEglSurface != EGL10.EGL_NO_SURFACE) {
-                mEgl.eglMakeCurrent(mEglDisplay, EGL10.EGL_NO_SURFACE,
-                        EGL10.EGL_NO_SURFACE,
-                        EGL10.EGL_NO_CONTEXT);
-                mEgl.eglDestroySurface(mEglDisplay, mEglSurface);
-                mEglSurface = null;
-            }
-        }
-
-        public void finish() {
-            if (mEglContext != null) {
-                mEgl.eglDestroyContext(mEglDisplay, mEglContext);
-                mEglContext = null;
-            }
-            if (mEglDisplay != null) {
-                mEgl.eglTerminate(mEglDisplay);
-                mEglDisplay = null;
-            }
-        }
-
-        private void throwEglException(String function) {
-            throwEglException(function, mEgl.eglGetError());
-        }
-
-        public static void throwEglException(String function, int error) {
-            String message = formatEglError(function, error);
-            throw new RuntimeException(message);
-        }
-
-        public static void logEglErrorAsWarning(String tag, String function, int error) {
-            Log.w(tag, formatEglError(function, error));
-        }
-
-        public static String formatEglError(String function, int error) {
-            return function + " failed: " + error;
-        }
-
-    }
-
-    private static class RenderThread extends Thread {
-        private static final int INVALID = -1;
-        private static final int RENDER = 1;
-        private static final int CHANGE_SURFACE = 2;
-        private static final int RESIZE_SURFACE = 3;
-        private static final int FINISH = 4;
-
-        private EglHelper mEglHelper = new EglHelper();
-
-        private Object mLock = new Object();
-        private int mExecMsgId = INVALID;
-        private SurfaceTexture mSurface;
-        private Renderer mRenderer;
-        private int mWidth, mHeight;
-
-        private boolean mFinished = false;
-        private GL10 mGL;
-
-        public RenderThread(Renderer renderer) {
-            super("RenderThread");
-            mRenderer = renderer;
-            start();
-        }
-
-        private void checkRenderer() {
-            if (mRenderer == null) {
-                throw new IllegalArgumentException("Renderer is null!");
-            }
-        }
-
-        private void checkSurface() {
-            if (mSurface == null) {
-                throw new IllegalArgumentException("surface is null!");
-            }
-        }
-
-        public void setSurface(SurfaceTexture surface) {
-            // If the surface is null we're being torn down, don't need a
-            // renderer then
-            if (surface != null) {
-                checkRenderer();
-            }
-            mSurface = surface;
-            exec(CHANGE_SURFACE);
-        }
-
-        public void setSize(int width, int height) {
-            checkRenderer();
-            checkSurface();
-            mWidth = width;
-            mHeight = height;
-            exec(RESIZE_SURFACE);
-        }
-
-        public void render() {
-            checkRenderer();
-            if (mSurface != null) {
-                exec(RENDER);
-                mSurface.updateTexImage();
-            }
-        }
-
-        public void finish() {
-            mSurface = null;
-            exec(FINISH);
-            try {
-                join();
-            } catch (InterruptedException e) {
-                // Ignore
-            }
-        }
-
-        private void exec(int msgid) {
-            synchronized (mLock) {
-                if (mExecMsgId != INVALID) {
-                    throw new IllegalArgumentException(
-                            "Message already set - multithreaded access?");
-                }
-                mExecMsgId = msgid;
-                mLock.notify();
-                try {
-                    mLock.wait();
-                } catch (InterruptedException e) {
-                    // Ignore
-                }
-            }
-        }
-
-        private void handleMessageLocked(int what) {
-            switch (what) {
-            case CHANGE_SURFACE:
-                if (mEglHelper.createSurface(mSurface)) {
-                    mGL = mEglHelper.createGL();
-                    mRenderer.onSurfaceCreated(mGL, mEglHelper.mEglConfig);
-                }
-                break;
-            case RESIZE_SURFACE:
-                mRenderer.onSurfaceChanged(mGL, mWidth, mHeight);
-                break;
-            case RENDER:
-                mRenderer.onDrawFrame(mGL);
-                mEglHelper.swap();
-                break;
-            case FINISH:
-                mEglHelper.destroySurface();
-                mEglHelper.finish();
-                mFinished = true;
-                break;
-            }
-        }
-
-        @Override
-        public void run() {
-            synchronized (mLock) {
-                mEglHelper.start();
-                while (!mFinished) {
-                    while (mExecMsgId == INVALID) {
-                        try {
-                            mLock.wait();
-                        } catch (InterruptedException e) {
-                            // Ignore
-                        }
-                    }
-                    handleMessageLocked(mExecMsgId);
-                    mExecMsgId = INVALID;
-                    mLock.notify();
-                }
-                mExecMsgId = FINISH;
-            }
-        }
-    }
-}
diff --git a/src/com/android/photos/views/GalleryThumbnailView.java b/src/com/android/photos/views/GalleryThumbnailView.java
deleted file mode 100644
index e5dd6f2..0000000
--- a/src/com/android/photos/views/GalleryThumbnailView.java
+++ /dev/null
@@ -1,883 +0,0 @@
-/*
- * Copyright (C) 2013 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.photos.views;
-
-import android.content.Context;
-import android.content.res.TypedArray;
-import android.database.DataSetObserver;
-import android.graphics.Canvas;
-import android.support.v4.view.MotionEventCompat;
-import android.support.v4.view.VelocityTrackerCompat;
-import android.support.v4.view.ViewCompat;
-import android.support.v4.widget.EdgeEffectCompat;
-import android.util.AttributeSet;
-import android.util.Log;
-import android.util.SparseArray;
-import android.view.MotionEvent;
-import android.view.VelocityTracker;
-import android.view.View;
-import android.view.ViewConfiguration;
-import android.view.ViewGroup;
-import android.widget.ListAdapter;
-import android.widget.OverScroller;
-
-import java.util.ArrayList;
-
-public class GalleryThumbnailView extends ViewGroup {
-
-    public interface GalleryThumbnailAdapter extends ListAdapter {
-        /**
-         * @param position Position to get the intrinsic aspect ratio for
-         * @return width / height
-         */
-        float getIntrinsicAspectRatio(int position);
-    }
-
-    private static final String TAG = "GalleryThumbnailView";
-    private static final float ASPECT_RATIO = (float) Math.sqrt(1.5f);
-    private static final int LAND_UNITS = 2;
-    private static final int PORT_UNITS = 3;
-
-    private GalleryThumbnailAdapter mAdapter;
-
-    private final RecycleBin mRecycler = new RecycleBin();
-
-    private final AdapterDataSetObserver mObserver = new AdapterDataSetObserver();
-
-    private boolean mDataChanged;
-    private int mOldItemCount;
-    private int mItemCount;
-    private boolean mHasStableIds;
-
-    private int mFirstPosition;
-
-    private boolean mPopulating;
-    private boolean mInLayout;
-
-    private int mTouchSlop;
-    private int mMaximumVelocity;
-    private int mFlingVelocity;
-    private float mLastTouchX;
-    private float mTouchRemainderX;
-    private int mActivePointerId;
-
-    private static final int TOUCH_MODE_IDLE = 0;
-    private static final int TOUCH_MODE_DRAGGING = 1;
-    private static final int TOUCH_MODE_FLINGING = 2;
-
-    private int mTouchMode;
-    private final VelocityTracker mVelocityTracker = VelocityTracker.obtain();
-    private final OverScroller mScroller;
-
-    private final EdgeEffectCompat mLeftEdge;
-    private final EdgeEffectCompat mRightEdge;
-
-    private int mLargeColumnWidth;
-    private int mSmallColumnWidth;
-    private int mLargeColumnUnitCount = 8;
-    private int mSmallColumnUnitCount = 10;
-
-    public GalleryThumbnailView(Context context) {
-        this(context, null);
-    }
-
-    public GalleryThumbnailView(Context context, AttributeSet attrs) {
-        this(context, attrs, 0);
-    }
-
-    public GalleryThumbnailView(Context context, AttributeSet attrs, int defStyle) {
-        super(context, attrs, defStyle);
-
-        final ViewConfiguration vc = ViewConfiguration.get(context);
-        mTouchSlop = vc.getScaledTouchSlop();
-        mMaximumVelocity = vc.getScaledMaximumFlingVelocity();
-        mFlingVelocity = vc.getScaledMinimumFlingVelocity();
-        mScroller = new OverScroller(context);
-
-        mLeftEdge = new EdgeEffectCompat(context);
-        mRightEdge = new EdgeEffectCompat(context);
-        setWillNotDraw(false);
-        setClipToPadding(false);
-    }
-
-    @Override
-    public void requestLayout() {
-        if (!mPopulating) {
-            super.requestLayout();
-        }
-    }
-
-    @Override
-    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
-        int widthMode = MeasureSpec.getMode(widthMeasureSpec);
-        int heightMode = MeasureSpec.getMode(heightMeasureSpec);
-        int widthSize = MeasureSpec.getSize(widthMeasureSpec);
-        int heightSize = MeasureSpec.getSize(heightMeasureSpec);
-
-        if (widthMode != MeasureSpec.EXACTLY) {
-            Log.e(TAG, "onMeasure: must have an exact width or match_parent! " +
-                    "Using fallback spec of EXACTLY " + widthSize);
-        }
-        if (heightMode != MeasureSpec.EXACTLY) {
-            Log.e(TAG, "onMeasure: must have an exact height or match_parent! " +
-                    "Using fallback spec of EXACTLY " + heightSize);
-        }
-
-        setMeasuredDimension(widthSize, heightSize);
-
-        float portSpaces = mLargeColumnUnitCount / PORT_UNITS;
-        float height = getMeasuredHeight() / portSpaces;
-        mLargeColumnWidth = (int) (height / ASPECT_RATIO);
-        portSpaces++;
-        height = getMeasuredHeight() / portSpaces;
-        mSmallColumnWidth = (int) (height / ASPECT_RATIO);
-    }
-
-    @Override
-    protected void onLayout(boolean changed, int l, int t, int r, int b) {
-        mInLayout = true;
-        populate();
-        mInLayout = false;
-
-        final int width = r - l;
-        final int height = b - t;
-        mLeftEdge.setSize(width, height);
-        mRightEdge.setSize(width, height);
-    }
-
-    private void populate() {
-        if (getWidth() == 0 || getHeight() == 0) {
-            return;
-        }
-
-        // TODO: Handle size changing
-//        final int colCount = mColCount;
-//        if (mItemTops == null || mItemTops.length != colCount) {
-//            mItemTops = new int[colCount];
-//            mItemBottoms = new int[colCount];
-//            final int top = getPaddingTop();
-//            final int offset = top + Math.min(mRestoreOffset, 0);
-//            Arrays.fill(mItemTops, offset);
-//            Arrays.fill(mItemBottoms, offset);
-//            mLayoutRecords.clear();
-//            if (mInLayout) {
-//                removeAllViewsInLayout();
-//            } else {
-//                removeAllViews();
-//            }
-//            mRestoreOffset = 0;
-//        }
-
-        mPopulating = true;
-        layoutChildren(mDataChanged);
-        fillRight(mFirstPosition + getChildCount(), 0);
-        fillLeft(mFirstPosition - 1, 0);
-        mPopulating = false;
-        mDataChanged = false;
-    }
-
-    final void layoutChildren(boolean queryAdapter) {
-// TODO
-//        final int childCount = getChildCount();
-//        for (int i = 0; i < childCount; i++) {
-//            View child = getChildAt(i);
-//
-//            if (child.isLayoutRequested()) {
-//                final int widthSpec = MeasureSpec.makeMeasureSpec(child.getMeasuredWidth(), MeasureSpec.EXACTLY);
-//                final int heightSpec = MeasureSpec.makeMeasureSpec(child.getMeasuredHeight(), MeasureSpec.EXACTLY);
-//                child.measure(widthSpec, heightSpec);
-//                child.layout(child.getLeft(), child.getTop(), child.getRight(), child.getBottom());
-//            }
-//
-//            int childTop = mItemBottoms[col] > Integer.MIN_VALUE ?
-//                    mItemBottoms[col] + mItemMargin : child.getTop();
-//            if (span > 1) {
-//                int lowest = childTop;
-//                for (int j = col + 1; j < col + span; j++) {
-//                    final int bottom = mItemBottoms[j] + mItemMargin;
-//                    if (bottom > lowest) {
-//                        lowest = bottom;
-//                    }
-//                }
-//                childTop = lowest;
-//            }
-//            final int childHeight = child.getMeasuredHeight();
-//            final int childBottom = childTop + childHeight;
-//            final int childLeft = paddingLeft + col * (colWidth + itemMargin);
-//            final int childRight = childLeft + child.getMeasuredWidth();
-//            child.layout(childLeft, childTop, childRight, childBottom);
-//        }
-    }
-
-    /**
-     * Obtain the view and add it to our list of children. The view can be made
-     * fresh, converted from an unused view, or used as is if it was in the
-     * recycle bin.
-     *
-     * @param startPosition Logical position in the list to start from
-     * @param x Left or right edge of the view to add
-     * @param forward If true, align left edge to x and increase position.
-     *                If false, align right edge to x and decrease position.
-     * @return Number of views added
-     */
-    private int makeAndAddColumn(int startPosition, int x, boolean forward) {
-        int columnWidth = mLargeColumnWidth;
-        int addViews = 0;
-        for (int remaining = mLargeColumnUnitCount, i = 0;
-                remaining > 0 && startPosition + i >= 0 && startPosition + i < mItemCount;
-                i += forward ? 1 : -1, addViews++) {
-            if (mAdapter.getIntrinsicAspectRatio(startPosition + i) >= 1f) {
-                // landscape
-                remaining -= LAND_UNITS;
-            } else {
-                // portrait
-                remaining -= PORT_UNITS;
-                if (remaining < 0) {
-                    remaining += (mSmallColumnUnitCount - mLargeColumnUnitCount);
-                    columnWidth = mSmallColumnWidth;
-                }
-            }
-        }
-        int nextTop = 0;
-        for (int i = 0; i < addViews; i++) {
-            int position = startPosition + (forward ? i : -i);
-            View child = obtainView(position, null);
-            if (child.getParent() != this) {
-                if (mInLayout) {
-                    addViewInLayout(child, forward ? -1 : 0, child.getLayoutParams());
-                } else {
-                    addView(child, forward ? -1 : 0);
-                }
-            }
-            int heightSize = (int) (.5f + (mAdapter.getIntrinsicAspectRatio(position) >= 1f
-                    ? columnWidth / ASPECT_RATIO
-                    : columnWidth * ASPECT_RATIO));
-            int heightSpec = MeasureSpec.makeMeasureSpec(heightSize, MeasureSpec.EXACTLY);
-            int widthSpec = MeasureSpec.makeMeasureSpec(columnWidth, MeasureSpec.EXACTLY);
-            child.measure(widthSpec, heightSpec);
-            int childLeft = forward ? x : x - columnWidth;
-            child.layout(childLeft, nextTop, childLeft + columnWidth, nextTop + heightSize);
-            nextTop += heightSize;
-        }
-        return addViews;
-    }
-
-    @Override
-    public boolean onInterceptTouchEvent(MotionEvent ev) {
-        mVelocityTracker.addMovement(ev);
-        final int action = ev.getAction() & MotionEventCompat.ACTION_MASK;
-        switch (action) {
-            case MotionEvent.ACTION_DOWN:
-                mVelocityTracker.clear();
-                mScroller.abortAnimation();
-                mLastTouchX = ev.getX();
-                mActivePointerId = MotionEventCompat.getPointerId(ev, 0);
-                mTouchRemainderX = 0;
-                if (mTouchMode == TOUCH_MODE_FLINGING) {
-                    // Catch!
-                    mTouchMode = TOUCH_MODE_DRAGGING;
-                    return true;
-                }
-                break;
-
-            case MotionEvent.ACTION_MOVE: {
-                final int index = MotionEventCompat.findPointerIndex(ev, mActivePointerId);
-                if (index < 0) {
-                    Log.e(TAG, "onInterceptTouchEvent could not find pointer with id " +
-                            mActivePointerId + " - did StaggeredGridView receive an inconsistent " +
-                            "event stream?");
-                    return false;
-                }
-                final float x = MotionEventCompat.getX(ev, index);
-                final float dx = x - mLastTouchX + mTouchRemainderX;
-                final int deltaY = (int) dx;
-                mTouchRemainderX = dx - deltaY;
-
-                if (Math.abs(dx) > mTouchSlop) {
-                    mTouchMode = TOUCH_MODE_DRAGGING;
-                    return true;
-                }
-            }
-        }
-
-        return false;
-    }
-
-    @Override
-    public boolean onTouchEvent(MotionEvent ev) {
-        mVelocityTracker.addMovement(ev);
-        final int action = ev.getAction() & MotionEventCompat.ACTION_MASK;
-        switch (action) {
-            case MotionEvent.ACTION_DOWN:
-                mVelocityTracker.clear();
-                mScroller.abortAnimation();
-                mLastTouchX = ev.getX();
-                mActivePointerId = MotionEventCompat.getPointerId(ev, 0);
-                mTouchRemainderX = 0;
-                break;
-
-            case MotionEvent.ACTION_MOVE: {
-                final int index = MotionEventCompat.findPointerIndex(ev, mActivePointerId);
-                if (index < 0) {
-                    Log.e(TAG, "onInterceptTouchEvent could not find pointer with id " +
-                            mActivePointerId + " - did StaggeredGridView receive an inconsistent " +
-                            "event stream?");
-                    return false;
-                }
-                final float x = MotionEventCompat.getX(ev, index);
-                final float dx = x - mLastTouchX + mTouchRemainderX;
-                final int deltaX = (int) dx;
-                mTouchRemainderX = dx - deltaX;
-
-                if (Math.abs(dx) > mTouchSlop) {
-                    mTouchMode = TOUCH_MODE_DRAGGING;
-                }
-
-                if (mTouchMode == TOUCH_MODE_DRAGGING) {
-                    mLastTouchX = x;
-
-                    if (!trackMotionScroll(deltaX, true)) {
-                        // Break fling velocity if we impacted an edge.
-                        mVelocityTracker.clear();
-                    }
-                }
-            } break;
-
-            case MotionEvent.ACTION_CANCEL:
-                mTouchMode = TOUCH_MODE_IDLE;
-                break;
-
-            case MotionEvent.ACTION_UP: {
-                mVelocityTracker.computeCurrentVelocity(1000, mMaximumVelocity);
-                final float velocity = VelocityTrackerCompat.getXVelocity(mVelocityTracker,
-                        mActivePointerId);
-                if (Math.abs(velocity) > mFlingVelocity) { // TODO
-                    mTouchMode = TOUCH_MODE_FLINGING;
-                    mScroller.fling(0, 0, (int) velocity, 0,
-                            Integer.MIN_VALUE, Integer.MAX_VALUE, 0, 0);
-                    mLastTouchX = 0;
-                    ViewCompat.postInvalidateOnAnimation(this);
-                } else {
-                    mTouchMode = TOUCH_MODE_IDLE;
-                }
-
-            } break;
-        }
-        return true;
-    }
-
-    /**
-     *
-     * @param deltaX Pixels that content should move by
-     * @return true if the movement completed, false if it was stopped prematurely.
-     */
-    private boolean trackMotionScroll(int deltaX, boolean allowOverScroll) {
-        final boolean contentFits = contentFits();
-        final int allowOverhang = Math.abs(deltaX);
-
-        final int overScrolledBy;
-        final int movedBy;
-        if (!contentFits) {
-            final int overhang;
-            final boolean up;
-            mPopulating = true;
-            if (deltaX > 0) {
-                overhang = fillLeft(mFirstPosition - 1, allowOverhang);
-                up = true;
-            } else {
-                overhang = fillRight(mFirstPosition + getChildCount(), allowOverhang);
-                up = false;
-            }
-            movedBy = Math.min(overhang, allowOverhang);
-            offsetChildren(up ? movedBy : -movedBy);
-            recycleOffscreenViews();
-            mPopulating = false;
-            overScrolledBy = allowOverhang - overhang;
-        } else {
-            overScrolledBy = allowOverhang;
-            movedBy = 0;
-        }
-
-        if (allowOverScroll) {
-            final int overScrollMode = ViewCompat.getOverScrollMode(this);
-
-            if (overScrollMode == ViewCompat.OVER_SCROLL_ALWAYS ||
-                    (overScrollMode == ViewCompat.OVER_SCROLL_IF_CONTENT_SCROLLS && !contentFits)) {
-
-                if (overScrolledBy > 0) {
-                    EdgeEffectCompat edge = deltaX > 0 ? mLeftEdge : mRightEdge;
-                    edge.onPull((float) Math.abs(deltaX) / getWidth());
-                    ViewCompat.postInvalidateOnAnimation(this);
-                }
-            }
-        }
-
-        return deltaX == 0 || movedBy != 0;
-    }
-
-    /**
-     * Important: this method will leave offscreen views attached if they
-     * are required to maintain the invariant that child view with index i
-     * is always the view corresponding to position mFirstPosition + i.
-     */
-    private void recycleOffscreenViews() {
-        final int height = getHeight();
-        final int clearAbove = 0;
-        final int clearBelow = height;
-        for (int i = getChildCount() - 1; i >= 0; i--) {
-            final View child = getChildAt(i);
-            if (child.getTop() <= clearBelow)  {
-                // There may be other offscreen views, but we need to maintain
-                // the invariant documented above.
-                break;
-            }
-
-            if (mInLayout) {
-                removeViewsInLayout(i, 1);
-            } else {
-                removeViewAt(i);
-            }
-
-            mRecycler.addScrap(child);
-        }
-
-        while (getChildCount() > 0) {
-            final View child = getChildAt(0);
-            if (child.getBottom() >= clearAbove) {
-                // There may be other offscreen views, but we need to maintain
-                // the invariant documented above.
-                break;
-            }
-
-            if (mInLayout) {
-                removeViewsInLayout(0, 1);
-            } else {
-                removeViewAt(0);
-            }
-
-            mRecycler.addScrap(child);
-            mFirstPosition++;
-        }
-    }
-
-    final void offsetChildren(int offset) {
-        final int childCount = getChildCount();
-        for (int i = 0; i < childCount; i++) {
-            final View child = getChildAt(i);
-            child.layout(child.getLeft() + offset, child.getTop(),
-                    child.getRight() + offset, child.getBottom());
-        }
-    }
-
-    private boolean contentFits() {
-        final int childCount = getChildCount();
-        if (childCount == 0) return true;
-        if (childCount != mItemCount) return false;
-
-        return getChildAt(0).getLeft() >= getPaddingLeft() &&
-                getChildAt(childCount - 1).getRight() <= getWidth() - getPaddingRight();
-    }
-
-    private void recycleAllViews() {
-        for (int i = 0; i < getChildCount(); i++) {
-            mRecycler.addScrap(getChildAt(i));
-        }
-
-        if (mInLayout) {
-            removeAllViewsInLayout();
-        } else {
-            removeAllViews();
-        }
-    }
-
-    private int fillRight(int pos, int overhang) {
-        int end = (getRight() - getLeft()) + overhang;
-
-        int nextLeft = getChildCount() == 0 ? 0 : getChildAt(getChildCount() - 1).getRight();
-        while (nextLeft < end && pos < mItemCount) {
-            pos += makeAndAddColumn(pos, nextLeft, true);
-            nextLeft = getChildAt(getChildCount() - 1).getRight();
-        }
-        final int gridRight = getWidth() - getPaddingRight();
-        return getChildAt(getChildCount() - 1).getRight() - gridRight;
-    }
-
-    private int fillLeft(int pos, int overhang) {
-        int end = getPaddingLeft() - overhang;
-
-        int nextRight = getChildAt(0).getLeft();
-        while (nextRight > end && pos >= 0) {
-            pos -= makeAndAddColumn(pos, nextRight, false);
-            nextRight = getChildAt(0).getLeft();
-        }
-
-        mFirstPosition = pos + 1;
-        return getPaddingLeft() - getChildAt(0).getLeft();
-    }
-
-    @Override
-    public void computeScroll() {
-        if (mScroller.computeScrollOffset()) {
-            final int x = mScroller.getCurrX();
-            final int dx = (int) (x - mLastTouchX);
-            mLastTouchX = x;
-            final boolean stopped = !trackMotionScroll(dx, false);
-
-            if (!stopped && !mScroller.isFinished()) {
-                ViewCompat.postInvalidateOnAnimation(this);
-            } else {
-                if (stopped) {
-                    final int overScrollMode = ViewCompat.getOverScrollMode(this);
-                    if (overScrollMode != ViewCompat.OVER_SCROLL_NEVER) {
-                        final EdgeEffectCompat edge;
-                        if (dx > 0) {
-                            edge = mLeftEdge;
-                        } else {
-                            edge = mRightEdge;
-                        }
-                        edge.onAbsorb(Math.abs((int) mScroller.getCurrVelocity()));
-                        ViewCompat.postInvalidateOnAnimation(this);
-                    }
-                    mScroller.abortAnimation();
-                }
-                mTouchMode = TOUCH_MODE_IDLE;
-            }
-        }
-    }
-
-    @Override
-    public void draw(Canvas canvas) {
-        super.draw(canvas);
-
-        if (!mLeftEdge.isFinished()) {
-            final int restoreCount = canvas.save();
-            final int height = getHeight() - getPaddingTop() - getPaddingBottom();
-
-            canvas.rotate(270);
-            canvas.translate(-height + getPaddingTop(), 0);
-            mLeftEdge.setSize(height, getWidth());
-            if (mLeftEdge.draw(canvas)) {
-                postInvalidateOnAnimation();
-            }
-            canvas.restoreToCount(restoreCount);
-        }
-        if (!mRightEdge.isFinished()) {
-            final int restoreCount = canvas.save();
-            final int width = getWidth();
-            final int height = getHeight() - getPaddingTop() - getPaddingBottom();
-
-            canvas.rotate(90);
-            canvas.translate(-getPaddingTop(), width);
-            mRightEdge.setSize(height, width);
-            if (mRightEdge.draw(canvas)) {
-                postInvalidateOnAnimation();
-            }
-            canvas.restoreToCount(restoreCount);
-        }
-    }
-
-    /**
-     * Obtain a populated view from the adapter. If optScrap is non-null and is not
-     * reused it will be placed in the recycle bin.
-     *
-     * @param position position to get view for
-     * @param optScrap Optional scrap view; will be reused if possible
-     * @return A new view, a recycled view from mRecycler, or optScrap
-     */
-    private final View obtainView(int position, View optScrap) {
-        View view = mRecycler.getTransientStateView(position);
-        if (view != null) {
-            return view;
-        }
-
-        // Reuse optScrap if it's of the right type (and not null)
-        final int optType = optScrap != null ?
-                ((LayoutParams) optScrap.getLayoutParams()).viewType : -1;
-        final int positionViewType = mAdapter.getItemViewType(position);
-        final View scrap = optType == positionViewType ?
-                optScrap : mRecycler.getScrapView(positionViewType);
-
-        view = mAdapter.getView(position, scrap, this);
-
-        if (view != scrap && scrap != null) {
-            // The adapter didn't use it; put it back.
-            mRecycler.addScrap(scrap);
-        }
-
-        ViewGroup.LayoutParams lp = view.getLayoutParams();
-
-        if (view.getParent() != this) {
-            if (lp == null) {
-                lp = generateDefaultLayoutParams();
-            } else if (!checkLayoutParams(lp)) {
-                lp = generateLayoutParams(lp);
-            }
-            view.setLayoutParams(lp);
-        }
-
-        final LayoutParams sglp = (LayoutParams) lp;
-        sglp.position = position;
-        sglp.viewType = positionViewType;
-
-        return view;
-    }
-
-    public GalleryThumbnailAdapter getAdapter() {
-        return mAdapter;
-    }
-
-    public void setAdapter(GalleryThumbnailAdapter adapter) {
-        if (mAdapter != null) {
-            mAdapter.unregisterDataSetObserver(mObserver);
-        }
-        // TODO: If the new adapter says that there are stable IDs, remove certain layout records
-        // and onscreen views if they have changed instead of removing all of the state here.
-        clearAllState();
-        mAdapter = adapter;
-        mDataChanged = true;
-        mOldItemCount = mItemCount = adapter != null ? adapter.getCount() : 0;
-        if (adapter != null) {
-            adapter.registerDataSetObserver(mObserver);
-            mRecycler.setViewTypeCount(adapter.getViewTypeCount());
-            mHasStableIds = adapter.hasStableIds();
-        } else {
-            mHasStableIds = false;
-        }
-        populate();
-    }
-
-    /**
-     * Clear all state because the grid will be used for a completely different set of data.
-     */
-    private void clearAllState() {
-        // Clear all layout records and views
-        removeAllViews();
-
-        // Reset to the top of the grid
-        mFirstPosition = 0;
-
-        // Clear recycler because there could be different view types now
-        mRecycler.clear();
-    }
-
-    @Override
-    protected LayoutParams generateDefaultLayoutParams() {
-        return new LayoutParams(LayoutParams.WRAP_CONTENT);
-    }
-
-    @Override
-    protected LayoutParams generateLayoutParams(ViewGroup.LayoutParams lp) {
-        return new LayoutParams(lp);
-    }
-
-    @Override
-    protected boolean checkLayoutParams(ViewGroup.LayoutParams lp) {
-        return lp instanceof LayoutParams;
-    }
-
-    @Override
-    public ViewGroup.LayoutParams generateLayoutParams(AttributeSet attrs) {
-        return new LayoutParams(getContext(), attrs);
-    }
-
-    public static class LayoutParams extends ViewGroup.LayoutParams {
-        private static final int[] LAYOUT_ATTRS = new int[] {
-                android.R.attr.layout_span
-        };
-
-        private static final int SPAN_INDEX = 0;
-
-        /**
-         * The number of columns this item should span
-         */
-        public int span = 1;
-
-        /**
-         * Item position this view represents
-         */
-        int position;
-
-        /**
-         * Type of this view as reported by the adapter
-         */
-        int viewType;
-
-        /**
-         * The column this view is occupying
-         */
-        int column;
-
-        /**
-         * The stable ID of the item this view displays
-         */
-        long id = -1;
-
-        public LayoutParams(int height) {
-            super(MATCH_PARENT, height);
-
-            if (this.height == MATCH_PARENT) {
-                Log.w(TAG, "Constructing LayoutParams with height MATCH_PARENT - " +
-                        "impossible! Falling back to WRAP_CONTENT");
-                this.height = WRAP_CONTENT;
-            }
-        }
-
-        public LayoutParams(Context c, AttributeSet attrs) {
-            super(c, attrs);
-
-            if (this.width != MATCH_PARENT) {
-                Log.w(TAG, "Inflation setting LayoutParams width to " + this.width +
-                        " - must be MATCH_PARENT");
-                this.width = MATCH_PARENT;
-            }
-            if (this.height == MATCH_PARENT) {
-                Log.w(TAG, "Inflation setting LayoutParams height to MATCH_PARENT - " +
-                        "impossible! Falling back to WRAP_CONTENT");
-                this.height = WRAP_CONTENT;
-            }
-
-            TypedArray a = c.obtainStyledAttributes(attrs, LAYOUT_ATTRS);
-            span = a.getInteger(SPAN_INDEX, 1);
-            a.recycle();
-        }
-
-        public LayoutParams(ViewGroup.LayoutParams other) {
-            super(other);
-
-            if (this.width != MATCH_PARENT) {
-                Log.w(TAG, "Constructing LayoutParams with width " + this.width +
-                        " - must be MATCH_PARENT");
-                this.width = MATCH_PARENT;
-            }
-            if (this.height == MATCH_PARENT) {
-                Log.w(TAG, "Constructing LayoutParams with height MATCH_PARENT - " +
-                        "impossible! Falling back to WRAP_CONTENT");
-                this.height = WRAP_CONTENT;
-            }
-        }
-    }
-
-    private class RecycleBin {
-        private ArrayList<View>[] mScrapViews;
-        private int mViewTypeCount;
-        private int mMaxScrap;
-
-        private SparseArray<View> mTransientStateViews;
-
-        public void setViewTypeCount(int viewTypeCount) {
-            if (viewTypeCount < 1) {
-                throw new IllegalArgumentException("Must have at least one view type (" +
-                        viewTypeCount + " types reported)");
-            }
-            if (viewTypeCount == mViewTypeCount) {
-                return;
-            }
-
-            ArrayList<View>[] scrapViews = new ArrayList[viewTypeCount];
-            for (int i = 0; i < viewTypeCount; i++) {
-                scrapViews[i] = new ArrayList<View>();
-            }
-            mViewTypeCount = viewTypeCount;
-            mScrapViews = scrapViews;
-        }
-
-        public void clear() {
-            final int typeCount = mViewTypeCount;
-            for (int i = 0; i < typeCount; i++) {
-                mScrapViews[i].clear();
-            }
-            if (mTransientStateViews != null) {
-                mTransientStateViews.clear();
-            }
-        }
-
-        public void clearTransientViews() {
-            if (mTransientStateViews != null) {
-                mTransientStateViews.clear();
-            }
-        }
-
-        public void addScrap(View v) {
-            final LayoutParams lp = (LayoutParams) v.getLayoutParams();
-            if (ViewCompat.hasTransientState(v)) {
-                if (mTransientStateViews == null) {
-                    mTransientStateViews = new SparseArray<View>();
-                }
-                mTransientStateViews.put(lp.position, v);
-                return;
-            }
-
-            final int childCount = getChildCount();
-            if (childCount > mMaxScrap) {
-                mMaxScrap = childCount;
-            }
-
-            ArrayList<View> scrap = mScrapViews[lp.viewType];
-            if (scrap.size() < mMaxScrap) {
-                scrap.add(v);
-            }
-        }
-
-        public View getTransientStateView(int position) {
-            if (mTransientStateViews == null) {
-                return null;
-            }
-
-            final View result = mTransientStateViews.get(position);
-            if (result != null) {
-                mTransientStateViews.remove(position);
-            }
-            return result;
-        }
-
-        public View getScrapView(int type) {
-            ArrayList<View> scrap = mScrapViews[type];
-            if (scrap.isEmpty()) {
-                return null;
-            }
-
-            final int index = scrap.size() - 1;
-            final View result = scrap.get(index);
-            scrap.remove(index);
-            return result;
-        }
-    }
-
-    private class AdapterDataSetObserver extends DataSetObserver {
-        @Override
-        public void onChanged() {
-            mDataChanged = true;
-            mOldItemCount = mItemCount;
-            mItemCount = mAdapter.getCount();
-
-            // TODO: Consider matching these back up if we have stable IDs.
-            mRecycler.clearTransientViews();
-
-            if (!mHasStableIds) {
-                recycleAllViews();
-            }
-
-            // TODO: consider repopulating in a deferred runnable instead
-            // (so that successive changes may still be batched)
-            requestLayout();
-        }
-
-        @Override
-        public void onInvalidated() {
-        }
-    }
-}
diff --git a/src/com/android/photos/views/HeaderGridView.java b/src/com/android/photos/views/HeaderGridView.java
deleted file mode 100644
index 45a5eaf..0000000
--- a/src/com/android/photos/views/HeaderGridView.java
+++ /dev/null
@@ -1,466 +0,0 @@
-/*
- * Copyright (C) 2013 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.photos.views;
-
-import android.content.Context;
-import android.database.DataSetObservable;
-import android.database.DataSetObserver;
-import android.util.AttributeSet;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.AdapterView;
-import android.widget.Filter;
-import android.widget.Filterable;
-import android.widget.FrameLayout;
-import android.widget.GridView;
-import android.widget.ListAdapter;
-import android.widget.WrapperListAdapter;
-
-import java.util.ArrayList;
-
-/**
- * A {@link GridView} that supports adding header rows in a
- * very similar way to {@link ListView}.
- * See {@link HeaderGridView#addHeaderView(View, Object, boolean)}
- */
-public class HeaderGridView extends GridView {
-    private static final String TAG = "HeaderGridView";
-
-    /**
-     * A class that represents a fixed view in a list, for example a header at the top
-     * or a footer at the bottom.
-     */
-    private static class FixedViewInfo {
-        /** The view to add to the grid */
-        public View view;
-        public ViewGroup viewContainer;
-        /** The data backing the view. This is returned from {@link ListAdapter#getItem(int)}. */
-        public Object data;
-        /** <code>true</code> if the fixed view should be selectable in the grid */
-        public boolean isSelectable;
-    }
-
-    private ArrayList<FixedViewInfo> mHeaderViewInfos = new ArrayList<FixedViewInfo>();
-
-    private void initHeaderGridView() {
-        super.setClipChildren(false);
-    }
-
-    public HeaderGridView(Context context) {
-        super(context);
-        initHeaderGridView();
-    }
-
-    public HeaderGridView(Context context, AttributeSet attrs) {
-        super(context, attrs);
-        initHeaderGridView();
-    }
-
-    public HeaderGridView(Context context, AttributeSet attrs, int defStyle) {
-        super(context, attrs, defStyle);
-        initHeaderGridView();
-    }
-
-    @Override
-    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
-        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
-        ListAdapter adapter = getAdapter();
-        if (adapter != null && adapter instanceof HeaderViewGridAdapter) {
-            ((HeaderViewGridAdapter) adapter).setNumColumns(getNumColumns());
-        }
-    }
-
-    @Override
-    public void setClipChildren(boolean clipChildren) {
-       // Ignore, since the header rows depend on not being clipped
-    }
-
-    /**
-     * Add a fixed view to appear at the top of the grid. If addHeaderView is
-     * called more than once, the views will appear in the order they were
-     * added. Views added using this call can take focus if they want.
-     * <p>
-     * NOTE: Call this before calling setAdapter. This is so HeaderGridView can wrap
-     * the supplied cursor with one that will also account for header views.
-     *
-     * @param v The view to add.
-     * @param data Data to associate with this view
-     * @param isSelectable whether the item is selectable
-     */
-    public void addHeaderView(View v, Object data, boolean isSelectable) {
-        ListAdapter adapter = getAdapter();
-
-        if (adapter != null && ! (adapter instanceof HeaderViewGridAdapter)) {
-            throw new IllegalStateException(
-                    "Cannot add header view to grid -- setAdapter has already been called.");
-        }
-
-        FixedViewInfo info = new FixedViewInfo();
-        FrameLayout fl = new FullWidthFixedViewLayout(getContext());
-        fl.addView(v);
-        info.view = v;
-        info.viewContainer = fl;
-        info.data = data;
-        info.isSelectable = isSelectable;
-        mHeaderViewInfos.add(info);
-
-        // in the case of re-adding a header view, or adding one later on,
-        // we need to notify the observer
-        if (adapter != null) {
-            ((HeaderViewGridAdapter) adapter).notifyDataSetChanged();
-        }
-    }
-
-    /**
-     * Add a fixed view to appear at the top of the grid. If addHeaderView is
-     * called more than once, the views will appear in the order they were
-     * added. Views added using this call can take focus if they want.
-     * <p>
-     * NOTE: Call this before calling setAdapter. This is so HeaderGridView can wrap
-     * the supplied cursor with one that will also account for header views.
-     *
-     * @param v The view to add.
-     */
-    public void addHeaderView(View v) {
-        addHeaderView(v, null, true);
-    }
-
-    public int getHeaderViewCount() {
-        return mHeaderViewInfos.size();
-    }
-
-    /**
-     * Removes a previously-added header view.
-     *
-     * @param v The view to remove
-     * @return true if the view was removed, false if the view was not a header
-     *         view
-     */
-    public boolean removeHeaderView(View v) {
-        if (mHeaderViewInfos.size() > 0) {
-            boolean result = false;
-            ListAdapter adapter = getAdapter();
-            if (adapter != null && ((HeaderViewGridAdapter) adapter).removeHeader(v)) {
-                result = true;
-            }
-            removeFixedViewInfo(v, mHeaderViewInfos);
-            return result;
-        }
-        return false;
-    }
-
-    private void removeFixedViewInfo(View v, ArrayList<FixedViewInfo> where) {
-        int len = where.size();
-        for (int i = 0; i < len; ++i) {
-            FixedViewInfo info = where.get(i);
-            if (info.view == v) {
-                where.remove(i);
-                break;
-            }
-        }
-    }
-
-    @Override
-    public void setAdapter(ListAdapter adapter) {
-        if (mHeaderViewInfos.size() > 0) {
-            HeaderViewGridAdapter hadapter = new HeaderViewGridAdapter(mHeaderViewInfos, adapter);
-            int numColumns = getNumColumns();
-            if (numColumns > 1) {
-                hadapter.setNumColumns(numColumns);
-            }
-            super.setAdapter(hadapter);
-        } else {
-            super.setAdapter(adapter);
-        }
-    }
-
-    private class FullWidthFixedViewLayout extends FrameLayout {
-        public FullWidthFixedViewLayout(Context context) {
-            super(context);
-        }
-
-        @Override
-        protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
-            int targetWidth = HeaderGridView.this.getMeasuredWidth()
-                    - HeaderGridView.this.getPaddingLeft()
-                    - HeaderGridView.this.getPaddingRight();
-            widthMeasureSpec = MeasureSpec.makeMeasureSpec(targetWidth,
-                    MeasureSpec.getMode(widthMeasureSpec));
-            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
-        }
-    }
-
-    /**
-     * ListAdapter used when a HeaderGridView has header views. This ListAdapter
-     * wraps another one and also keeps track of the header views and their
-     * associated data objects.
-     *<p>This is intended as a base class; you will probably not need to
-     * use this class directly in your own code.
-     */
-    private static class HeaderViewGridAdapter implements WrapperListAdapter, Filterable {
-
-        // This is used to notify the container of updates relating to number of columns
-        // or headers changing, which changes the number of placeholders needed
-        private final DataSetObservable mDataSetObservable = new DataSetObservable();
-
-        private final ListAdapter mAdapter;
-        private int mNumColumns = 1;
-
-        // This ArrayList is assumed to NOT be null.
-        ArrayList<FixedViewInfo> mHeaderViewInfos;
-
-        boolean mAreAllFixedViewsSelectable;
-
-        private final boolean mIsFilterable;
-
-        public HeaderViewGridAdapter(ArrayList<FixedViewInfo> headerViewInfos, ListAdapter adapter) {
-            mAdapter = adapter;
-            mIsFilterable = adapter instanceof Filterable;
-
-            if (headerViewInfos == null) {
-                throw new IllegalArgumentException("headerViewInfos cannot be null");
-            }
-            mHeaderViewInfos = headerViewInfos;
-
-            mAreAllFixedViewsSelectable = areAllListInfosSelectable(mHeaderViewInfos);
-        }
-
-        public int getHeadersCount() {
-            return mHeaderViewInfos.size();
-        }
-
-        @Override
-        public boolean isEmpty() {
-            return (mAdapter == null || mAdapter.isEmpty()) && getHeadersCount() == 0;
-        }
-
-        public void setNumColumns(int numColumns) {
-            if (numColumns < 1) {
-                throw new IllegalArgumentException("Number of columns must be 1 or more");
-            }
-            if (mNumColumns != numColumns) {
-                mNumColumns = numColumns;
-                notifyDataSetChanged();
-            }
-        }
-
-        private boolean areAllListInfosSelectable(ArrayList<FixedViewInfo> infos) {
-            if (infos != null) {
-                for (FixedViewInfo info : infos) {
-                    if (!info.isSelectable) {
-                        return false;
-                    }
-                }
-            }
-            return true;
-        }
-
-        public boolean removeHeader(View v) {
-            for (int i = 0; i < mHeaderViewInfos.size(); i++) {
-                FixedViewInfo info = mHeaderViewInfos.get(i);
-                if (info.view == v) {
-                    mHeaderViewInfos.remove(i);
-
-                    mAreAllFixedViewsSelectable = areAllListInfosSelectable(mHeaderViewInfos);
-
-                    mDataSetObservable.notifyChanged();
-                    return true;
-                }
-            }
-
-            return false;
-        }
-
-        @Override
-        public int getCount() {
-            if (mAdapter != null) {
-                return getHeadersCount() * mNumColumns + mAdapter.getCount();
-            } else {
-                return getHeadersCount() * mNumColumns;
-            }
-        }
-
-        @Override
-        public boolean areAllItemsEnabled() {
-            if (mAdapter != null) {
-                return mAreAllFixedViewsSelectable && mAdapter.areAllItemsEnabled();
-            } else {
-                return true;
-            }
-        }
-
-        @Override
-        public boolean isEnabled(int position) {
-            // Header (negative positions will throw an ArrayIndexOutOfBoundsException)
-            int numHeadersAndPlaceholders = getHeadersCount() * mNumColumns;
-            if (position < numHeadersAndPlaceholders) {
-                return (position % mNumColumns == 0)
-                        && mHeaderViewInfos.get(position / mNumColumns).isSelectable;
-            }
-
-            // Adapter
-            final int adjPosition = position - numHeadersAndPlaceholders;
-            int adapterCount = 0;
-            if (mAdapter != null) {
-                adapterCount = mAdapter.getCount();
-                if (adjPosition < adapterCount) {
-                    return mAdapter.isEnabled(adjPosition);
-                }
-            }
-
-            throw new ArrayIndexOutOfBoundsException(position);
-        }
-
-        @Override
-        public Object getItem(int position) {
-            // Header (negative positions will throw an ArrayIndexOutOfBoundsException)
-            int numHeadersAndPlaceholders = getHeadersCount() * mNumColumns;
-            if (position < numHeadersAndPlaceholders) {
-                if (position % mNumColumns == 0) {
-                    return mHeaderViewInfos.get(position / mNumColumns).data;
-                }
-                return null;
-            }
-
-            // Adapter
-            final int adjPosition = position - numHeadersAndPlaceholders;
-            int adapterCount = 0;
-            if (mAdapter != null) {
-                adapterCount = mAdapter.getCount();
-                if (adjPosition < adapterCount) {
-                    return mAdapter.getItem(adjPosition);
-                }
-            }
-
-            throw new ArrayIndexOutOfBoundsException(position);
-        }
-
-        @Override
-        public long getItemId(int position) {
-            int numHeadersAndPlaceholders = getHeadersCount() * mNumColumns;
-            if (mAdapter != null && position >= numHeadersAndPlaceholders) {
-                int adjPosition = position - numHeadersAndPlaceholders;
-                int adapterCount = mAdapter.getCount();
-                if (adjPosition < adapterCount) {
-                    return mAdapter.getItemId(adjPosition);
-                }
-            }
-            return -1;
-        }
-
-        @Override
-        public boolean hasStableIds() {
-            if (mAdapter != null) {
-                return mAdapter.hasStableIds();
-            }
-            return false;
-        }
-
-        @Override
-        public View getView(int position, View convertView, ViewGroup parent) {
-            // Header (negative positions will throw an ArrayIndexOutOfBoundsException)
-            int numHeadersAndPlaceholders = getHeadersCount() * mNumColumns ;
-            if (position < numHeadersAndPlaceholders) {
-                View headerViewContainer = mHeaderViewInfos
-                        .get(position / mNumColumns).viewContainer;
-                if (position % mNumColumns == 0) {
-                    return headerViewContainer;
-                } else {
-                    if (convertView == null) {
-                        convertView = new View(parent.getContext());
-                    }
-                    // We need to do this because GridView uses the height of the last item
-                    // in a row to determine the height for the entire row.
-                    convertView.setVisibility(View.INVISIBLE);
-                    convertView.setMinimumHeight(headerViewContainer.getHeight());
-                    return convertView;
-                }
-            }
-
-            // Adapter
-            final int adjPosition = position - numHeadersAndPlaceholders;
-            int adapterCount = 0;
-            if (mAdapter != null) {
-                adapterCount = mAdapter.getCount();
-                if (adjPosition < adapterCount) {
-                    return mAdapter.getView(adjPosition, convertView, parent);
-                }
-            }
-
-            throw new ArrayIndexOutOfBoundsException(position);
-        }
-
-        @Override
-        public int getItemViewType(int position) {
-            int numHeadersAndPlaceholders = getHeadersCount() * mNumColumns;
-            if (position < numHeadersAndPlaceholders && (position % mNumColumns != 0)) {
-                // Placeholders get the last view type number
-                return mAdapter != null ? mAdapter.getViewTypeCount() : 1;
-            }
-            if (mAdapter != null && position >= numHeadersAndPlaceholders) {
-                int adjPosition = position - numHeadersAndPlaceholders;
-                int adapterCount = mAdapter.getCount();
-                if (adjPosition < adapterCount) {
-                    return mAdapter.getItemViewType(adjPosition);
-                }
-            }
-
-            return AdapterView.ITEM_VIEW_TYPE_HEADER_OR_FOOTER;
-        }
-
-        @Override
-        public int getViewTypeCount() {
-            if (mAdapter != null) {
-                return mAdapter.getViewTypeCount() + 1;
-            }
-            return 2;
-        }
-
-        @Override
-        public void registerDataSetObserver(DataSetObserver observer) {
-            mDataSetObservable.registerObserver(observer);
-            if (mAdapter != null) {
-                mAdapter.registerDataSetObserver(observer);
-            }
-        }
-
-        @Override
-        public void unregisterDataSetObserver(DataSetObserver observer) {
-            mDataSetObservable.unregisterObserver(observer);
-            if (mAdapter != null) {
-                mAdapter.unregisterDataSetObserver(observer);
-            }
-        }
-
-        @Override
-        public Filter getFilter() {
-            if (mIsFilterable) {
-                return ((Filterable) mAdapter).getFilter();
-            }
-            return null;
-        }
-
-        @Override
-        public ListAdapter getWrappedAdapter() {
-            return mAdapter;
-        }
-
-        public void notifyDataSetChanged() {
-            mDataSetObservable.notifyChanged();
-        }
-    }
-}
diff --git a/src/com/android/photos/views/SquareImageView.java b/src/com/android/photos/views/SquareImageView.java
deleted file mode 100644
index 14eff10..0000000
--- a/src/com/android/photos/views/SquareImageView.java
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Copyright (C) 2013 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.photos.views;
-
-import android.content.Context;
-import android.util.AttributeSet;
-import android.widget.ImageView;
-
-
-public class SquareImageView extends ImageView {
-
-    public SquareImageView(Context context) {
-        super(context);
-    }
-
-    public SquareImageView(Context context, AttributeSet attrs) {
-        super(context, attrs);
-    }
-
-    public SquareImageView(Context context, AttributeSet attrs, int defStyle) {
-        super(context, attrs, defStyle);
-    }
-
-    @Override
-    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
-        int widthMode = MeasureSpec.getMode(widthMeasureSpec);
-        int heightMode = MeasureSpec.getMode(heightMeasureSpec);
-        if (widthMode == MeasureSpec.EXACTLY && heightMode != MeasureSpec.EXACTLY) {
-            int width = MeasureSpec.getSize(widthMeasureSpec);
-            int height = width;
-            if (heightMode == MeasureSpec.AT_MOST) {
-                height = Math.min(height, MeasureSpec.getSize(heightMeasureSpec));
-            }
-            setMeasuredDimension(width, height);
-        } else {
-            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
-        }
-    }
-}
diff --git a/src/com/android/photos/views/TiledImageRenderer.java b/src/com/android/photos/views/TiledImageRenderer.java
deleted file mode 100644
index c4e493b..0000000
--- a/src/com/android/photos/views/TiledImageRenderer.java
+++ /dev/null
@@ -1,825 +0,0 @@
-/*
- * Copyright (C) 2013 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.photos.views;
-
-import android.content.Context;
-import android.graphics.Bitmap;
-import android.graphics.Rect;
-import android.graphics.RectF;
-import android.support.v4.util.LongSparseArray;
-import android.util.DisplayMetrics;
-import android.util.Log;
-import android.util.Pools.Pool;
-import android.util.Pools.SynchronizedPool;
-import android.view.View;
-import android.view.WindowManager;
-
-import com.android.gallery3d.common.Utils;
-import com.android.gallery3d.glrenderer.BasicTexture;
-import com.android.gallery3d.glrenderer.GLCanvas;
-import com.android.gallery3d.glrenderer.UploadedTexture;
-
-/**
- * Handles laying out, decoding, and drawing of tiles in GL
- */
-public class TiledImageRenderer {
-    public static final int SIZE_UNKNOWN = -1;
-
-    private static final String TAG = "TiledImageRenderer";
-    private static final int UPLOAD_LIMIT = 1;
-
-    /*
-     *  This is the tile state in the CPU side.
-     *  Life of a Tile:
-     *      ACTIVATED (initial state)
-     *              --> IN_QUEUE - by queueForDecode()
-     *              --> RECYCLED - by recycleTile()
-     *      IN_QUEUE --> DECODING - by decodeTile()
-     *               --> RECYCLED - by recycleTile)
-     *      DECODING --> RECYCLING - by recycleTile()
-     *               --> DECODED  - by decodeTile()
-     *               --> DECODE_FAIL - by decodeTile()
-     *      RECYCLING --> RECYCLED - by decodeTile()
-     *      DECODED --> ACTIVATED - (after the decoded bitmap is uploaded)
-     *      DECODED --> RECYCLED - by recycleTile()
-     *      DECODE_FAIL -> RECYCLED - by recycleTile()
-     *      RECYCLED --> ACTIVATED - by obtainTile()
-     */
-    private static final int STATE_ACTIVATED = 0x01;
-    private static final int STATE_IN_QUEUE = 0x02;
-    private static final int STATE_DECODING = 0x04;
-    private static final int STATE_DECODED = 0x08;
-    private static final int STATE_DECODE_FAIL = 0x10;
-    private static final int STATE_RECYCLING = 0x20;
-    private static final int STATE_RECYCLED = 0x40;
-
-    private static Pool<Bitmap> sTilePool = new SynchronizedPool<Bitmap>(64);
-
-    // TILE_SIZE must be 2^N
-    private int mTileSize;
-
-    private TileSource mModel;
-    private BasicTexture mPreview;
-    protected int mLevelCount;  // cache the value of mScaledBitmaps.length
-
-    // The mLevel variable indicates which level of bitmap we should use.
-    // Level 0 means the original full-sized bitmap, and a larger value means
-    // a smaller scaled bitmap (The width and height of each scaled bitmap is
-    // half size of the previous one). If the value is in [0, mLevelCount), we
-    // use the bitmap in mScaledBitmaps[mLevel] for display, otherwise the value
-    // is mLevelCount
-    private int mLevel = 0;
-
-    private int mOffsetX;
-    private int mOffsetY;
-
-    private int mUploadQuota;
-    private boolean mRenderComplete;
-
-    private final RectF mSourceRect = new RectF();
-    private final RectF mTargetRect = new RectF();
-
-    private final LongSparseArray<Tile> mActiveTiles = new LongSparseArray<Tile>();
-
-    // The following three queue are guarded by mQueueLock
-    private final Object mQueueLock = new Object();
-    private final TileQueue mRecycledQueue = new TileQueue();
-    private final TileQueue mUploadQueue = new TileQueue();
-    private final TileQueue mDecodeQueue = new TileQueue();
-
-    // The width and height of the full-sized bitmap
-    protected int mImageWidth = SIZE_UNKNOWN;
-    protected int mImageHeight = SIZE_UNKNOWN;
-
-    protected int mCenterX;
-    protected int mCenterY;
-    protected float mScale;
-    protected int mRotation;
-
-    private boolean mLayoutTiles;
-
-    // Temp variables to avoid memory allocation
-    private final Rect mTileRange = new Rect();
-    private final Rect mActiveRange[] = {new Rect(), new Rect()};
-
-    private TileDecoder mTileDecoder;
-    private boolean mBackgroundTileUploaded;
-
-    private int mViewWidth, mViewHeight;
-    private View mParent;
-
-    /**
-     * Interface for providing tiles to a {@link TiledImageRenderer}
-     */
-    public static interface TileSource {
-
-        /**
-         * If the source does not care about the tile size, it should use
-         * {@link TiledImageRenderer#suggestedTileSize(Context)}
-         */
-        public int getTileSize();
-        public int getImageWidth();
-        public int getImageHeight();
-        public int getRotation();
-
-        /**
-         * Return a Preview image if available. This will be used as the base layer
-         * if higher res tiles are not yet available
-         */
-        public BasicTexture getPreview();
-
-        /**
-         * The tile returned by this method can be specified this way: Assuming
-         * the image size is (width, height), first take the intersection of (0,
-         * 0) - (width, height) and (x, y) - (x + tileSize, y + tileSize). If
-         * in extending the region, we found some part of the region is outside
-         * the image, those pixels are filled with black.
-         *
-         * If level > 0, it does the same operation on a down-scaled version of
-         * the original image (down-scaled by a factor of 2^level), but (x, y)
-         * still refers to the coordinate on the original image.
-         *
-         * The method would be called by the decoder thread.
-         */
-        public Bitmap getTile(int level, int x, int y, Bitmap reuse);
-    }
-
-    public static int suggestedTileSize(Context context) {
-        return isHighResolution(context) ? 512 : 256;
-    }
-
-    private static boolean isHighResolution(Context context) {
-        DisplayMetrics metrics = new DisplayMetrics();
-        WindowManager wm = (WindowManager)
-                context.getSystemService(Context.WINDOW_SERVICE);
-        wm.getDefaultDisplay().getMetrics(metrics);
-        return metrics.heightPixels > 2048 ||  metrics.widthPixels > 2048;
-    }
-
-    public TiledImageRenderer(View parent) {
-        mParent = parent;
-        mTileDecoder = new TileDecoder();
-        mTileDecoder.start();
-    }
-
-    public int getViewWidth() {
-        return mViewWidth;
-    }
-
-    public int getViewHeight() {
-        return mViewHeight;
-    }
-
-    private void invalidate() {
-        mParent.postInvalidate();
-    }
-
-    public void setModel(TileSource model, int rotation) {
-        if (mModel != model) {
-            mModel = model;
-            notifyModelInvalidated();
-        }
-        if (mRotation != rotation) {
-            mRotation = rotation;
-            mLayoutTiles = true;
-        }
-    }
-
-    private void calculateLevelCount() {
-        if (mPreview != null) {
-            mLevelCount = Math.max(0, Utils.ceilLog2(
-                mImageWidth / (float) mPreview.getWidth()));
-        } else {
-            int levels = 1;
-            int maxDim = Math.max(mImageWidth, mImageHeight);
-            int t = mTileSize;
-            while (t < maxDim) {
-                t <<= 1;
-                levels++;
-            }
-            mLevelCount = levels;
-        }
-    }
-
-    public void notifyModelInvalidated() {
-        invalidateTiles();
-        if (mModel == null) {
-            mImageWidth = 0;
-            mImageHeight = 0;
-            mLevelCount = 0;
-            mPreview = null;
-        } else {
-            mImageWidth = mModel.getImageWidth();
-            mImageHeight = mModel.getImageHeight();
-            mPreview = mModel.getPreview();
-            mTileSize = mModel.getTileSize();
-            calculateLevelCount();
-        }
-        mLayoutTiles = true;
-    }
-
-    public void setViewSize(int width, int height) {
-        mViewWidth = width;
-        mViewHeight = height;
-    }
-
-    public void setPosition(int centerX, int centerY, float scale) {
-        if (mCenterX == centerX && mCenterY == centerY
-                && mScale == scale) {
-            return;
-        }
-        mCenterX = centerX;
-        mCenterY = centerY;
-        mScale = scale;
-        mLayoutTiles = true;
-    }
-
-    // Prepare the tiles we want to use for display.
-    //
-    // 1. Decide the tile level we want to use for display.
-    // 2. Decide the tile levels we want to keep as texture (in addition to
-    //    the one we use for display).
-    // 3. Recycle unused tiles.
-    // 4. Activate the tiles we want.
-    private void layoutTiles() {
-        if (mViewWidth == 0 || mViewHeight == 0 || !mLayoutTiles) {
-            return;
-        }
-        mLayoutTiles = false;
-
-        // The tile levels we want to keep as texture is in the range
-        // [fromLevel, endLevel).
-        int fromLevel;
-        int endLevel;
-
-        // We want to use a texture larger than or equal to the display size.
-        mLevel = Utils.clamp(Utils.floorLog2(1f / mScale), 0, mLevelCount);
-
-        // We want to keep one more tile level as texture in addition to what
-        // we use for display. So it can be faster when the scale moves to the
-        // next level. We choose the level closest to the current scale.
-        if (mLevel != mLevelCount) {
-            Rect range = mTileRange;
-            getRange(range, mCenterX, mCenterY, mLevel, mScale, mRotation);
-            mOffsetX = Math.round(mViewWidth / 2f + (range.left - mCenterX) * mScale);
-            mOffsetY = Math.round(mViewHeight / 2f + (range.top - mCenterY) * mScale);
-            fromLevel = mScale * (1 << mLevel) > 0.75f ? mLevel - 1 : mLevel;
-        } else {
-            // Activate the tiles of the smallest two levels.
-            fromLevel = mLevel - 2;
-            mOffsetX = Math.round(mViewWidth / 2f - mCenterX * mScale);
-            mOffsetY = Math.round(mViewHeight / 2f - mCenterY * mScale);
-        }
-
-        fromLevel = Math.max(0, Math.min(fromLevel, mLevelCount - 2));
-        endLevel = Math.min(fromLevel + 2, mLevelCount);
-
-        Rect range[] = mActiveRange;
-        for (int i = fromLevel; i < endLevel; ++i) {
-            getRange(range[i - fromLevel], mCenterX, mCenterY, i, mRotation);
-        }
-
-        // If rotation is transient, don't update the tile.
-        if (mRotation % 90 != 0) {
-            return;
-        }
-
-        synchronized (mQueueLock) {
-            mDecodeQueue.clean();
-            mUploadQueue.clean();
-            mBackgroundTileUploaded = false;
-
-            // Recycle unused tiles: if the level of the active tile is outside the
-            // range [fromLevel, endLevel) or not in the visible range.
-            int n = mActiveTiles.size();
-            for (int i = 0; i < n; i++) {
-                Tile tile = mActiveTiles.valueAt(i);
-                int level = tile.mTileLevel;
-                if (level < fromLevel || level >= endLevel
-                        || !range[level - fromLevel].contains(tile.mX, tile.mY)) {
-                    mActiveTiles.removeAt(i);
-                    i--;
-                    n--;
-                    recycleTile(tile);
-                }
-            }
-        }
-
-        for (int i = fromLevel; i < endLevel; ++i) {
-            int size = mTileSize << i;
-            Rect r = range[i - fromLevel];
-            for (int y = r.top, bottom = r.bottom; y < bottom; y += size) {
-                for (int x = r.left, right = r.right; x < right; x += size) {
-                    activateTile(x, y, i);
-                }
-            }
-        }
-        invalidate();
-    }
-
-    private void invalidateTiles() {
-        synchronized (mQueueLock) {
-            mDecodeQueue.clean();
-            mUploadQueue.clean();
-
-            // TODO(xx): disable decoder
-            int n = mActiveTiles.size();
-            for (int i = 0; i < n; i++) {
-                Tile tile = mActiveTiles.valueAt(i);
-                recycleTile(tile);
-            }
-            mActiveTiles.clear();
-        }
-    }
-
-    private void getRange(Rect out, int cX, int cY, int level, int rotation) {
-        getRange(out, cX, cY, level, 1f / (1 << (level + 1)), rotation);
-    }
-
-    // If the bitmap is scaled by the given factor "scale", return the
-    // rectangle containing visible range. The left-top coordinate returned is
-    // aligned to the tile boundary.
-    //
-    // (cX, cY) is the point on the original bitmap which will be put in the
-    // center of the ImageViewer.
-    private void getRange(Rect out,
-            int cX, int cY, int level, float scale, int rotation) {
-
-        double radians = Math.toRadians(-rotation);
-        double w = mViewWidth;
-        double h = mViewHeight;
-
-        double cos = Math.cos(radians);
-        double sin = Math.sin(radians);
-        int width = (int) Math.ceil(Math.max(
-                Math.abs(cos * w - sin * h), Math.abs(cos * w + sin * h)));
-        int height = (int) Math.ceil(Math.max(
-                Math.abs(sin * w + cos * h), Math.abs(sin * w - cos * h)));
-
-        int left = (int) Math.floor(cX - width / (2f * scale));
-        int top = (int) Math.floor(cY - height / (2f * scale));
-        int right = (int) Math.ceil(left + width / scale);
-        int bottom = (int) Math.ceil(top + height / scale);
-
-        // align the rectangle to tile boundary
-        int size = mTileSize << level;
-        left = Math.max(0, size * (left / size));
-        top = Math.max(0, size * (top / size));
-        right = Math.min(mImageWidth, right);
-        bottom = Math.min(mImageHeight, bottom);
-
-        out.set(left, top, right, bottom);
-    }
-
-    public void freeTextures() {
-        mLayoutTiles = true;
-
-        mTileDecoder.finishAndWait();
-        synchronized (mQueueLock) {
-            mUploadQueue.clean();
-            mDecodeQueue.clean();
-            Tile tile = mRecycledQueue.pop();
-            while (tile != null) {
-                tile.recycle();
-                tile = mRecycledQueue.pop();
-            }
-        }
-
-        int n = mActiveTiles.size();
-        for (int i = 0; i < n; i++) {
-            Tile texture = mActiveTiles.valueAt(i);
-            texture.recycle();
-        }
-        mActiveTiles.clear();
-        mTileRange.set(0, 0, 0, 0);
-
-        while (sTilePool.acquire() != null) {}
-    }
-
-    public boolean draw(GLCanvas canvas) {
-        layoutTiles();
-        uploadTiles(canvas);
-
-        mUploadQuota = UPLOAD_LIMIT;
-        mRenderComplete = true;
-
-        int level = mLevel;
-        int rotation = mRotation;
-        int flags = 0;
-        if (rotation != 0) {
-            flags |= GLCanvas.SAVE_FLAG_MATRIX;
-        }
-
-        if (flags != 0) {
-            canvas.save(flags);
-            if (rotation != 0) {
-                int centerX = mViewWidth / 2, centerY = mViewHeight / 2;
-                canvas.translate(centerX, centerY);
-                canvas.rotate(rotation, 0, 0, 1);
-                canvas.translate(-centerX, -centerY);
-            }
-        }
-        try {
-            if (level != mLevelCount) {
-                int size = (mTileSize << level);
-                float length = size * mScale;
-                Rect r = mTileRange;
-
-                for (int ty = r.top, i = 0; ty < r.bottom; ty += size, i++) {
-                    float y = mOffsetY + i * length;
-                    for (int tx = r.left, j = 0; tx < r.right; tx += size, j++) {
-                        float x = mOffsetX + j * length;
-                        drawTile(canvas, tx, ty, level, x, y, length);
-                    }
-                }
-            } else if (mPreview != null) {
-                mPreview.draw(canvas, mOffsetX, mOffsetY,
-                        Math.round(mImageWidth * mScale),
-                        Math.round(mImageHeight * mScale));
-            }
-        } finally {
-            if (flags != 0) {
-                canvas.restore();
-            }
-        }
-
-        if (mRenderComplete) {
-            if (!mBackgroundTileUploaded) {
-                uploadBackgroundTiles(canvas);
-            }
-        } else {
-            invalidate();
-        }
-        return mRenderComplete || mPreview != null;
-    }
-
-    private void uploadBackgroundTiles(GLCanvas canvas) {
-        mBackgroundTileUploaded = true;
-        int n = mActiveTiles.size();
-        for (int i = 0; i < n; i++) {
-            Tile tile = mActiveTiles.valueAt(i);
-            if (!tile.isContentValid()) {
-                queueForDecode(tile);
-            }
-        }
-    }
-
-   private void queueForDecode(Tile tile) {
-       synchronized (mQueueLock) {
-           if (tile.mTileState == STATE_ACTIVATED) {
-               tile.mTileState = STATE_IN_QUEUE;
-               if (mDecodeQueue.push(tile)) {
-                   mQueueLock.notifyAll();
-               }
-           }
-       }
-    }
-
-    private void decodeTile(Tile tile) {
-        synchronized (mQueueLock) {
-            if (tile.mTileState != STATE_IN_QUEUE) {
-                return;
-            }
-            tile.mTileState = STATE_DECODING;
-        }
-        boolean decodeComplete = tile.decode();
-        synchronized (mQueueLock) {
-            if (tile.mTileState == STATE_RECYCLING) {
-                tile.mTileState = STATE_RECYCLED;
-                if (tile.mDecodedTile != null) {
-                    sTilePool.release(tile.mDecodedTile);
-                    tile.mDecodedTile = null;
-                }
-                mRecycledQueue.push(tile);
-                return;
-            }
-            tile.mTileState = decodeComplete ? STATE_DECODED : STATE_DECODE_FAIL;
-            if (!decodeComplete) {
-                return;
-            }
-            mUploadQueue.push(tile);
-        }
-        invalidate();
-    }
-
-    private Tile obtainTile(int x, int y, int level) {
-        synchronized (mQueueLock) {
-            Tile tile = mRecycledQueue.pop();
-            if (tile != null) {
-                tile.mTileState = STATE_ACTIVATED;
-                tile.update(x, y, level);
-                return tile;
-            }
-            return new Tile(x, y, level);
-        }
-    }
-
-    private void recycleTile(Tile tile) {
-        synchronized (mQueueLock) {
-            if (tile.mTileState == STATE_DECODING) {
-                tile.mTileState = STATE_RECYCLING;
-                return;
-            }
-            tile.mTileState = STATE_RECYCLED;
-            if (tile.mDecodedTile != null) {
-                sTilePool.release(tile.mDecodedTile);
-                tile.mDecodedTile = null;
-            }
-            mRecycledQueue.push(tile);
-        }
-    }
-
-    private void activateTile(int x, int y, int level) {
-        long key = makeTileKey(x, y, level);
-        Tile tile = mActiveTiles.get(key);
-        if (tile != null) {
-            if (tile.mTileState == STATE_IN_QUEUE) {
-                tile.mTileState = STATE_ACTIVATED;
-            }
-            return;
-        }
-        tile = obtainTile(x, y, level);
-        mActiveTiles.put(key, tile);
-    }
-
-    private Tile getTile(int x, int y, int level) {
-        return mActiveTiles.get(makeTileKey(x, y, level));
-    }
-
-    private static long makeTileKey(int x, int y, int level) {
-        long result = x;
-        result = (result << 16) | y;
-        result = (result << 16) | level;
-        return result;
-    }
-
-    private void uploadTiles(GLCanvas canvas) {
-        int quota = UPLOAD_LIMIT;
-        Tile tile = null;
-        while (quota > 0) {
-            synchronized (mQueueLock) {
-                tile = mUploadQueue.pop();
-            }
-            if (tile == null) {
-                break;
-            }
-            if (!tile.isContentValid()) {
-                if (tile.mTileState == STATE_DECODED) {
-                    tile.updateContent(canvas);
-                    --quota;
-                } else {
-                    Log.w(TAG, "Tile in upload queue has invalid state: " + tile.mTileState);
-                }
-            }
-        }
-        if (tile != null) {
-            invalidate();
-        }
-    }
-
-    // Draw the tile to a square at canvas that locates at (x, y) and
-    // has a side length of length.
-    private void drawTile(GLCanvas canvas,
-            int tx, int ty, int level, float x, float y, float length) {
-        RectF source = mSourceRect;
-        RectF target = mTargetRect;
-        target.set(x, y, x + length, y + length);
-        source.set(0, 0, mTileSize, mTileSize);
-
-        Tile tile = getTile(tx, ty, level);
-        if (tile != null) {
-            if (!tile.isContentValid()) {
-                if (tile.mTileState == STATE_DECODED) {
-                    if (mUploadQuota > 0) {
-                        --mUploadQuota;
-                        tile.updateContent(canvas);
-                    } else {
-                        mRenderComplete = false;
-                    }
-                } else if (tile.mTileState != STATE_DECODE_FAIL){
-                    mRenderComplete = false;
-                    queueForDecode(tile);
-                }
-            }
-            if (drawTile(tile, canvas, source, target)) {
-                return;
-            }
-        }
-        if (mPreview != null) {
-            int size = mTileSize << level;
-            float scaleX = (float) mPreview.getWidth() / mImageWidth;
-            float scaleY = (float) mPreview.getHeight() / mImageHeight;
-            source.set(tx * scaleX, ty * scaleY, (tx + size) * scaleX,
-                    (ty + size) * scaleY);
-            canvas.drawTexture(mPreview, source, target);
-        }
-    }
-
-    private boolean drawTile(
-            Tile tile, GLCanvas canvas, RectF source, RectF target) {
-        while (true) {
-            if (tile.isContentValid()) {
-                canvas.drawTexture(tile, source, target);
-                return true;
-            }
-
-            // Parent can be divided to four quads and tile is one of the four.
-            Tile parent = tile.getParentTile();
-            if (parent == null) {
-                return false;
-            }
-            if (tile.mX == parent.mX) {
-                source.left /= 2f;
-                source.right /= 2f;
-            } else {
-                source.left = (mTileSize + source.left) / 2f;
-                source.right = (mTileSize + source.right) / 2f;
-            }
-            if (tile.mY == parent.mY) {
-                source.top /= 2f;
-                source.bottom /= 2f;
-            } else {
-                source.top = (mTileSize + source.top) / 2f;
-                source.bottom = (mTileSize + source.bottom) / 2f;
-            }
-            tile = parent;
-        }
-    }
-
-    private class Tile extends UploadedTexture {
-        public int mX;
-        public int mY;
-        public int mTileLevel;
-        public Tile mNext;
-        public Bitmap mDecodedTile;
-        public volatile int mTileState = STATE_ACTIVATED;
-
-        public Tile(int x, int y, int level) {
-            mX = x;
-            mY = y;
-            mTileLevel = level;
-        }
-
-        @Override
-        protected void onFreeBitmap(Bitmap bitmap) {
-            sTilePool.release(bitmap);
-        }
-
-        boolean decode() {
-            // Get a tile from the original image. The tile is down-scaled
-            // by (1 << mTilelevel) from a region in the original image.
-            try {
-                Bitmap reuse = sTilePool.acquire();
-                if (reuse != null && reuse.getWidth() != mTileSize) {
-                    reuse = null;
-                }
-                mDecodedTile = mModel.getTile(mTileLevel, mX, mY, reuse);
-            } catch (Throwable t) {
-                Log.w(TAG, "fail to decode tile", t);
-            }
-            return mDecodedTile != null;
-        }
-
-        @Override
-        protected Bitmap onGetBitmap() {
-            Utils.assertTrue(mTileState == STATE_DECODED);
-
-            // We need to override the width and height, so that we won't
-            // draw beyond the boundaries.
-            int rightEdge = ((mImageWidth - mX) >> mTileLevel);
-            int bottomEdge = ((mImageHeight - mY) >> mTileLevel);
-            setSize(Math.min(mTileSize, rightEdge), Math.min(mTileSize, bottomEdge));
-
-            Bitmap bitmap = mDecodedTile;
-            mDecodedTile = null;
-            mTileState = STATE_ACTIVATED;
-            return bitmap;
-        }
-
-        // We override getTextureWidth() and getTextureHeight() here, so the
-        // texture can be re-used for different tiles regardless of the actual
-        // size of the tile (which may be small because it is a tile at the
-        // boundary).
-        @Override
-        public int getTextureWidth() {
-            return mTileSize;
-        }
-
-        @Override
-        public int getTextureHeight() {
-            return mTileSize;
-        }
-
-        public void update(int x, int y, int level) {
-            mX = x;
-            mY = y;
-            mTileLevel = level;
-            invalidateContent();
-        }
-
-        public Tile getParentTile() {
-            if (mTileLevel + 1 == mLevelCount) {
-                return null;
-            }
-            int size = mTileSize << (mTileLevel + 1);
-            int x = size * (mX / size);
-            int y = size * (mY / size);
-            return getTile(x, y, mTileLevel + 1);
-        }
-
-        @Override
-        public String toString() {
-            return String.format("tile(%s, %s, %s / %s)",
-                    mX / mTileSize, mY / mTileSize, mLevel, mLevelCount);
-        }
-    }
-
-    private static class TileQueue {
-        private Tile mHead;
-
-        public Tile pop() {
-            Tile tile = mHead;
-            if (tile != null) {
-                mHead = tile.mNext;
-            }
-            return tile;
-        }
-
-        public boolean push(Tile tile) {
-            if (contains(tile)) {
-                Log.w(TAG, "Attempting to add a tile already in the queue!");
-                return false;
-            }
-            boolean wasEmpty = mHead == null;
-            tile.mNext = mHead;
-            mHead = tile;
-            return wasEmpty;
-        }
-
-        private boolean contains(Tile tile) {
-            Tile other = mHead;
-            while (other != null) {
-                if (other == tile) {
-                    return true;
-                }
-                other = other.mNext;
-            }
-            return false;
-        }
-
-        public void clean() {
-            mHead = null;
-        }
-    }
-
-    private class TileDecoder extends Thread {
-
-        public void finishAndWait() {
-            interrupt();
-            try {
-                join();
-            } catch (InterruptedException e) {
-                Log.w(TAG, "Interrupted while waiting for TileDecoder thread to finish!");
-            }
-        }
-
-        private Tile waitForTile() throws InterruptedException {
-            synchronized (mQueueLock) {
-                while (true) {
-                    Tile tile = mDecodeQueue.pop();
-                    if (tile != null) {
-                        return tile;
-                    }
-                    mQueueLock.wait();
-                }
-            }
-        }
-
-        @Override
-        public void run() {
-            try {
-                while (!isInterrupted()) {
-                    Tile tile = waitForTile();
-                    decodeTile(tile);
-                }
-            } catch (InterruptedException ex) {
-                // We were finished
-            }
-        }
-
-    }
-}
diff --git a/src/com/android/photos/views/TiledImageView.java b/src/com/android/photos/views/TiledImageView.java
deleted file mode 100644
index 8bc07c0..0000000
--- a/src/com/android/photos/views/TiledImageView.java
+++ /dev/null
@@ -1,382 +0,0 @@
-/*
- * Copyright (C) 2013 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.photos.views;
-
-import android.annotation.SuppressLint;
-import android.annotation.TargetApi;
-import android.content.Context;
-import android.graphics.Bitmap;
-import android.graphics.Canvas;
-import android.graphics.Color;
-import android.graphics.Matrix;
-import android.graphics.Paint;
-import android.graphics.Paint.Align;
-import android.graphics.RectF;
-import android.opengl.GLSurfaceView;
-import android.opengl.GLSurfaceView.Renderer;
-import android.os.Build;
-import android.util.AttributeSet;
-import android.view.Choreographer;
-import android.view.Choreographer.FrameCallback;
-import android.view.View;
-import android.widget.FrameLayout;
-
-import com.android.gallery3d.glrenderer.BasicTexture;
-import com.android.gallery3d.glrenderer.GLES20Canvas;
-import com.android.photos.views.TiledImageRenderer.TileSource;
-
-import javax.microedition.khronos.egl.EGLConfig;
-import javax.microedition.khronos.opengles.GL10;
-
-/**
- * Shows an image using {@link TiledImageRenderer} using either {@link GLSurfaceView}
- * or {@link BlockingGLTextureView}.
- */
-public class TiledImageView extends FrameLayout {
-
-    private static final boolean USE_TEXTURE_VIEW = false;
-    private static final boolean IS_SUPPORTED =
-            Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN;
-    private static final boolean USE_CHOREOGRAPHER =
-            Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN;
-
-    private BlockingGLTextureView mTextureView;
-    private GLSurfaceView mGLSurfaceView;
-    private boolean mInvalPending = false;
-    private FrameCallback mFrameCallback;
-
-    private static class ImageRendererWrapper {
-        // Guarded by locks
-        float scale;
-        int centerX, centerY;
-        int rotation;
-        TileSource source;
-        Runnable isReadyCallback;
-
-        // GL thread only
-        TiledImageRenderer image;
-    }
-
-    private float[] mValues = new float[9];
-
-    // -------------------------
-    // Guarded by mLock
-    // -------------------------
-    private Object mLock = new Object();
-    private ImageRendererWrapper mRenderer;
-
-    public TiledImageView(Context context) {
-        this(context, null);
-    }
-
-    public TiledImageView(Context context, AttributeSet attrs) {
-        super(context, attrs);
-        if (!IS_SUPPORTED) {
-            return;
-        }
-
-        mRenderer = new ImageRendererWrapper();
-        mRenderer.image = new TiledImageRenderer(this);
-        View view;
-        if (USE_TEXTURE_VIEW) {
-            mTextureView = new BlockingGLTextureView(context);
-            mTextureView.setRenderer(new TileRenderer());
-            view = mTextureView;
-        } else {
-            mGLSurfaceView = new GLSurfaceView(context);
-            mGLSurfaceView.setEGLContextClientVersion(2);
-            mGLSurfaceView.setRenderer(new TileRenderer());
-            mGLSurfaceView.setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY);
-            view = mGLSurfaceView;
-        }
-        addView(view, new LayoutParams(
-                LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
-        //setTileSource(new ColoredTiles());
-    }
-
-    public void destroy() {
-        if (!IS_SUPPORTED) {
-            return;
-        }
-        if (USE_TEXTURE_VIEW) {
-            mTextureView.destroy();
-        } else {
-            mGLSurfaceView.queueEvent(mFreeTextures);
-        }
-    }
-
-    private Runnable mFreeTextures = new Runnable() {
-
-        @Override
-        public void run() {
-            mRenderer.image.freeTextures();
-        }
-    };
-
-    public void onPause() {
-        if (!IS_SUPPORTED) {
-            return;
-        }
-        if (!USE_TEXTURE_VIEW) {
-            mGLSurfaceView.onPause();
-        }
-    }
-
-    public void onResume() {
-        if (!IS_SUPPORTED) {
-            return;
-        }
-        if (!USE_TEXTURE_VIEW) {
-            mGLSurfaceView.onResume();
-        }
-    }
-
-    public void setTileSource(TileSource source, Runnable isReadyCallback) {
-        if (!IS_SUPPORTED) {
-            return;
-        }
-        synchronized (mLock) {
-            mRenderer.source = source;
-            mRenderer.isReadyCallback = isReadyCallback;
-            mRenderer.centerX = source != null ? source.getImageWidth() / 2 : 0;
-            mRenderer.centerY = source != null ? source.getImageHeight() / 2 : 0;
-            mRenderer.rotation = source != null ? source.getRotation() : 0;
-            mRenderer.scale = 0;
-            updateScaleIfNecessaryLocked(mRenderer);
-        }
-        invalidate();
-    }
-
-    @Override
-    protected void onLayout(boolean changed, int left, int top, int right,
-            int bottom) {
-        super.onLayout(changed, left, top, right, bottom);
-        if (!IS_SUPPORTED) {
-            return;
-        }
-        synchronized (mLock) {
-            updateScaleIfNecessaryLocked(mRenderer);
-        }
-    }
-
-    private void updateScaleIfNecessaryLocked(ImageRendererWrapper renderer) {
-        if (renderer == null || renderer.source == null
-                || renderer.scale > 0 || getWidth() == 0) {
-            return;
-        }
-        renderer.scale = Math.min(
-                (float) getWidth() / (float) renderer.source.getImageWidth(),
-                (float) getHeight() / (float) renderer.source.getImageHeight());
-    }
-
-    @Override
-    protected void dispatchDraw(Canvas canvas) {
-        if (!IS_SUPPORTED) {
-            return;
-        }
-        if (USE_TEXTURE_VIEW) {
-            mTextureView.render();
-        }
-        super.dispatchDraw(canvas);
-    }
-
-    @SuppressLint("NewApi")
-    @Override
-    public void setTranslationX(float translationX) {
-        if (!IS_SUPPORTED) {
-            return;
-        }
-        super.setTranslationX(translationX);
-    }
-
-    @Override
-    public void invalidate() {
-        if (!IS_SUPPORTED) {
-            return;
-        }
-        if (USE_TEXTURE_VIEW) {
-            super.invalidate();
-            mTextureView.invalidate();
-        } else {
-            if (USE_CHOREOGRAPHER) {
-                invalOnVsync();
-            } else {
-                mGLSurfaceView.requestRender();
-            }
-        }
-    }
-
-    @TargetApi(Build.VERSION_CODES.JELLY_BEAN)
-    private void invalOnVsync() {
-        if (!mInvalPending) {
-            mInvalPending = true;
-            if (mFrameCallback == null) {
-                mFrameCallback = new FrameCallback() {
-                    @Override
-                    public void doFrame(long frameTimeNanos) {
-                        mInvalPending = false;
-                        mGLSurfaceView.requestRender();
-                    }
-                };
-            }
-            Choreographer.getInstance().postFrameCallback(mFrameCallback);
-        }
-    }
-
-    private RectF mTempRectF = new RectF();
-    public void positionFromMatrix(Matrix matrix) {
-        if (!IS_SUPPORTED) {
-            return;
-        }
-        if (mRenderer.source != null) {
-            final int rotation = mRenderer.source.getRotation();
-            final boolean swap = !(rotation % 180 == 0);
-            final int width = swap ? mRenderer.source.getImageHeight()
-                    : mRenderer.source.getImageWidth();
-            final int height = swap ? mRenderer.source.getImageWidth()
-                    : mRenderer.source.getImageHeight();
-            mTempRectF.set(0, 0, width, height);
-            matrix.mapRect(mTempRectF);
-            matrix.getValues(mValues);
-            int cx = width / 2;
-            int cy = height / 2;
-            float scale = mValues[Matrix.MSCALE_X];
-            int xoffset = Math.round((getWidth() - mTempRectF.width()) / 2 / scale);
-            int yoffset = Math.round((getHeight() - mTempRectF.height()) / 2 / scale);
-            if (rotation == 90 || rotation == 180) {
-                cx += (mTempRectF.left / scale) - xoffset;
-            } else {
-                cx -= (mTempRectF.left / scale) - xoffset;
-            }
-            if (rotation == 180 || rotation == 270) {
-                cy += (mTempRectF.top / scale) - yoffset;
-            } else {
-                cy -= (mTempRectF.top / scale) - yoffset;
-            }
-            mRenderer.scale = scale;
-            mRenderer.centerX = swap ? cy : cx;
-            mRenderer.centerY = swap ? cx : cy;
-            invalidate();
-        }
-    }
-
-    private class TileRenderer implements Renderer {
-
-        private GLES20Canvas mCanvas;
-
-        @Override
-        public void onSurfaceCreated(GL10 gl, EGLConfig config) {
-            mCanvas = new GLES20Canvas();
-            BasicTexture.invalidateAllTextures();
-            mRenderer.image.setModel(mRenderer.source, mRenderer.rotation);
-        }
-
-        @Override
-        public void onSurfaceChanged(GL10 gl, int width, int height) {
-            mCanvas.setSize(width, height);
-            mRenderer.image.setViewSize(width, height);
-        }
-
-        @Override
-        public void onDrawFrame(GL10 gl) {
-            mCanvas.clearBuffer();
-            Runnable readyCallback;
-            synchronized (mLock) {
-                readyCallback = mRenderer.isReadyCallback;
-                mRenderer.image.setModel(mRenderer.source, mRenderer.rotation);
-                mRenderer.image.setPosition(mRenderer.centerX, mRenderer.centerY,
-                        mRenderer.scale);
-            }
-            boolean complete = mRenderer.image.draw(mCanvas);
-            if (complete && readyCallback != null) {
-                synchronized (mLock) {
-                    // Make sure we don't trample on a newly set callback/source
-                    // if it changed while we were rendering
-                    if (mRenderer.isReadyCallback == readyCallback) {
-                        mRenderer.isReadyCallback = null;
-                    }
-                }
-                if (readyCallback != null) {
-                    post(readyCallback);
-                }
-            }
-        }
-
-    }
-
-    @SuppressWarnings("unused")
-    private static class ColoredTiles implements TileSource {
-        private static final int[] COLORS = new int[] {
-            Color.RED,
-            Color.BLUE,
-            Color.YELLOW,
-            Color.GREEN,
-            Color.CYAN,
-            Color.MAGENTA,
-            Color.WHITE,
-        };
-
-        private Paint mPaint = new Paint();
-        private Canvas mCanvas = new Canvas();
-
-        @Override
-        public int getTileSize() {
-            return 256;
-        }
-
-        @Override
-        public int getImageWidth() {
-            return 16384;
-        }
-
-        @Override
-        public int getImageHeight() {
-            return 8192;
-        }
-
-        @Override
-        public int getRotation() {
-            return 0;
-        }
-
-        @Override
-        public Bitmap getTile(int level, int x, int y, Bitmap bitmap) {
-            int tileSize = getTileSize();
-            if (bitmap == null) {
-                bitmap = Bitmap.createBitmap(tileSize, tileSize,
-                        Bitmap.Config.ARGB_8888);
-            }
-            mCanvas.setBitmap(bitmap);
-            mCanvas.drawColor(COLORS[level]);
-            mPaint.setColor(Color.BLACK);
-            mPaint.setTextSize(20);
-            mPaint.setTextAlign(Align.CENTER);
-            mCanvas.drawText(x + "x" + y, 128, 128, mPaint);
-            tileSize <<= level;
-            x /= tileSize;
-            y /= tileSize;
-            mCanvas.drawText(x + "x" + y + " @ " + level, 128, 30, mPaint);
-            mCanvas.setBitmap(null);
-            return bitmap;
-        }
-
-        @Override
-        public BasicTexture getPreview() {
-            return null;
-        }
-    }
-}
diff --git a/src_pd/com/android/camera/PanoramaStitchingManager.java b/src_pd/com/android/camera/PanoramaStitchingManager.java
index 5ba16b8..48f67ce 100644
--- a/src_pd/com/android/camera/PanoramaStitchingManager.java
+++ b/src_pd/com/android/camera/PanoramaStitchingManager.java
@@ -1,19 +1,3 @@
-/*
- * Copyright (C) 2013 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.content.Context;
diff --git a/src_pd/com/android/camera/app/StitchingProgressManager.java b/src_pd/com/android/camera/app/StitchingProgressManager.java
new file mode 100644
index 0000000..a9b796a
--- /dev/null
+++ b/src_pd/com/android/camera/app/StitchingProgressManager.java
@@ -0,0 +1,21 @@
+package com.android.camera.app;
+
+import android.content.Context;
+import android.net.Uri;
+
+import com.android.camera.support.app.StitchingChangeListener;
+
+public class StitchingProgressManager {
+    public StitchingProgressManager(Context app) {
+    }
+
+    public void addChangeListener(StitchingChangeListener l) {
+    }
+
+    public void removeChangeListener(StitchingChangeListener l) {
+    }
+
+    public Integer getProgress(Uri uri) {
+        return null;
+    }
+}
diff --git a/src_pd/com/android/camera/util/HelpUtils.java b/src_pd/com/android/camera/util/HelpUtils.java
new file mode 100644
index 0000000..2ed3dca
--- /dev/null
+++ b/src_pd/com/android/camera/util/HelpUtils.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2013 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.util;
+
+import android.content.Context;
+import android.content.Intent;
+
+public class HelpUtils {
+
+    public static Intent getHelpIntent(Context context) {
+		return null;
+	}
+
+}
diff --git a/src_pd/com/android/camera/util/PhotoSphereHelper.java b/src_pd/com/android/camera/util/PhotoSphereHelper.java
new file mode 100644
index 0000000..570e95f
--- /dev/null
+++ b/src_pd/com/android/camera/util/PhotoSphereHelper.java
@@ -0,0 +1,84 @@
+package com.android.camera.util;
+
+
+import android.app.Activity;
+import android.content.ContentResolver;
+import android.content.Context;
+import android.content.Intent;
+import android.net.Uri;
+
+import com.android.camera.CameraModule;
+import com.android.camera.app.StitchingProgressManager;
+
+public class PhotoSphereHelper {
+    public static class PanoramaMetadata {
+        // Whether a panorama viewer should be used
+        public final boolean mUsePanoramaViewer;
+        // Whether a panorama is 360 degrees
+        public final boolean mIsPanorama360;
+
+        public PanoramaMetadata(boolean usePanoramaViewer, boolean isPanorama360) {
+            mUsePanoramaViewer = usePanoramaViewer;
+            mIsPanorama360 = isPanorama360;
+        }
+    }
+
+    public static class PanoramaViewHelper {
+
+        public PanoramaViewHelper(Activity activity) {
+            /* Do nothing */
+        }
+
+        public void onStart() {
+            /* Do nothing */
+        }
+
+        public void onCreate() {
+            /* Do nothing */
+        }
+
+        public void onStop() {
+            /* Do nothing */
+        }
+
+        public void showPanorama(Uri uri) {
+            /* Do nothing */
+        }
+    }
+
+    public static final PanoramaMetadata NOT_PANORAMA = new PanoramaMetadata(false, false);
+
+    public static void setupCaptureIntent(Context context, Intent it, String outputDir) {
+        /* Do nothing */
+    }
+
+    public static boolean hasLightCycleCapture(Context context) {
+        return false;
+    }
+
+    public static PanoramaMetadata getPanoramaMetadata(Context context, Uri uri) {
+        return NOT_PANORAMA;
+    }
+
+    public static CameraModule createPanoramaModule() {
+        return null;
+    }
+
+    public static StitchingProgressManager createStitchingManagerInstance(Context context) {
+        return null;
+    }
+
+    /**
+     * Get the file path from a Media storage URI.
+     */
+    public static String getPathFromURI(ContentResolver contentResolver, Uri contentUri) {
+        return null;
+    }
+
+    /**
+     * Get the modified time from a Media storage URI.
+     */
+    public static long getModifiedTimeFromURI(ContentResolver contentResolver, Uri contentUri) {
+        return 0;
+    }
+}
diff --git a/src_pd/com/android/camera/util/RefocusHelper.java b/src_pd/com/android/camera/util/RefocusHelper.java
new file mode 100644
index 0000000..4de7d1a
--- /dev/null
+++ b/src_pd/com/android/camera/util/RefocusHelper.java
@@ -0,0 +1,10 @@
+package com.android.camera.util;
+
+
+import com.android.camera.CameraModule;
+
+public class RefocusHelper {
+    public static CameraModule createRefocusModule() {
+        return null;
+    }
+}
diff --git a/src_pd/com/android/camera/util/UsageStatistics.java b/src_pd/com/android/camera/util/UsageStatistics.java
new file mode 100644
index 0000000..40f74a4
--- /dev/null
+++ b/src_pd/com/android/camera/util/UsageStatistics.java
@@ -0,0 +1,37 @@
+package com.android.camera.util;
+
+import android.content.Context;
+
+public class UsageStatistics {
+
+    public static final String COMPONENT_GALLERY = "Gallery";
+    public static final String COMPONENT_CAMERA = "Camera";
+    public static final String COMPONENT_EDITOR = "Editor";
+    public static final String COMPONENT_IMPORTER = "Importer";
+
+    public static final String TRANSITION_BACK_BUTTON = "BackButton";
+    public static final String TRANSITION_UP_BUTTON = "UpButton";
+    public static final String TRANSITION_PINCH_IN = "PinchIn";
+    public static final String TRANSITION_PINCH_OUT = "PinchOut";
+    public static final String TRANSITION_INTENT = "Intent";
+    public static final String TRANSITION_ITEM_TAP = "ItemTap";
+    public static final String TRANSITION_MENU_TAP = "MenuTap";
+    public static final String TRANSITION_BUTTON_TAP = "ButtonTap";
+    public static final String TRANSITION_SWIPE = "Swipe";
+
+    public static final String ACTION_CAPTURE_START = "CaptureStart";
+    public static final String ACTION_CAPTURE_FAIL = "CaptureFail";
+    public static final String ACTION_CAPTURE_DONE = "CaptureDone";
+    public static final String ACTION_SHARE = "Share";
+
+    public static final String CATEGORY_LIFECYCLE = "AppLifecycle";
+    public static final String CATEGORY_BUTTON_PRESS = "ButtonPress";
+
+    public static final String LIFECYCLE_START = "Start";
+
+    public static void initialize(Context context) {}
+    public static void setPendingTransitionCause(String cause) {}
+    public static void onContentViewChanged(String screenComponent, String screenName) {}
+    public static void onEvent(String category, String action, String label) {};
+    public static void onEvent(String category, String action, String label, long optional_value) {};
+}
diff --git a/src_pd/com/android/gallery3d/app/StitchingProgressManager.java b/src_pd/com/android/gallery3d/app/StitchingProgressManager.java
deleted file mode 100644
index 7386847..0000000
--- a/src_pd/com/android/gallery3d/app/StitchingProgressManager.java
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * 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.gallery3d.app;
-
-import android.net.Uri;
-
-public class StitchingProgressManager {
-    public StitchingProgressManager(GalleryApp app) {
-    }
-
-    public void addChangeListener(StitchingChangeListener l) {
-    }
-
-    public void removeChangeListener(StitchingChangeListener l) {
-    }
-
-    public Integer getProgress(Uri uri) {
-        return null;
-    }
-}
diff --git a/src_pd/com/android/gallery3d/filtershow/editors/EditorManager.java b/src_pd/com/android/gallery3d/filtershow/editors/EditorManager.java
deleted file mode 100644
index 3266425..0000000
--- a/src_pd/com/android/gallery3d/filtershow/editors/EditorManager.java
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * 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.gallery3d.filtershow.editors;
-
-import com.android.gallery3d.filtershow.EditorPlaceHolder;
-import com.android.gallery3d.filtershow.editors.BasicEditor;
-import com.android.gallery3d.filtershow.editors.EditorCurves;
-import com.android.gallery3d.filtershow.editors.EditorZoom;
-
-public class EditorManager {
-
-    public static void addEditors(EditorPlaceHolder editorPlaceHolder) {
-        editorPlaceHolder.addEditor(new EditorGrad());
-        editorPlaceHolder.addEditor(new EditorChanSat());
-        editorPlaceHolder.addEditor(new EditorZoom());
-        editorPlaceHolder.addEditor(new EditorCurves());
-        editorPlaceHolder.addEditor(new EditorTinyPlanet());
-        editorPlaceHolder.addEditor(new EditorDraw());
-        editorPlaceHolder.addEditor(new EditorVignette());
-        editorPlaceHolder.addEditor(new EditorMirror());
-        editorPlaceHolder.addEditor(new EditorRotate());
-        editorPlaceHolder.addEditor(new EditorStraighten());
-        editorPlaceHolder.addEditor(new EditorCrop());
-    }
-
-}
diff --git a/src_pd/com/android/gallery3d/filtershow/filters/FiltersManager.java b/src_pd/com/android/gallery3d/filtershow/filters/FiltersManager.java
deleted file mode 100644
index 66372c2..0000000
--- a/src_pd/com/android/gallery3d/filtershow/filters/FiltersManager.java
+++ /dev/null
@@ -1,141 +0,0 @@
-/*
- * Copyright (C) 2013 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.gallery3d.filtershow.filters;
-
-import android.content.Context;
-import android.content.res.Resources;
-import android.graphics.Color;
-
-import com.android.gallery3d.R;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.Vector;
-
-public class FiltersManager extends BaseFiltersManager {
-    private static FiltersManager sInstance = null;
-    private static FiltersManager sPreviewInstance = null;
-    private static FiltersManager sHighresInstance = null;
-    private static int mImageBorderSize = 4; // in percent
-    public FiltersManager() {
-        init();
-    }
-
-    public static FiltersManager getPreviewManager() {
-        if (sPreviewInstance == null) {
-            sPreviewInstance = new FiltersManager();
-        }
-        return sPreviewInstance;
-    }
-
-    public static FiltersManager getManager() {
-        if (sInstance == null) {
-            sInstance = new FiltersManager();
-        }
-        return sInstance;
-    }
-
-    @Override
-    public void addBorders(Context context) {
-
-        // Do not localize
-        String[] serializationNames = {
-                "FRAME_4X5",
-                "FRAME_BRUSH",
-                "FRAME_GRUNGE",
-                "FRAME_SUMI_E",
-                "FRAME_TAPE",
-                "FRAME_BLACK",
-                "FRAME_BLACK_ROUNDED",
-                "FRAME_WHITE",
-                "FRAME_WHITE_ROUNDED",
-                "FRAME_CREAM",
-                "FRAME_CREAM_ROUNDED"
-        };
-
-        // The "no border" implementation
-        int i = 0;
-        FilterRepresentation rep = new FilterImageBorderRepresentation(0);
-        mBorders.add(rep);
-
-        // Regular borders
-        ArrayList <FilterRepresentation> borderList = new ArrayList<FilterRepresentation>();
-
-
-        rep = new FilterImageBorderRepresentation(R.drawable.filtershow_border_4x5);
-        borderList.add(rep);
-
-        rep = new FilterImageBorderRepresentation(R.drawable.filtershow_border_brush);
-        borderList.add(rep);
-
-        rep = new FilterImageBorderRepresentation(R.drawable.filtershow_border_grunge);
-        borderList.add(rep);
-
-        rep = new FilterImageBorderRepresentation(R.drawable.filtershow_border_sumi_e);
-        borderList.add(rep);
-
-        rep = new FilterImageBorderRepresentation(R.drawable.filtershow_border_tape);
-        borderList.add(rep);
-
-        rep = new FilterColorBorderRepresentation(Color.BLACK, mImageBorderSize, 0);
-        borderList.add(rep);
-
-        rep = new FilterColorBorderRepresentation(Color.BLACK, mImageBorderSize,
-                mImageBorderSize);
-        borderList.add(rep);
-
-        rep = new FilterColorBorderRepresentation(Color.WHITE, mImageBorderSize, 0);
-        borderList.add(rep);
-
-        rep = new FilterColorBorderRepresentation(Color.WHITE, mImageBorderSize,
-                mImageBorderSize);
-        borderList.add(rep);
-
-        int creamColor = Color.argb(255, 237, 237, 227);
-        rep = new FilterColorBorderRepresentation(creamColor, mImageBorderSize, 0);
-        borderList.add(rep);
-
-        rep = new FilterColorBorderRepresentation(creamColor, mImageBorderSize,
-                mImageBorderSize);
-        borderList.add(rep);
-
-        for (FilterRepresentation filter : borderList) {
-            filter.setSerializationName(serializationNames[i++]);
-            addRepresentation(filter);
-        }
-
-    }
-
-    public static FiltersManager getHighresManager() {
-        if (sHighresInstance == null) {
-            sHighresInstance = new FiltersManager();
-        }
-        return sHighresInstance;
-    }
-
-    public static void reset() {
-        sInstance = null;
-        sPreviewInstance = null;
-        sHighresInstance = null;
-    }
-
-    public static void setResources(Resources resources) {
-        FiltersManager.getManager().setFilterResources(resources);
-        FiltersManager.getPreviewManager().setFilterResources(resources);
-        FiltersManager.getHighresManager().setFilterResources(resources);
-    }
-}
diff --git a/src_pd/com/android/gallery3d/picasasource/PicasaSource.java b/src_pd/com/android/gallery3d/picasasource/PicasaSource.java
deleted file mode 100644
index 5e800e2..0000000
--- a/src_pd/com/android/gallery3d/picasasource/PicasaSource.java
+++ /dev/null
@@ -1,148 +0,0 @@
-/*
- * Copyright (C) 2010 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.gallery3d.picasasource;
-
-import android.app.Activity;
-import android.app.Dialog;
-import android.content.Context;
-import android.os.ParcelFileDescriptor;
-
-import com.android.gallery3d.app.GalleryApp;
-import com.android.gallery3d.data.MediaItem;
-import com.android.gallery3d.data.MediaObject;
-import com.android.gallery3d.data.MediaSet;
-import com.android.gallery3d.data.MediaSource;
-import com.android.gallery3d.data.Path;
-import com.android.gallery3d.data.PathMatcher;
-
-import java.io.FileNotFoundException;
-
-public class PicasaSource extends MediaSource {
-    private static final String TAG = "PicasaSource";
-
-    private static final int NO_MATCH = -1;
-    private static final int IMAGE_MEDIA_ID = 1;
-
-    private static final int PICASA_ALBUMSET = 0;
-    private static final int MAP_BATCH_COUNT = 100;
-
-    private GalleryApp mApplication;
-    private PathMatcher mMatcher;
-
-    public static final Path ALBUM_PATH = Path.fromString("/picasa/all");
-
-    public PicasaSource(GalleryApp application) {
-        super("picasa");
-        mApplication = application;
-        mMatcher = new PathMatcher();
-        mMatcher.add("/picasa/all", PICASA_ALBUMSET);
-        mMatcher.add("/picasa/image", PICASA_ALBUMSET);
-        mMatcher.add("/picasa/video", PICASA_ALBUMSET);
-    }
-
-    private static class EmptyAlbumSet extends MediaSet {
-
-        public EmptyAlbumSet(Path path, long version) {
-            super(path, version);
-        }
-
-        @Override
-        public String getName() {
-            return "picasa";
-        }
-
-        @Override
-        public long reload() {
-            return mDataVersion;
-        }
-    }
-
-    @Override
-    public MediaObject createMediaObject(Path path) {
-        switch (mMatcher.match(path)) {
-            case PICASA_ALBUMSET:
-                return new EmptyAlbumSet(path, MediaObject.nextVersionNumber());
-            default:
-                throw new RuntimeException("bad path: " + path);
-        }
-    }
-
-    public static MediaItem getFaceItem(Context context, MediaItem item, int faceIndex) {
-        throw new UnsupportedOperationException();
-    }
-
-    public static boolean isPicasaImage(MediaObject object) {
-        return false;
-    }
-
-    public static String getImageTitle(MediaObject image) {
-        throw new UnsupportedOperationException();
-    }
-
-    public static int getImageSize(MediaObject image) {
-        throw new UnsupportedOperationException();
-    }
-
-    public static String getContentType(MediaObject image) {
-        throw new UnsupportedOperationException();
-    }
-
-    public static long getDateTaken(MediaObject image) {
-        throw new UnsupportedOperationException();
-    }
-
-    public static double getLatitude(MediaObject image) {
-        throw new UnsupportedOperationException();
-    }
-
-    public static double getLongitude(MediaObject image) {
-        throw new UnsupportedOperationException();
-    }
-
-    public static int getRotation(MediaObject image) {
-        throw new UnsupportedOperationException();
-    }
-
-    public static long getPicasaId(MediaObject image) {
-        throw new UnsupportedOperationException();
-    }
-
-    public static String getUserAccount(Context context, MediaObject image) {
-        throw new UnsupportedOperationException();
-    }
-
-    public static ParcelFileDescriptor openFile(Context context, MediaObject image, String mode)
-            throws FileNotFoundException {
-        throw new UnsupportedOperationException();
-    }
-
-    public static void initialize(Context context) {/*do nothing*/}
-
-    public static void requestSync(Context context) {/*do nothing*/}
-
-    public static void showSignInReminder(Activity context) {/*do nothing*/}
-
-    public static void onPackageAdded(Context context, String packageName) {/*do nothing*/}
-
-    public static void onPackageRemoved(Context context, String packageName) {/*do nothing*/}
-
-    public static void onPackageChanged(Context context, String packageName) {/*do nothing*/}
-
-    public static Dialog getVersionCheckDialog(Activity activity){
-        return null;
-    }
-}
diff --git a/src_pd/com/android/gallery3d/settings/GallerySettings.java b/src_pd/com/android/gallery3d/settings/GallerySettings.java
deleted file mode 100644
index d30d755..0000000
--- a/src_pd/com/android/gallery3d/settings/GallerySettings.java
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * Copyright (C) 2011 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.gallery3d.settings;
-
-import android.preference.PreferenceActivity;
-
-public class GallerySettings extends PreferenceActivity {
-    private static final String TAG = "GallerySettings";
-}
diff --git a/src_pd/com/android/gallery3d/util/HelpUtils.java b/src_pd/com/android/gallery3d/util/HelpUtils.java
deleted file mode 100644
index 7da3fca..0000000
--- a/src_pd/com/android/gallery3d/util/HelpUtils.java
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Copyright (C) 2013 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.gallery3d.util;
-
-import android.content.Context;
-import android.content.Intent;
-
-public class HelpUtils {
-
-    public static Intent getHelpIntent(Context context) {
-		return null;
-	}
-
-}
diff --git a/src_pd/com/android/gallery3d/util/LightCycleHelper.java b/src_pd/com/android/gallery3d/util/LightCycleHelper.java
deleted file mode 100644
index 5cd910f..0000000
--- a/src_pd/com/android/gallery3d/util/LightCycleHelper.java
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
- * 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.gallery3d.util;
-
-import android.app.Activity;
-import android.content.ContentResolver;
-import android.content.Context;
-import android.content.Intent;
-import android.net.Uri;
-
-import com.android.camera.CameraModule;
-import com.android.gallery3d.app.GalleryApp;
-import com.android.gallery3d.app.StitchingProgressManager;
-
-public class LightCycleHelper {
-    public static class PanoramaMetadata {
-        // Whether a panorama viewer should be used
-        public final boolean mUsePanoramaViewer;
-        // Whether a panorama is 360 degrees
-        public final boolean mIsPanorama360;
-
-        public PanoramaMetadata(boolean usePanoramaViewer, boolean isPanorama360) {
-            mUsePanoramaViewer = usePanoramaViewer;
-            mIsPanorama360 = isPanorama360;
-        }
-    }
-
-    public static class PanoramaViewHelper {
-
-        public PanoramaViewHelper(Activity activity) {
-            /* Do nothing */
-        }
-
-        public void onStart() {
-            /* Do nothing */
-        }
-
-        public void onCreate() {
-            /* Do nothing */
-        }
-
-        public void onStop() {
-            /* Do nothing */
-        }
-
-        public void showPanorama(Uri uri) {
-            /* Do nothing */
-        }
-    }
-
-    public static final PanoramaMetadata NOT_PANORAMA = new PanoramaMetadata(false, false);
-
-    public static void setupCaptureIntent(Context context, Intent it, String outputDir) {
-        /* Do nothing */
-    }
-
-    public static boolean hasLightCycleCapture(Context context) {
-        return false;
-    }
-
-    public static PanoramaMetadata getPanoramaMetadata(Context context, Uri uri) {
-        return NOT_PANORAMA;
-    }
-
-    public static CameraModule createPanoramaModule() {
-        return null;
-    }
-
-    public static StitchingProgressManager createStitchingManagerInstance(GalleryApp app) {
-        return null;
-    }
-
-    /**
-     * Get the file path from a Media storage URI.
-     */
-    public static String getPathFromURI(ContentResolver contentResolver, Uri contentUri) {
-        return null;
-    }
-
-    /**
-     * Get the modified time from a Media storage URI.
-     */
-    public static long getModifiedTimeFromURI(ContentResolver contentResolver, Uri contentUri) {
-        return 0;
-    }
-}
diff --git a/src_pd/com/android/gallery3d/util/RefocusHelper.java b/src_pd/com/android/gallery3d/util/RefocusHelper.java
deleted file mode 100644
index 39ded47..0000000
--- a/src_pd/com/android/gallery3d/util/RefocusHelper.java
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * Copyright (C) 2013 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.gallery3d.util;
-
-import com.android.camera.CameraModule;
-
-public class RefocusHelper {
-    public static CameraModule createRefocusModule() {
-        return null;
-    }
-}
diff --git a/src_pd/com/android/gallery3d/util/UsageStatistics.java b/src_pd/com/android/gallery3d/util/UsageStatistics.java
deleted file mode 100644
index 48fc6ae..0000000
--- a/src_pd/com/android/gallery3d/util/UsageStatistics.java
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Copyright (C) 2013 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.gallery3d.util;
-
-import android.content.Context;
-
-public class UsageStatistics {
-
-    public static final String COMPONENT_GALLERY = "Gallery";
-    public static final String COMPONENT_CAMERA = "Camera";
-    public static final String COMPONENT_EDITOR = "Editor";
-    public static final String COMPONENT_IMPORTER = "Importer";
-
-    public static final String TRANSITION_BACK_BUTTON = "BackButton";
-    public static final String TRANSITION_UP_BUTTON = "UpButton";
-    public static final String TRANSITION_PINCH_IN = "PinchIn";
-    public static final String TRANSITION_PINCH_OUT = "PinchOut";
-    public static final String TRANSITION_INTENT = "Intent";
-    public static final String TRANSITION_ITEM_TAP = "ItemTap";
-    public static final String TRANSITION_MENU_TAP = "MenuTap";
-    public static final String TRANSITION_BUTTON_TAP = "ButtonTap";
-    public static final String TRANSITION_SWIPE = "Swipe";
-
-    public static final String ACTION_CAPTURE_START = "CaptureStart";
-    public static final String ACTION_CAPTURE_FAIL = "CaptureFail";
-    public static final String ACTION_CAPTURE_DONE = "CaptureDone";
-    public static final String ACTION_SHARE = "Share";
-
-    public static final String CATEGORY_LIFECYCLE = "AppLifecycle";
-    public static final String CATEGORY_BUTTON_PRESS = "ButtonPress";
-
-    public static final String LIFECYCLE_START = "Start";
-
-    public static void initialize(Context context) {}
-    public static void setPendingTransitionCause(String cause) {}
-    public static void onContentViewChanged(String screenComponent, String screenName) {}
-    public static void onEvent(String category, String action, String label) {};
-    public static void onEvent(String category, String action, String label, long optional_value) {};
-}
diff --git a/src_pd/com/android/gallery3d/util/XmpUtilHelper.java b/src_pd/com/android/gallery3d/util/XmpUtilHelper.java
deleted file mode 100644
index 88b813d..0000000
--- a/src_pd/com/android/gallery3d/util/XmpUtilHelper.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * 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.gallery3d.util;
-
-import com.adobe.xmp.XMPMeta;
-
-import java.io.InputStream;
-
-public class XmpUtilHelper {
-
-    public static XMPMeta extractXMPMeta(InputStream is) {
-        return null;
-    }
-
-    public static boolean writeXMPMeta(String filename, Object meta) {
-        return false;
-    }
-
-}
diff --git a/src_pd/com/android/photos/data/PhotoProviderAuthority.java b/src_pd/com/android/photos/data/PhotoProviderAuthority.java
deleted file mode 100644
index 0ac76cb..0000000
--- a/src_pd/com/android/photos/data/PhotoProviderAuthority.java
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- * Copyright (C) 2013 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.photos.data;
-
-interface PhotoProviderAuthority {
-    public static final String AUTHORITY = "com.android.gallery3d.photoprovider";
-}
diff --git a/tests/AndroidManifest.xml b/tests/AndroidManifest.xml
deleted file mode 100644
index f44156e..0000000
--- a/tests/AndroidManifest.xml
+++ /dev/null
@@ -1,48 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2010 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.
--->
-
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
-    package="com.android.gallery3d.tests">
-
-    <application
-        android:debuggable="true">
-        <uses-library android:name="android.test.runner" />
-    </application>
-
-    <instrumentation android:name="android.test.InstrumentationTestRunner"
-             android:targetPackage="com.android.gallery3d"
-             android:label="Tests for GalleryNew3D application."/>
-
-    <instrumentation android:name="com.android.gallery3d.CameraTestRunner"
-            android:targetPackage="com.android.gallery3d"
-            android:label="Camera continuous test runner"/>
-
-    <instrumentation android:name="com.android.gallery3d.exif.ExifTestRunner"
-            android:targetPackage="com.android.gallery3d"
-            android:label="Tests for ExifParser."/>
-
-    <instrumentation android:name="com.android.gallery3d.jpegstream.JpegStreamTestRunner"
-            android:targetPackage="com.android.gallery3d"
-            android:label="Tests for JpegStream classes."/>
-
-    <instrumentation android:name="com.android.gallery3d.stress.CameraStressTestRunner"
-            android:targetPackage="com.android.gallery3d"
-            android:label="Camera stress test runner"/>
-
-    <instrumentation android:name="com.android.photos.data.DataTestRunner"
-            android:targetPackage="com.android.gallery3d"
-            android:label="Tests for android photo DataProviders."/>
-</manifest>
diff --git a/tests/exiftool_parser/parser.py b/tests/exiftool_parser/parser.py
deleted file mode 100755
index 7df23f1..0000000
--- a/tests/exiftool_parser/parser.py
+++ /dev/null
@@ -1,90 +0,0 @@
-#!/usr/bin/env python
-#
-# This parser parses the output from Phil Harvey's exiftool (version 9.02)
-# and convert it to xml format. It reads exiftool's output from stdin and
-# write the xml format to stdout.
-#
-# In order to get the raw infomation from exiftool, we need to enable the verbose
-# flag (-v2) of exiftool.
-#
-# Usage:
-#      exiftool -v2 img.jpg | ./parser.py >> output.xml
-#
-#
-
-import os
-import sys
-import re
-
-text = sys.stdin.read()
-
-print """<?xml version="1.0" encoding="utf-8"?>"""
-print "<exif>"
-
-# find the following two groups of string:
-#
-# 1. tag:
-#
-# | | | x) name = value
-# | | |     - Tag 0x1234
-#
-# 2. IFD indicator:
-#
-# | | | + [xxx directory with xx entries]
-#
-p = re.compile(
-        "(((?:\| )+)[0-9]*\)(?:(?:.*? = .*?)|(?:.*? \(SubDirectory\) -->))\n.*?- Tag 0x[0-9a-f]{4})" + "|"
-        + "(((?:\| )*)\+ \[.*? directory with [0-9]+ entries]$)"
-        , re.M)
-tags = p.findall(text)
-
-layer = 0
-ifds = []
-
-for s in tags:
-    # IFD indicator
-    if s[2]:
-        l = len(s[3])
-        ifd = s[2][l + 3:].split()[0]
-        new_layer = l / 2 + 1
-        if new_layer > layer:
-            ifds.append(ifd)
-        else:
-            for i in range(layer - new_layer):
-                ifds.pop()
-            ifds[-1] = ifd
-        layer = new_layer
-    else:
-        l = len(s[1])
-        s = s[0]
-        new_layer = l / 2
-        if new_layer < layer:
-            for i in range(layer - new_layer):
-                ifds.pop()
-        layer = new_layer
-
-        # find the ID
-        _id = re.search("0x[0-9a-f]{4}", s)
-        _id = _id.group(0)
-
-        # find the name
-        name = re.search("[0-9]*?\).*?(?:(?: = )|(?: \(SubDirectory\) -->))", s)
-        name = name.group(0).split()[1]
-
-        # find the raw value in the parenthesis
-        value = re.search("\(SubDirectory\) -->", s)
-        if value:
-            value = "NO_VALUE"
-        else:
-            value = re.search("\(.*\)\n", s)
-            if (name != 'Model' and value):
-                value = value.group(0)[1:-2]
-            else:
-                value = re.search("=.*\n", s)
-                value = value.group(0)[2:-1]
-                if "[snip]" in value:
-                    value = "NO_VALUE"
-
-        print ('    <tag ifd="' + ifds[-1] + '" id="'
-            + _id + '" name="' + name +'">' + value + "</tag>")
-print "</exif>"
diff --git a/tests/res/raw/android_lawn.mp4 b/tests/res/raw/android_lawn.mp4
deleted file mode 100644
index bdeffbe..0000000
--- a/tests/res/raw/android_lawn.mp4
+++ /dev/null
Binary files differ
diff --git a/tests/res/raw/galaxy_nexus.jpg b/tests/res/raw/galaxy_nexus.jpg
deleted file mode 100755
index de91df6..0000000
--- a/tests/res/raw/galaxy_nexus.jpg
+++ /dev/null
Binary files differ
diff --git a/tests/res/raw/jpeg_control.jpg b/tests/res/raw/jpeg_control.jpg
deleted file mode 100644
index bb468a7..0000000
--- a/tests/res/raw/jpeg_control.jpg
+++ /dev/null
Binary files differ
diff --git a/tests/res/xml/galaxy_nexus.xml b/tests/res/xml/galaxy_nexus.xml
deleted file mode 100644
index 55dd524..0000000
--- a/tests/res/xml/galaxy_nexus.xml
+++ /dev/null
@@ -1,43 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<exif>
-    <tag ifd="IFD0" id="0x0100" name="ImageWidth">2560</tag>
-    <tag ifd="IFD0" id="0x0101" name="ImageHeight">1920</tag>
-    <tag ifd="IFD0" id="0x010f" name="Make">google</tag>
-    <tag ifd="IFD0" id="0x0110" name="Model">Nexus S</tag>
-    <tag ifd="IFD0" id="0x0112" name="Orientation">1</tag>
-    <tag ifd="IFD0" id="0x0131" name="Software">MASTER</tag>
-    <tag ifd="IFD0" id="0x0132" name="ModifyDate">2012:07:30 16:28:42</tag>
-    <tag ifd="IFD0" id="0x0213" name="YCbCrPositioning">1</tag>
-    <tag ifd="IFD0" id="0x8769" name="ExifOffset">NO_VALUE</tag>
-    <tag ifd="ExifIFD" id="0x829a" name="ExposureTime">1/40</tag>
-    <tag ifd="ExifIFD" id="0x829d" name="FNumber">26/10</tag>
-    <tag ifd="ExifIFD" id="0x8822" name="ExposureProgram">3</tag>
-    <tag ifd="ExifIFD" id="0x8827" name="ISO">100</tag>
-    <tag ifd="ExifIFD" id="0x9000" name="ExifVersion">0220</tag>
-    <tag ifd="ExifIFD" id="0x9003" name="DateTimeOriginal">2012:07:30 16:28:42</tag>
-    <tag ifd="ExifIFD" id="0x9004" name="CreateDate">2012:07:30 16:28:42</tag>
-    <tag ifd="ExifIFD" id="0x9201" name="ShutterSpeedValue">50/10</tag>
-    <tag ifd="ExifIFD" id="0x9202" name="ApertureValue">30/10</tag>
-    <tag ifd="ExifIFD" id="0x9203" name="BrightnessValue">30/10</tag>
-    <tag ifd="ExifIFD" id="0x9204" name="ExposureCompensation">0/0</tag>
-    <tag ifd="ExifIFD" id="0x9205" name="MaxApertureValue">30/10</tag>
-    <tag ifd="ExifIFD" id="0x9207" name="MeteringMode">2</tag>
-    <tag ifd="ExifIFD" id="0x9209" name="Flash">0</tag>
-    <tag ifd="ExifIFD" id="0x920a" name="FocalLength">343/100</tag>
-    <tag ifd="ExifIFD" id="0x9286" name="UserComment">IICSAUser comments</tag>
-    <tag ifd="ExifIFD" id="0xa001" name="ColorSpace">1</tag>
-    <tag ifd="ExifIFD" id="0xa002" name="ExifImageWidth">2560</tag>
-    <tag ifd="ExifIFD" id="0xa003" name="ExifImageHeight">1920</tag>
-    <tag ifd="ExifIFD" id="0xa402" name="ExposureMode">0</tag>
-    <tag ifd="ExifIFD" id="0xa403" name="WhiteBalance">0</tag>
-    <tag ifd="ExifIFD" id="0xa406" name="SceneCaptureType">0</tag>
-    <tag ifd="IFD1" id="0x0100" name="ImageWidth">320</tag>
-    <tag ifd="IFD1" id="0x0101" name="ImageHeight">240</tag>
-    <tag ifd="IFD1" id="0x0103" name="Compression">6</tag>
-    <tag ifd="IFD1" id="0x0112" name="Orientation">1</tag>
-    <tag ifd="IFD1" id="0x011a" name="XResolution">72/1</tag>
-    <tag ifd="IFD1" id="0x011b" name="YResolution">72/1</tag>
-    <tag ifd="IFD1" id="0x0128" name="ResolutionUnit">2</tag>
-    <tag ifd="IFD1" id="0x0201" name="ThumbnailOffset">690</tag>
-    <tag ifd="IFD1" id="0x0202" name="ThumbnailLength">10447</tag>
-</exif>
diff --git a/tests/src/com/android/gallery3d/CameraTestRunner.java b/tests/src/com/android/gallery3d/CameraTestRunner.java
deleted file mode 100755
index 5032336..0000000
--- a/tests/src/com/android/gallery3d/CameraTestRunner.java
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * 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.gallery3d;
-
-import android.test.InstrumentationTestRunner;
-import android.test.InstrumentationTestSuite;
-
-import com.android.gallery3d.functional.CameraTest;
-import com.android.gallery3d.functional.ImageCaptureIntentTest;
-import com.android.gallery3d.functional.VideoCaptureIntentTest;
-import com.android.gallery3d.unittest.CameraUnitTest;
-
-import junit.framework.TestSuite;
-
-
-public class CameraTestRunner extends InstrumentationTestRunner {
-
-    @Override
-    public TestSuite getAllTests() {
-        TestSuite suite = new InstrumentationTestSuite(this);
-        suite.addTestSuite(CameraTest.class);
-        suite.addTestSuite(ImageCaptureIntentTest.class);
-        suite.addTestSuite(VideoCaptureIntentTest.class);
-        suite.addTestSuite(CameraUnitTest.class);
-        return suite;
-    }
-
-    @Override
-    public ClassLoader getLoader() {
-        return CameraTestRunner.class.getClassLoader();
-    }
-}
diff --git a/tests/src/com/android/gallery3d/StressTests.java b/tests/src/com/android/gallery3d/StressTests.java
deleted file mode 100755
index b991e9e..0000000
--- a/tests/src/com/android/gallery3d/StressTests.java
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Copyright (C) 2009 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.gallery3d;
-
-import com.android.gallery3d.stress.CameraLatency;
-import com.android.gallery3d.stress.CameraStartUp;
-import com.android.gallery3d.stress.ImageCapture;
-import com.android.gallery3d.stress.SwitchPreview;
-
-import junit.framework.Test;
-import junit.framework.TestSuite;
-
-
-/**
- * Instrumentation Test Runner for all Camera tests.
- *
- * Running all tests:
- *
- * adb shell am instrument \
- *    -e class com.android.gallery3d.StressTests \
- *    -w com.google.android.gallery3d.tests/com.android.gallery3d.stress.CameraStressTestRunner
- */
-
-public class StressTests extends TestSuite {
-    public static Test suite() {
-        TestSuite result = new TestSuite();
-        result.addTestSuite(CameraLatency.class);
-        result.addTestSuite(CameraStartUp.class);
-        result.addTestSuite(ImageCapture.class);
-//      result.addTestSuite(SwitchPreview.class);
-        return result;
-    }
-}
diff --git a/tests/src/com/android/gallery3d/anim/AnimationTest.java b/tests/src/com/android/gallery3d/anim/AnimationTest.java
deleted file mode 100644
index c7d5dae..0000000
--- a/tests/src/com/android/gallery3d/anim/AnimationTest.java
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * Copyright (C) 2010 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.gallery3d.anim;
-
-import android.test.suitebuilder.annotation.SmallTest;
-import android.util.Log;
-import android.view.animation.Interpolator;
-
-import junit.framework.TestCase;
-
-@SmallTest
-public class AnimationTest extends TestCase {
-    private static final String TAG = "AnimationTest";
-
-    public void testFloatAnimation() {
-        FloatAnimation a = new FloatAnimation(0f, 1f, 10);  // value 0 to 1.0, duration 10
-        a.start();                 // start animation
-        assertTrue(a.isActive());  // should be active now
-        a.calculate(0);            // set start time = 0
-        assertTrue(a.get() == 0);  // start value should be 0
-        a.calculate(1);            // calculate value for time 1
-        assertFloatEq(a.get(), 0.1f);
-        a.calculate(5);            // calculate value for time 5
-        assertTrue(a.get() == 0.5);//
-        a.calculate(9);            // calculate value for time 9
-        assertFloatEq(a.get(), 0.9f);
-        a.calculate(10);           // calculate value for time 10
-        assertTrue(!a.isActive()); // should be inactive now
-        assertTrue(a.get() == 1.0);//
-        a.start();                 // restart
-        assertTrue(a.isActive());  // should be active now
-        a.calculate(5);            // set start time = 5
-        assertTrue(a.get() == 0);  // start value should be 0
-        a.calculate(5+9);          // calculate for time 5+9
-        assertFloatEq(a.get(), 0.9f);
-    }
-
-    private static class MyInterpolator implements Interpolator {
-        public float getInterpolation(float input) {
-            return 4f * (input - 0.5f);  // maps [0,1] to [-2,2]
-        }
-    }
-
-    public void testInterpolator() {
-        FloatAnimation a = new FloatAnimation(0f, 1f, 10);  // value 0 to 1.0, duration 10
-        a.setInterpolator(new MyInterpolator());
-        a.start();                 // start animation
-        a.calculate(0);            // set start time = 0
-        assertTrue(a.get() == -2); // start value should be -2
-        a.calculate(1);            // calculate value for time 1
-        assertFloatEq(a.get(), -1.6f);
-        a.calculate(5);            // calculate value for time 5
-        assertTrue(a.get() == 0);  //
-        a.calculate(9);            // calculate value for time 9
-        assertFloatEq(a.get(), 1.6f);
-        a.calculate(10);           // calculate value for time 10
-        assertTrue(a.get() == 2);  //
-    }
-
-    public static void assertFloatEq(float expected, float actual) {
-        if (Math.abs(actual - expected) > 1e-6) {
-            Log.v(TAG, "expected: " + expected + ", actual: " + actual);
-            fail();
-        }
-    }
-}
diff --git a/tests/src/com/android/gallery3d/common/BlobCacheTest.java b/tests/src/com/android/gallery3d/common/BlobCacheTest.java
deleted file mode 100644
index 2a911c4..0000000
--- a/tests/src/com/android/gallery3d/common/BlobCacheTest.java
+++ /dev/null
@@ -1,738 +0,0 @@
-/*
- * Copyright (C) 2010 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.gallery3d.common;
-
-import com.android.gallery3d.common.BlobCache;
-
-import android.test.AndroidTestCase;
-import android.test.suitebuilder.annotation.SmallTest;
-import android.test.suitebuilder.annotation.MediumTest;
-import android.test.suitebuilder.annotation.LargeTest;
-import android.util.Log;
-
-import java.io.File;
-import java.io.IOException;
-import java.io.RandomAccessFile;
-import java.util.Random;
-
-public class BlobCacheTest extends AndroidTestCase {
-    private static final String TAG = "BlobCacheTest";
-
-    @SmallTest
-    public void testReadIntLong() {
-        byte[] buf = new byte[9];
-        assertEquals(0, BlobCache.readInt(buf, 0));
-        assertEquals(0, BlobCache.readLong(buf, 0));
-        buf[0] = 1;
-        assertEquals(1, BlobCache.readInt(buf, 0));
-        assertEquals(1, BlobCache.readLong(buf, 0));
-        buf[3] = 0x7f;
-        assertEquals(0x7f000001, BlobCache.readInt(buf, 0));
-        assertEquals(0x7f000001, BlobCache.readLong(buf, 0));
-        assertEquals(0x007f0000, BlobCache.readInt(buf, 1));
-        assertEquals(0x007f0000, BlobCache.readLong(buf, 1));
-        buf[3] = (byte) 0x80;
-        buf[7] = (byte) 0xA0;
-        buf[0] = 0;
-        assertEquals(0x80000000, BlobCache.readInt(buf, 0));
-        assertEquals(0xA000000080000000L, BlobCache.readLong(buf, 0));
-        for (int i = 0; i < 8; i++) {
-            buf[i] = (byte) (0x11 * (i+8));
-        }
-        assertEquals(0xbbaa9988, BlobCache.readInt(buf, 0));
-        assertEquals(0xffeeddccbbaa9988L, BlobCache.readLong(buf, 0));
-        buf[8] = 0x33;
-        assertEquals(0x33ffeeddccbbaa99L, BlobCache.readLong(buf, 1));
-    }
-
-    @SmallTest
-    public void testWriteIntLong() {
-        byte[] buf = new byte[8];
-        BlobCache.writeInt(buf, 0, 0x12345678);
-        assertEquals(0x78, buf[0]);
-        assertEquals(0x56, buf[1]);
-        assertEquals(0x34, buf[2]);
-        assertEquals(0x12, buf[3]);
-        assertEquals(0x00, buf[4]);
-        BlobCache.writeLong(buf, 0, 0xffeeddccbbaa9988L);
-        for (int i = 0; i < 8; i++) {
-            assertEquals((byte) (0x11 * (i+8)), buf[i]);
-        }
-    }
-
-    @MediumTest
-    public void testChecksum() throws IOException {
-        BlobCache bc = new BlobCache(TEST_FILE_NAME, MAX_ENTRIES, MAX_BYTES, true);
-        byte[] buf = new byte[0];
-        assertEquals(0x1, bc.checkSum(buf));
-        buf = new byte[1];
-        assertEquals(0x10001, bc.checkSum(buf));
-        buf[0] = 0x47;
-        assertEquals(0x480048, bc.checkSum(buf));
-        buf = new byte[3];
-        buf[0] = 0x10;
-        buf[1] = 0x30;
-        buf[2] = 0x01;
-        assertEquals(0x940042, bc.checkSum(buf));
-        assertEquals(0x310031, bc.checkSum(buf, 1, 1));
-        assertEquals(0x1, bc.checkSum(buf, 1, 0));
-        assertEquals(0x630032, bc.checkSum(buf, 1, 2));
-        buf = new byte[1024];
-        for (int i = 0; i < buf.length; i++) {
-            buf[i] = (byte)(i*i);
-        }
-        assertEquals(0x3574a610, bc.checkSum(buf));
-        bc.close();
-    }
-
-    private static final int HEADER_SIZE = 32;
-    private static final int DATA_HEADER_SIZE = 4;
-    private static final int BLOB_HEADER_SIZE = 20;
-
-    private static final String TEST_FILE_NAME = "/sdcard/btest";
-    private static final int MAX_ENTRIES = 100;
-    private static final int MAX_BYTES = 1000;
-    private static final int INDEX_SIZE = HEADER_SIZE + MAX_ENTRIES * 12 * 2;
-    private static final long KEY_0 = 0x1122334455667788L;
-    private static final long KEY_1 = 0x1122334455667789L;
-    private static final long KEY_2 = 0x112233445566778AL;
-    private static byte[] DATA_0 = new byte[10];
-    private static byte[] DATA_1 = new byte[10];
-
-    @MediumTest
-    public void testBasic() throws IOException {
-        String name = TEST_FILE_NAME;
-        BlobCache bc;
-        File idxFile = new File(name + ".idx");
-        File data0File = new File(name + ".0");
-        File data1File = new File(name + ".1");
-
-        // Create a brand new cache.
-        bc = new BlobCache(name, MAX_ENTRIES, MAX_BYTES, true);
-        bc.close();
-
-        // Make sure the initial state is correct.
-        assertTrue(idxFile.exists());
-        assertTrue(data0File.exists());
-        assertTrue(data1File.exists());
-        assertEquals(INDEX_SIZE, idxFile.length());
-        assertEquals(DATA_HEADER_SIZE, data0File.length());
-        assertEquals(DATA_HEADER_SIZE, data1File.length());
-        assertEquals(0, bc.getActiveCount());
-
-        // Re-open it.
-        bc = new BlobCache(name, MAX_ENTRIES, MAX_BYTES, false);
-        assertNull(bc.lookup(KEY_0));
-
-        // insert one blob
-        genData(DATA_0, 1);
-        bc.insert(KEY_0, DATA_0);
-        assertSameData(DATA_0, bc.lookup(KEY_0));
-        assertEquals(1, bc.getActiveCount());
-        bc.close();
-
-        // Make sure the file size is right.
-        assertEquals(INDEX_SIZE, idxFile.length());
-        assertEquals(DATA_HEADER_SIZE + BLOB_HEADER_SIZE + DATA_0.length,
-                data0File.length());
-        assertEquals(DATA_HEADER_SIZE, data1File.length());
-
-        // Re-open it and make sure we can get the old data
-        bc = new BlobCache(name, MAX_ENTRIES, MAX_BYTES, false);
-        assertSameData(DATA_0, bc.lookup(KEY_0));
-
-        // insert with the same key (but using a different blob)
-        genData(DATA_0, 2);
-        bc.insert(KEY_0, DATA_0);
-        assertSameData(DATA_0, bc.lookup(KEY_0));
-        assertEquals(1, bc.getActiveCount());
-        bc.close();
-
-        // Make sure the file size is right.
-        assertEquals(INDEX_SIZE, idxFile.length());
-        assertEquals(DATA_HEADER_SIZE + 2 * (BLOB_HEADER_SIZE + DATA_0.length),
-                data0File.length());
-        assertEquals(DATA_HEADER_SIZE, data1File.length());
-
-        // Re-open it and make sure we can get the old data
-        bc = new BlobCache(name, MAX_ENTRIES, MAX_BYTES, false);
-        assertSameData(DATA_0, bc.lookup(KEY_0));
-
-        // insert another key and make sure we can get both key.
-        assertNull(bc.lookup(KEY_1));
-        genData(DATA_1, 3);
-        bc.insert(KEY_1, DATA_1);
-        assertSameData(DATA_0, bc.lookup(KEY_0));
-        assertSameData(DATA_1, bc.lookup(KEY_1));
-        assertEquals(2, bc.getActiveCount());
-        bc.close();
-
-        // Make sure the file size is right.
-        assertEquals(INDEX_SIZE, idxFile.length());
-        assertEquals(DATA_HEADER_SIZE + 3 * (BLOB_HEADER_SIZE + DATA_0.length),
-                data0File.length());
-        assertEquals(DATA_HEADER_SIZE, data1File.length());
-
-        // Re-open it and make sure we can get the old data
-        bc = new BlobCache(name, 100, 1000, false);
-        assertSameData(DATA_0, bc.lookup(KEY_0));
-        assertSameData(DATA_1, bc.lookup(KEY_1));
-        assertEquals(2, bc.getActiveCount());
-        bc.close();
-    }
-
-    @MediumTest
-    public void testNegativeKey() throws IOException {
-        BlobCache bc = new BlobCache(TEST_FILE_NAME, MAX_ENTRIES, MAX_BYTES, true);
-
-        // insert one blob
-        genData(DATA_0, 1);
-        bc.insert(-123, DATA_0);
-        assertSameData(DATA_0, bc.lookup(-123));
-        bc.close();
-    }
-
-    @MediumTest
-    public void testEmptyBlob() throws IOException {
-        BlobCache bc = new BlobCache(TEST_FILE_NAME, MAX_ENTRIES, MAX_BYTES, true);
-
-        byte[] data = new byte[0];
-        bc.insert(123, data);
-        assertSameData(data, bc.lookup(123));
-        bc.close();
-    }
-
-    @MediumTest
-    public void testLookupRequest() throws IOException {
-        BlobCache bc = new BlobCache(TEST_FILE_NAME, MAX_ENTRIES, MAX_BYTES, true);
-
-        // insert one blob
-        genData(DATA_0, 1);
-        bc.insert(1, DATA_0);
-        assertSameData(DATA_0, bc.lookup(1));
-
-        // the same size buffer
-        byte[] buf = new byte[DATA_0.length];
-        BlobCache.LookupRequest req = new BlobCache.LookupRequest();
-        req.key = 1;
-        req.buffer = buf;
-        assertTrue(bc.lookup(req));
-        assertEquals(1, req.key);
-        assertSame(buf, req.buffer);
-        assertEquals(DATA_0.length, req.length);
-
-        // larger buffer
-        buf = new byte[DATA_0.length + 22];
-        req = new BlobCache.LookupRequest();
-        req.key = 1;
-        req.buffer = buf;
-        assertTrue(bc.lookup(req));
-        assertEquals(1, req.key);
-        assertSame(buf, req.buffer);
-        assertEquals(DATA_0.length, req.length);
-
-        // smaller buffer
-        buf = new byte[DATA_0.length - 1];
-        req = new BlobCache.LookupRequest();
-        req.key = 1;
-        req.buffer = buf;
-        assertTrue(bc.lookup(req));
-        assertEquals(1, req.key);
-        assertNotSame(buf, req.buffer);
-        assertEquals(DATA_0.length, req.length);
-        assertSameData(DATA_0, req.buffer, DATA_0.length);
-
-        // null buffer
-        req = new BlobCache.LookupRequest();
-        req.key = 1;
-        req.buffer = null;
-        assertTrue(bc.lookup(req));
-        assertEquals(1, req.key);
-        assertNotNull(req.buffer);
-        assertEquals(DATA_0.length, req.length);
-        assertSameData(DATA_0, req.buffer, DATA_0.length);
-
-        bc.close();
-    }
-
-    @MediumTest
-    public void testKeyCollision() throws IOException {
-        BlobCache bc = new BlobCache(TEST_FILE_NAME, MAX_ENTRIES, MAX_BYTES, true);
-
-        for (int i = 0; i < MAX_ENTRIES / 2; i++) {
-            genData(DATA_0, i);
-            long key = KEY_1 + i * MAX_ENTRIES;
-            bc.insert(key, DATA_0);
-        }
-
-        for (int i = 0; i < MAX_ENTRIES / 2; i++) {
-            genData(DATA_0, i);
-            long key = KEY_1 + i * MAX_ENTRIES;
-            assertSameData(DATA_0, bc.lookup(key));
-        }
-        bc.close();
-    }
-
-    @MediumTest
-    public void testRegionFlip() throws IOException {
-        String name = TEST_FILE_NAME;
-        BlobCache bc;
-        File idxFile = new File(name + ".idx");
-        File data0File = new File(name + ".0");
-        File data1File = new File(name + ".1");
-
-        // Create a brand new cache.
-        bc = new BlobCache(name, MAX_ENTRIES, MAX_BYTES, true);
-
-        // This is the number of blobs fits into a region.
-        int maxFit = (MAX_BYTES - DATA_HEADER_SIZE) /
-                (BLOB_HEADER_SIZE + DATA_0.length);
-
-        for (int k = 0; k < maxFit; k++) {
-            genData(DATA_0, k);
-            bc.insert(k, DATA_0);
-        }
-        assertEquals(maxFit, bc.getActiveCount());
-
-        // Make sure the file size is right.
-        assertEquals(INDEX_SIZE, idxFile.length());
-        assertEquals(DATA_HEADER_SIZE + maxFit * (BLOB_HEADER_SIZE + DATA_0.length),
-                data0File.length());
-        assertEquals(DATA_HEADER_SIZE, data1File.length());
-
-        // Now insert another one and let it flip.
-        genData(DATA_0, 777);
-        bc.insert(KEY_1, DATA_0);
-        assertEquals(1, bc.getActiveCount());
-
-        assertEquals(INDEX_SIZE, idxFile.length());
-        assertEquals(DATA_HEADER_SIZE + maxFit * (BLOB_HEADER_SIZE + DATA_0.length),
-                data0File.length());
-        assertEquals(DATA_HEADER_SIZE + 1 * (BLOB_HEADER_SIZE + DATA_0.length),
-                data1File.length());
-
-        // Make sure we can find the new data
-        assertSameData(DATA_0, bc.lookup(KEY_1));
-
-        // Now find an old blob
-        int old = maxFit / 2;
-        genData(DATA_0, old);
-        assertSameData(DATA_0, bc.lookup(old));
-        assertEquals(2, bc.getActiveCount());
-
-        // Observed data is copied.
-        assertEquals(INDEX_SIZE, idxFile.length());
-        assertEquals(DATA_HEADER_SIZE + maxFit * (BLOB_HEADER_SIZE + DATA_0.length),
-                data0File.length());
-        assertEquals(DATA_HEADER_SIZE + 2 * (BLOB_HEADER_SIZE + DATA_0.length),
-                data1File.length());
-
-        // Now copy everything over (except we should have no space for the last one)
-        assertTrue(old < maxFit - 1);
-        for (int k = 0; k < maxFit; k++) {
-            genData(DATA_0, k);
-            assertSameData(DATA_0, bc.lookup(k));
-        }
-        assertEquals(maxFit, bc.getActiveCount());
-
-        // Now both file should be full.
-        assertEquals(INDEX_SIZE, idxFile.length());
-        assertEquals(DATA_HEADER_SIZE + maxFit * (BLOB_HEADER_SIZE + DATA_0.length),
-                data0File.length());
-        assertEquals(DATA_HEADER_SIZE + maxFit * (BLOB_HEADER_SIZE + DATA_0.length),
-                data1File.length());
-
-        // Now insert one to make it flip.
-        genData(DATA_0, 888);
-        bc.insert(KEY_2, DATA_0);
-        assertEquals(1, bc.getActiveCount());
-
-        // Check the size after the second flip.
-        assertEquals(INDEX_SIZE, idxFile.length());
-        assertEquals(DATA_HEADER_SIZE + 1 * (BLOB_HEADER_SIZE + DATA_0.length),
-                data0File.length());
-        assertEquals(DATA_HEADER_SIZE + maxFit * (BLOB_HEADER_SIZE + DATA_0.length),
-                data1File.length());
-
-        // Now the last key should be gone.
-        assertNull(bc.lookup(maxFit - 1));
-
-        // But others should remain
-        for (int k = 0; k < maxFit - 1; k++) {
-            genData(DATA_0, k);
-            assertSameData(DATA_0, bc.lookup(k));
-        }
-
-        assertEquals(maxFit, bc.getActiveCount());
-        genData(DATA_0, 777);
-        assertSameData(DATA_0, bc.lookup(KEY_1));
-        genData(DATA_0, 888);
-        assertSameData(DATA_0, bc.lookup(KEY_2));
-        assertEquals(maxFit, bc.getActiveCount());
-
-        // Now two files should be full.
-        assertEquals(INDEX_SIZE, idxFile.length());
-        assertEquals(DATA_HEADER_SIZE + maxFit * (BLOB_HEADER_SIZE + DATA_0.length),
-                data0File.length());
-        assertEquals(DATA_HEADER_SIZE + maxFit * (BLOB_HEADER_SIZE + DATA_0.length),
-                data1File.length());
-
-        bc.close();
-    }
-
-    @MediumTest
-    public void testEntryLimit() throws IOException {
-        String name = TEST_FILE_NAME;
-        BlobCache bc;
-        File idxFile = new File(name + ".idx");
-        File data0File = new File(name + ".0");
-        File data1File = new File(name + ".1");
-        int maxEntries = 10;
-        int maxFit = maxEntries / 2;
-        int indexSize = HEADER_SIZE + maxEntries * 12 * 2;
-
-        // Create a brand new cache with a small entry limit.
-        bc = new BlobCache(name, maxEntries, MAX_BYTES, true);
-
-        // Fill to just before flipping
-        for (int i = 0; i < maxFit; i++) {
-            genData(DATA_0, i);
-            bc.insert(i, DATA_0);
-        }
-        assertEquals(maxFit, bc.getActiveCount());
-
-        // Check the file size.
-        assertEquals(indexSize, idxFile.length());
-        assertEquals(DATA_HEADER_SIZE + maxFit * (BLOB_HEADER_SIZE + DATA_0.length),
-                data0File.length());
-        assertEquals(DATA_HEADER_SIZE, data1File.length());
-
-        // Insert one and make it flip
-        genData(DATA_0, 777);
-        bc.insert(777, DATA_0);
-        assertEquals(1, bc.getActiveCount());
-
-        // Check the file size.
-        assertEquals(indexSize, idxFile.length());
-        assertEquals(DATA_HEADER_SIZE + maxFit * (BLOB_HEADER_SIZE + DATA_0.length),
-                data0File.length());
-        assertEquals(DATA_HEADER_SIZE + 1 * (BLOB_HEADER_SIZE + DATA_0.length),
-                data1File.length());
-        bc.close();
-    }
-
-    @LargeTest
-    public void testDataIntegrity() throws IOException {
-        String name = TEST_FILE_NAME;
-        File idxFile = new File(name + ".idx");
-        File data0File = new File(name + ".0");
-        File data1File = new File(name + ".1");
-        RandomAccessFile f;
-
-        Log.v(TAG, "It should be readable if the content is not changed.");
-        prepareNewCache();
-        f = new RandomAccessFile(data0File, "rw");
-        f.seek(1);
-        byte b = f.readByte();
-        f.seek(1);
-        f.write(b);
-        f.close();
-        assertReadable();
-
-        Log.v(TAG, "Change the data file magic field");
-        prepareNewCache();
-        f = new RandomAccessFile(data0File, "rw");
-        f.seek(1);
-        f.write(0xFF);
-        f.close();
-        assertUnreadable();
-
-        prepareNewCache();
-        f = new RandomAccessFile(data1File, "rw");
-        f.write(0xFF);
-        f.close();
-        assertUnreadable();
-
-        Log.v(TAG, "Change the blob key");
-        prepareNewCache();
-        f = new RandomAccessFile(data0File, "rw");
-        f.seek(4);
-        f.write(0x00);
-        f.close();
-        assertUnreadable();
-
-        Log.v(TAG, "Change the blob checksum");
-        prepareNewCache();
-        f = new RandomAccessFile(data0File, "rw");
-        f.seek(4 + 8);
-        f.write(0x00);
-        f.close();
-        assertUnreadable();
-
-        Log.v(TAG, "Change the blob offset");
-        prepareNewCache();
-        f = new RandomAccessFile(data0File, "rw");
-        f.seek(4 + 12);
-        f.write(0x20);
-        f.close();
-        assertUnreadable();
-
-        Log.v(TAG, "Change the blob length: some other value");
-        prepareNewCache();
-        f = new RandomAccessFile(data0File, "rw");
-        f.seek(4 + 16);
-        f.write(0x20);
-        f.close();
-        assertUnreadable();
-
-        Log.v(TAG, "Change the blob length: -1");
-        prepareNewCache();
-        f = new RandomAccessFile(data0File, "rw");
-        f.seek(4 + 16);
-        f.writeInt(0xFFFFFFFF);
-        f.close();
-        assertUnreadable();
-
-        Log.v(TAG, "Change the blob length: big value");
-        prepareNewCache();
-        f = new RandomAccessFile(data0File, "rw");
-        f.seek(4 + 16);
-        f.writeInt(0xFFFFFF00);
-        f.close();
-        assertUnreadable();
-
-        Log.v(TAG, "Change the blob content");
-        prepareNewCache();
-        f = new RandomAccessFile(data0File, "rw");
-        f.seek(4 + 20);
-        f.write(0x01);
-        f.close();
-        assertUnreadable();
-
-        Log.v(TAG, "Change the index magic");
-        prepareNewCache();
-        f = new RandomAccessFile(idxFile, "rw");
-        f.seek(1);
-        f.write(0x00);
-        f.close();
-        assertUnreadable();
-
-        Log.v(TAG, "Change the active region");
-        prepareNewCache();
-        f = new RandomAccessFile(idxFile, "rw");
-        f.seek(12);
-        f.write(0x01);
-        f.close();
-        assertUnreadable();
-
-        Log.v(TAG, "Change the reserved data");
-        prepareNewCache();
-        f = new RandomAccessFile(idxFile, "rw");
-        f.seek(24);
-        f.write(0x01);
-        f.close();
-        assertUnreadable();
-
-        Log.v(TAG, "Change the checksum");
-        prepareNewCache();
-        f = new RandomAccessFile(idxFile, "rw");
-        f.seek(29);
-        f.write(0x00);
-        f.close();
-        assertUnreadable();
-
-        Log.v(TAG, "Change the key");
-        prepareNewCache();
-        f = new RandomAccessFile(idxFile, "rw");
-        f.seek(32 + 12 * (KEY_1 % MAX_ENTRIES));
-        f.write(0x00);
-        f.close();
-        assertUnreadable();
-
-        Log.v(TAG, "Change the offset");
-        prepareNewCache();
-        f = new RandomAccessFile(idxFile, "rw");
-        f.seek(32 + 12 * (KEY_1 % MAX_ENTRIES) + 8);
-        f.write(0x05);
-        f.close();
-        assertUnreadable();
-
-        Log.v(TAG, "Change the offset");
-        prepareNewCache();
-        f = new RandomAccessFile(idxFile, "rw");
-        f.seek(32 + 12 * (KEY_1 % MAX_ENTRIES) + 8 + 3);
-        f.write(0xFF);
-        f.close();
-        assertUnreadable();
-
-        Log.v(TAG, "Garbage index");
-        prepareNewCache();
-        f = new RandomAccessFile(idxFile, "rw");
-        int n = (int) idxFile.length();
-        f.seek(32);
-        byte[] garbage = new byte[1024];
-        for (int i = 0; i < garbage.length; i++) {
-            garbage[i] = (byte) 0x80;
-        }
-        int i = 32;
-        while (i < n) {
-            int todo = Math.min(garbage.length, n - i);
-            f.write(garbage, 0, todo);
-            i += todo;
-        }
-        f.close();
-        assertUnreadable();
-    }
-
-    // Create a brand new cache and put one entry into it.
-    private void prepareNewCache() throws IOException {
-        BlobCache bc = new BlobCache(TEST_FILE_NAME, MAX_ENTRIES, MAX_BYTES, true);
-        genData(DATA_0, 777);
-        bc.insert(KEY_1, DATA_0);
-        bc.close();
-    }
-
-    private void assertReadable() throws IOException {
-        BlobCache bc = new BlobCache(TEST_FILE_NAME, MAX_ENTRIES, MAX_BYTES, false);
-        genData(DATA_0, 777);
-        assertSameData(DATA_0, bc.lookup(KEY_1));
-        bc.close();
-    }
-
-    private void assertUnreadable() throws IOException {
-        BlobCache bc = new BlobCache(TEST_FILE_NAME, MAX_ENTRIES, MAX_BYTES, false);
-        genData(DATA_0, 777);
-        assertNull(bc.lookup(KEY_1));
-        bc.close();
-    }
-
-    @LargeTest
-    public void testRandomSize() throws IOException {
-        BlobCache bc = new BlobCache(TEST_FILE_NAME, MAX_ENTRIES, MAX_BYTES, true);
-
-        // Random size test
-        Random rand = new Random(0);
-        for (int i = 0; i < 100; i++) {
-            byte[] data = new byte[rand.nextInt(MAX_BYTES*12/10)];
-            try {
-                bc.insert(rand.nextLong(), data);
-                if (data.length > MAX_BYTES - 4 - 20) fail();
-            } catch (RuntimeException ex) {
-                if (data.length <= MAX_BYTES - 4 - 20) fail();
-            }
-        }
-
-        bc.close();
-    }
-
-    @LargeTest
-    public void testBandwidth() throws IOException {
-        BlobCache bc = new BlobCache(TEST_FILE_NAME, 1000, 10000000, true);
-
-        // Write
-        int count = 0;
-        byte[] data = new byte[20000];
-        long t0 = System.nanoTime();
-        for (int i = 0; i < 1000; i++) {
-            bc.insert(i, data);
-            count += data.length;
-        }
-        bc.syncAll();
-        float delta = (System.nanoTime() - t0) * 1e-3f;
-        Log.v(TAG, "write bandwidth = " + (count / delta) + " M/s");
-
-        // Copy over
-        BlobCache.LookupRequest req = new BlobCache.LookupRequest();
-        count = 0;
-        t0 = System.nanoTime();
-        for (int i = 0; i < 1000; i++) {
-            req.key = i;
-            req.buffer = data;
-            if (bc.lookup(req)) {
-                count += req.length;
-            }
-        }
-        bc.syncAll();
-        delta = (System.nanoTime() - t0) * 1e-3f;
-        Log.v(TAG, "copy over bandwidth = " + (count / delta) + " M/s");
-
-        // Read
-        count = 0;
-        t0 = System.nanoTime();
-        for (int i = 0; i < 1000; i++) {
-            req.key = i;
-            req.buffer = data;
-            if (bc.lookup(req)) {
-                count += req.length;
-            }
-        }
-        bc.syncAll();
-        delta = (System.nanoTime() - t0) * 1e-3f;
-        Log.v(TAG, "read bandwidth = " + (count / delta) + " M/s");
-
-        bc.close();
-    }
-
-    @LargeTest
-    public void testSmallSize() throws IOException {
-        BlobCache bc = new BlobCache(TEST_FILE_NAME, MAX_ENTRIES, 40, true);
-
-        // Small size test
-        Random rand = new Random(0);
-        for (int i = 0; i < 100; i++) {
-            byte[] data = new byte[rand.nextInt(3)];
-            bc.insert(rand.nextLong(), data);
-        }
-
-        bc.close();
-    }
-
-    @LargeTest
-    public void testManyEntries() throws IOException {
-        BlobCache bc = new BlobCache(TEST_FILE_NAME, 1, MAX_BYTES, true);
-
-        // Many entries test
-        Random rand = new Random(0);
-        for (int i = 0; i < 100; i++) {
-            byte[] data = new byte[rand.nextInt(10)];
-        }
-
-        bc.close();
-    }
-
-    private void genData(byte[] data, int seed) {
-        for(int i = 0; i < data.length; i++) {
-            data[i] = (byte) (seed * i);
-        }
-    }
-
-    private void assertSameData(byte[] data1, byte[] data2) {
-        if (data1 == null && data2 == null) return;
-        if (data1 == null || data2 == null) fail();
-        if (data1.length != data2.length) fail();
-        for (int i = 0; i < data1.length; i++) {
-            if (data1[i] != data2[i]) fail();
-        }
-    }
-
-    private void assertSameData(byte[] data1, byte[] data2, int n) {
-        if (data1 == null || data2 == null) fail();
-        for (int i = 0; i < n; i++) {
-            if (data1[i] != data2[i]) fail();
-        }
-    }
-}
diff --git a/tests/src/com/android/gallery3d/common/UtilsTest.java b/tests/src/com/android/gallery3d/common/UtilsTest.java
deleted file mode 100644
index a20ebeb..0000000
--- a/tests/src/com/android/gallery3d/common/UtilsTest.java
+++ /dev/null
@@ -1,202 +0,0 @@
-/*
- * Copyright (C) 2010 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.gallery3d.common;
-
-import android.test.AndroidTestCase;
-import android.test.suitebuilder.annotation.SmallTest;
-import android.util.Log;
-
-public class UtilsTest extends AndroidTestCase {
-    private static final String TAG = "UtilsTest";
-
-    private static final int [] testData = new int [] {
-        /* outWidth, outHeight, minSideLength, maxNumOfPixels, sample size */
-        1, 1, BitmapUtils.UNCONSTRAINED, BitmapUtils.UNCONSTRAINED, 1,
-        1, 1, 1, 1, 1,
-        100, 100, 100, 10000, 1,
-        100, 100, 100, 2500, 2,
-        99, 66, 33, 10000, 2,
-        66, 99, 33, 10000, 2,
-        99, 66, 34, 10000, 1,
-        99, 66, 22, 10000, 4,
-        99, 66, 16, 10000, 4,
-
-        10000, 10000, 20000, 1000000, 16,
-
-        100, 100, 100, 10000, 1, // 1
-        100, 100, 50, 10000, 2,  // 2
-        100, 100, 30, 10000, 4,  // 3->4
-        100, 100, 22, 10000, 4,  // 4
-        100, 100, 20, 10000, 8,  // 5->8
-        100, 100, 11, 10000, 16, // 9->16
-        100, 100, 5,  10000, 24, // 20->24
-        100, 100, 2,  10000, 56, // 50->56
-
-        100, 100, 100, 10000 - 1, 2,                  // a bit less than 1
-        100, 100, 100, 10000 / (2 * 2) - 1, 4,        // a bit less than 2
-        100, 100, 100, 10000 / (3 * 3) - 1, 4,        // a bit less than 3
-        100, 100, 100, 10000 / (4 * 4) - 1, 8,        // a bit less than 4
-        100, 100, 100, 10000 / (8 * 8) - 1, 16,       // a bit less than 8
-        100, 100, 100, 10000 / (16 * 16) - 1, 24,     // a bit less than 16
-        100, 100, 100, 10000 / (24 * 24) - 1, 32,     // a bit less than 24
-        100, 100, 100, 10000 / (32 * 32) - 1, 40,     // a bit less than 32
-
-        640, 480, 480, BitmapUtils.UNCONSTRAINED, 1,  // 1
-        640, 480, 240, BitmapUtils.UNCONSTRAINED, 2,  // 2
-        640, 480, 160, BitmapUtils.UNCONSTRAINED, 4,  // 3->4
-        640, 480, 120, BitmapUtils.UNCONSTRAINED, 4,  // 4
-        640, 480, 96, BitmapUtils.UNCONSTRAINED,  8,  // 5->8
-        640, 480, 80, BitmapUtils.UNCONSTRAINED,  8,  // 6->8
-        640, 480, 60, BitmapUtils.UNCONSTRAINED,  8,  // 8
-        640, 480, 48, BitmapUtils.UNCONSTRAINED, 16,  // 10->16
-        640, 480, 40, BitmapUtils.UNCONSTRAINED, 16,  // 12->16
-        640, 480, 30, BitmapUtils.UNCONSTRAINED, 16,  // 16
-        640, 480, 24, BitmapUtils.UNCONSTRAINED, 24,  // 20->24
-        640, 480, 20, BitmapUtils.UNCONSTRAINED, 24,  // 24
-        640, 480, 16, BitmapUtils.UNCONSTRAINED, 32,  // 30->32
-        640, 480, 12, BitmapUtils.UNCONSTRAINED, 40,  // 40
-        640, 480, 10, BitmapUtils.UNCONSTRAINED, 48,  // 48
-        640, 480, 8, BitmapUtils.UNCONSTRAINED,  64,  // 60->64
-        640, 480, 6, BitmapUtils.UNCONSTRAINED,  80,  // 80
-        640, 480, 4, BitmapUtils.UNCONSTRAINED, 120,  // 120
-        640, 480, 3, BitmapUtils.UNCONSTRAINED, 160,  // 160
-        640, 480, 2, BitmapUtils.UNCONSTRAINED, 240,  // 240
-        640, 480, 1, BitmapUtils.UNCONSTRAINED, 480,  // 480
-
-        640, 480, BitmapUtils.UNCONSTRAINED, BitmapUtils.UNCONSTRAINED, 1,
-        640, 480, BitmapUtils.UNCONSTRAINED, 640 * 480, 1,                  // 1
-        640, 480, BitmapUtils.UNCONSTRAINED, 640 * 480 - 1, 2,              // a bit less than 1
-        640, 480, BitmapUtils.UNCONSTRAINED, 640 * 480 / 4, 2,              // 2
-        640, 480, BitmapUtils.UNCONSTRAINED, 640 * 480 / 4 - 1, 4,          // a bit less than 2
-        640, 480, BitmapUtils.UNCONSTRAINED, 640 * 480 / 9, 4,              // 3
-        640, 480, BitmapUtils.UNCONSTRAINED, 640 * 480 / 9 - 1, 4,          // a bit less than 3
-        640, 480, BitmapUtils.UNCONSTRAINED, 640 * 480 / 16, 4,             // 4
-        640, 480, BitmapUtils.UNCONSTRAINED, 640 * 480 / 16 - 1, 8,         // a bit less than 4
-        640, 480, BitmapUtils.UNCONSTRAINED, 640 * 480 / 64, 8,             // 8
-        640, 480, BitmapUtils.UNCONSTRAINED, 640 * 480 / 64 - 1, 16,        // a bit less than 8
-        640, 480, BitmapUtils.UNCONSTRAINED, 640 * 480 / 256, 16,           // 16
-        640, 480, BitmapUtils.UNCONSTRAINED, 640 * 480 / 256 - 1, 24,       // a bit less than 16
-        640, 480, BitmapUtils.UNCONSTRAINED, 640 * 480 / (24 * 24) - 1, 32, // a bit less than 24
-    };
-
-    @SmallTest
-    public void testComputeSampleSize() {
-
-        for (int i = 0; i < testData.length; i += 5) {
-            int w = testData[i];
-            int h = testData[i + 1];
-            int minSide = testData[i + 2];
-            int maxPixels = testData[i + 3];
-            int sampleSize = testData[i + 4];
-            int result = BitmapUtils.computeSampleSize(w, h, minSide, maxPixels);
-            if (result != sampleSize) {
-                Log.v(TAG, w + "x" + h + ", minSide = " + minSide + ", maxPixels = "
-                        + maxPixels + ", sampleSize = " + sampleSize + ", result = "
-                        + result);
-            }
-            assertTrue(sampleSize == result);
-        }
-    }
-
-    public void testAssert() {
-        // This should not throw an exception.
-        Utils.assertTrue(true);
-
-        // This should throw an exception.
-        try {
-            Utils.assertTrue(false);
-            fail();
-        } catch (AssertionError ex) {
-            // expected.
-        }
-    }
-
-    public void testCheckNotNull() {
-        // These should not throw an expection.
-        Utils.checkNotNull(new Object());
-        Utils.checkNotNull(0);
-        Utils.checkNotNull("");
-
-        // This should throw an expection.
-        try {
-            Utils.checkNotNull(null);
-            fail();
-        } catch (NullPointerException ex) {
-            // expected.
-        }
-    }
-
-    public void testEquals() {
-        Object a = new Object();
-        Object b = new Object();
-
-        assertTrue(Utils.equals(null, null));
-        assertTrue(Utils.equals(a, a));
-        assertFalse(Utils.equals(null, a));
-        assertFalse(Utils.equals(a, null));
-        assertFalse(Utils.equals(a, b));
-    }
-
-    public void testNextPowerOf2() {
-        int[] q = new int[] {1, 2, 3, 4, 5, 6, 10, 65535, (1 << 30) - 1, (1 << 30)};
-        int[] a = new int[] {1, 2, 4, 4, 8, 8, 16, 65536, (1 << 30)    , (1 << 30)};
-
-        for (int i = 0; i < q.length; i++) {
-            assertEquals(a[i], Utils.nextPowerOf2(q[i]));
-        }
-
-        int[] e = new int[] {0, -1, -2, -4, -65536, (1 << 30) + 1, Integer.MAX_VALUE};
-
-        for (int v : e) {
-            try {
-                Utils.nextPowerOf2(v);
-                fail();
-            } catch (IllegalArgumentException ex) {
-                // expected.
-            }
-        }
-    }
-
-    public void testClamp() {
-        assertEquals(1000, Utils.clamp(300, 1000, 2000));
-        assertEquals(1300, Utils.clamp(1300, 1000, 2000));
-        assertEquals(2000, Utils.clamp(2300, 1000, 2000));
-
-        assertEquals(0.125f, Utils.clamp(0.1f, 0.125f, 0.5f));
-        assertEquals(0.25f, Utils.clamp(0.25f, 0.125f, 0.5f));
-        assertEquals(0.5f, Utils.clamp(0.9f, 0.125f, 0.5f));
-    }
-
-    public void testIsOpaque() {
-        assertTrue(Utils.isOpaque(0xFF000000));
-        assertTrue(Utils.isOpaque(0xFFFFFFFF));
-        assertTrue(Utils.isOpaque(0xFF123456));
-
-        assertFalse(Utils.isOpaque(0xFEFFFFFF));
-        assertFalse(Utils.isOpaque(0x8FFFFFFF));
-        assertFalse(Utils.isOpaque(0x00FF0000));
-        assertFalse(Utils.isOpaque(0x5500FF00));
-        assertFalse(Utils.isOpaque(0xAA0000FF));
-    }
-
-    public static void assertFloatEq(float expected, float actual) {
-        if (Math.abs(actual - expected) > 1e-6) {
-            Log.v(TAG, "expected: " + expected + ", actual: " + actual);
-            fail();
-        }
-    }
-}
diff --git a/tests/src/com/android/gallery3d/data/GalleryAppMock.java b/tests/src/com/android/gallery3d/data/GalleryAppMock.java
deleted file mode 100644
index bbc5692..0000000
--- a/tests/src/com/android/gallery3d/data/GalleryAppMock.java
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Copyright (C) 2010 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.gallery3d.data;
-
-import android.content.ContentResolver;
-import android.content.Context;
-import android.os.Looper;
-
-import com.android.gallery3d.ui.GLRoot;
-import com.android.gallery3d.ui.GLRootStub;
-
-class GalleryAppMock extends GalleryAppStub {
-    GLRoot mGLRoot = new GLRootStub();
-    DataManager mDataManager = new DataManager(this);
-    ContentResolver mResolver;
-    Context mContext;
-    Looper mMainLooper;
-
-    GalleryAppMock(Context context,
-            ContentResolver resolver, Looper mainLooper) {
-        mContext = context;
-        mResolver = resolver;
-        mMainLooper = mainLooper;
-    }
-
-    @Override
-    public GLRoot getGLRoot() { return mGLRoot; }
-    @Override
-    public DataManager getDataManager() { return mDataManager; }
-    @Override
-    public Context getAndroidContext() { return mContext; }
-    @Override
-    public ContentResolver getContentResolver() { return mResolver; }
-    @Override
-    public Looper getMainLooper() { return mMainLooper; }
-}
diff --git a/tests/src/com/android/gallery3d/data/GalleryAppStub.java b/tests/src/com/android/gallery3d/data/GalleryAppStub.java
deleted file mode 100644
index 5aff2a2..0000000
--- a/tests/src/com/android/gallery3d/data/GalleryAppStub.java
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Copyright (C) 2010 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.gallery3d.data;
-
-import com.android.gallery3d.app.GalleryApp;
-import com.android.gallery3d.app.StateManager;
-import com.android.gallery3d.app.StitchingProgressManager;
-import com.android.gallery3d.ui.GLRoot;
-import com.android.gallery3d.util.ThreadPool;
-
-import android.content.ContentResolver;
-import android.content.Context;
-import android.content.res.Resources;
-import android.os.Looper;
-
-class GalleryAppStub implements GalleryApp {
-    public ImageCacheService getImageCacheService() { return null; }
-    public StateManager getStateManager() { return null; }
-    public DataManager getDataManager() { return null; }
-    public DownloadUtils getDownloadService() { return null; }
-    public DecodeUtils getDecodeService() { return null; }
-
-    public GLRoot getGLRoot() { return null; }
-
-    public Context getAndroidContext() { return null; }
-
-    public Looper getMainLooper() { return null; }
-    public Resources getResources() { return null; }
-    public ContentResolver getContentResolver() { return null; }
-    public ThreadPool getThreadPool() { return null; }
-    public DownloadCache getDownloadCache() { return null; }
-    public StitchingProgressManager getStitchingProgressManager() { return null; }
-}
diff --git a/tests/src/com/android/gallery3d/data/LocalDataTest.java b/tests/src/com/android/gallery3d/data/LocalDataTest.java
deleted file mode 100644
index 8f6a46b..0000000
--- a/tests/src/com/android/gallery3d/data/LocalDataTest.java
+++ /dev/null
@@ -1,461 +0,0 @@
-/*
- * Copyright (C) 2010 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.gallery3d.data;
-
-import android.content.ContentProvider;
-import android.content.ContentResolver;
-import android.database.Cursor;
-import android.database.sqlite.SQLiteDatabase;
-import android.database.sqlite.SQLiteQueryBuilder;
-import android.net.Uri;
-import android.os.Looper;
-import android.test.AndroidTestCase;
-import android.test.mock.MockContentProvider;
-import android.test.mock.MockContentResolver;
-import android.test.suitebuilder.annotation.MediumTest;
-import android.util.Log;
-
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.TimeUnit;
-
-public class LocalDataTest extends AndroidTestCase {
-    @SuppressWarnings("unused")
-    private static final String TAG = "LocalDataTest";
-    private static final long DEFAULT_TIMEOUT = 1000; // one second
-
-    @MediumTest
-    public void testLocalAlbum() throws Exception {
-        new TestZeroImage().run();
-        new TestOneImage().run();
-        new TestMoreImages().run();
-        new TestZeroVideo().run();
-        new TestOneVideo().run();
-        new TestMoreVideos().run();
-        new TestDeleteOneImage().run();
-        new TestDeleteOneAlbum().run();
-    }
-
-    abstract class TestLocalAlbumBase {
-        private boolean mIsImage;
-        protected GalleryAppStub mApp;
-        protected LocalAlbumSet mAlbumSet;
-
-        TestLocalAlbumBase(boolean isImage) {
-            mIsImage = isImage;
-        }
-
-        public void run() throws Exception {
-            SQLiteDatabase db = SQLiteDatabase.create(null);
-            prepareData(db);
-            mApp = newGalleryContext(db, Looper.getMainLooper());
-            Path.clearAll();
-            Path path = Path.fromString(
-                    mIsImage ? "/local/image" : "/local/video");
-            mAlbumSet = new LocalAlbumSet(path, mApp);
-            mAlbumSet.reload();
-            verifyResult();
-        }
-
-        abstract void prepareData(SQLiteDatabase db);
-        abstract void verifyResult() throws Exception;
-    }
-
-    abstract class TestLocalImageAlbum extends TestLocalAlbumBase {
-        TestLocalImageAlbum() {
-            super(true);
-        }
-    }
-
-    abstract class TestLocalVideoAlbum extends TestLocalAlbumBase {
-        TestLocalVideoAlbum() {
-            super(false);
-        }
-    }
-
-    class TestZeroImage extends TestLocalImageAlbum {
-        @Override
-        public void prepareData(SQLiteDatabase db) {
-            createImageTable(db);
-        }
-
-        @Override
-        public void verifyResult() {
-            assertEquals(0, mAlbumSet.getMediaItemCount());
-            assertEquals(0, mAlbumSet.getSubMediaSetCount());
-            assertEquals(0, mAlbumSet.getTotalMediaItemCount());
-         }
-    }
-
-    class TestOneImage extends TestLocalImageAlbum {
-        @Override
-        public void prepareData(SQLiteDatabase db) {
-            createImageTable(db);
-            insertImageData(db);
-        }
-
-        @Override
-        public void verifyResult() {
-            assertEquals(0, mAlbumSet.getMediaItemCount());
-            assertEquals(1, mAlbumSet.getSubMediaSetCount());
-            assertEquals(1, mAlbumSet.getTotalMediaItemCount());
-            MediaSet sub = mAlbumSet.getSubMediaSet(0);
-            assertEquals(1, sub.getMediaItemCount());
-            assertEquals(0, sub.getSubMediaSetCount());
-            LocalMediaItem item = (LocalMediaItem) sub.getMediaItem(0, 1).get(0);
-            assertEquals(1, item.id);
-            assertEquals("IMG_0072", item.caption);
-            assertEquals("image/jpeg", item.mimeType);
-            assertEquals(12.0, item.latitude);
-            assertEquals(34.0, item.longitude);
-            assertEquals(0xD000, item.dateTakenInMs);
-            assertEquals(1280395646L, item.dateAddedInSec);
-            assertEquals(1275934796L, item.dateModifiedInSec);
-            assertEquals("/mnt/sdcard/DCIM/100CANON/IMG_0072.JPG", item.filePath);
-        }
-    }
-
-    class TestMoreImages extends TestLocalImageAlbum {
-        @Override
-        public void prepareData(SQLiteDatabase db) {
-            // Albums are sorted by names, and items are sorted by
-            // dateTimeTaken (descending)
-            createImageTable(db);
-            // bucket 0xB000
-            insertImageData(db, 1000, 0xB000, "second");  // id 1
-            insertImageData(db, 2000, 0xB000, "second");  // id 2
-            // bucket 0xB001
-            insertImageData(db, 3000, 0xB001, "first");   // id 3
-        }
-
-        @Override
-        public void verifyResult() {
-            assertEquals(0, mAlbumSet.getMediaItemCount());
-            assertEquals(2, mAlbumSet.getSubMediaSetCount());
-            assertEquals(3, mAlbumSet.getTotalMediaItemCount());
-
-            MediaSet first = mAlbumSet.getSubMediaSet(0);
-            assertEquals(1, first.getMediaItemCount());
-            LocalMediaItem item = (LocalMediaItem) first.getMediaItem(0, 1).get(0);
-            assertEquals(3, item.id);
-            assertEquals(3000L, item.dateTakenInMs);
-
-            MediaSet second = mAlbumSet.getSubMediaSet(1);
-            assertEquals(2, second.getMediaItemCount());
-            item = (LocalMediaItem) second.getMediaItem(0, 1).get(0);
-            assertEquals(2, item.id);
-            assertEquals(2000L, item.dateTakenInMs);
-            item = (LocalMediaItem) second.getMediaItem(1, 1).get(0);
-            assertEquals(1, item.id);
-            assertEquals(1000L, item.dateTakenInMs);
-        }
-    }
-
-    class OnContentDirtyLatch implements ContentListener {
-        private CountDownLatch mLatch = new CountDownLatch(1);
-
-        public void onContentDirty() {
-            mLatch.countDown();
-        }
-
-        public boolean isOnContentDirtyBeCalled(long timeout)
-                throws InterruptedException {
-            return mLatch.await(timeout, TimeUnit.MILLISECONDS);
-        }
-    }
-
-    class TestDeleteOneAlbum extends TestLocalImageAlbum {
-        @Override
-        public void prepareData(SQLiteDatabase db) {
-            // Albums are sorted by names, and items are sorted by
-            // dateTimeTaken (descending)
-            createImageTable(db);
-            // bucket 0xB000
-            insertImageData(db, 1000, 0xB000, "second");  // id 1
-            insertImageData(db, 2000, 0xB000, "second");  // id 2
-            // bucket 0xB001
-            insertImageData(db, 3000, 0xB001, "first");   // id 3
-        }
-
-        @Override
-        public void verifyResult() throws Exception {
-            MediaSet sub = mAlbumSet.getSubMediaSet(1);  // "second"
-            assertEquals(2, mAlbumSet.getSubMediaSetCount());
-            OnContentDirtyLatch latch = new OnContentDirtyLatch();
-            sub.addContentListener(latch);
-            assertTrue((sub.getSupportedOperations() & MediaSet.SUPPORT_DELETE) != 0);
-            sub.delete();
-            mAlbumSet.fakeChange();
-            latch.isOnContentDirtyBeCalled(DEFAULT_TIMEOUT);
-            mAlbumSet.reload();
-            assertEquals(1, mAlbumSet.getSubMediaSetCount());
-        }
-    }
-
-    class TestDeleteOneImage extends TestLocalImageAlbum {
-
-        @Override
-        public void prepareData(SQLiteDatabase db) {
-            createImageTable(db);
-            insertImageData(db);
-        }
-
-        @Override
-        public void verifyResult() {
-            MediaSet sub = mAlbumSet.getSubMediaSet(0);
-            LocalMediaItem item = (LocalMediaItem) sub.getMediaItem(0, 1).get(0);
-            assertEquals(1, sub.getMediaItemCount());
-            assertTrue((sub.getSupportedOperations() & MediaSet.SUPPORT_DELETE) != 0);
-            sub.delete();
-            sub.reload();
-            assertEquals(0, sub.getMediaItemCount());
-        }
-    }
-
-    static void createImageTable(SQLiteDatabase db) {
-        // This is copied from MediaProvider
-        db.execSQL("CREATE TABLE IF NOT EXISTS images (" +
-                "_id INTEGER PRIMARY KEY," +
-                "_data TEXT," +
-                "_size INTEGER," +
-                "_display_name TEXT," +
-                "mime_type TEXT," +
-                "title TEXT," +
-                "date_added INTEGER," +
-                "date_modified INTEGER," +
-                "description TEXT," +
-                "picasa_id TEXT," +
-                "isprivate INTEGER," +
-                "latitude DOUBLE," +
-                "longitude DOUBLE," +
-                "datetaken INTEGER," +
-                "orientation INTEGER," +
-                "mini_thumb_magic INTEGER," +
-                "bucket_id TEXT," +
-                "bucket_display_name TEXT" +
-               ");");
-    }
-
-    static void insertImageData(SQLiteDatabase db) {
-        insertImageData(db, 0xD000, 0xB000, "name");
-    }
-
-    static void insertImageData(SQLiteDatabase db, long dateTaken,
-            int bucketId, String bucketName) {
-        db.execSQL("INSERT INTO images (title, mime_type, latitude, longitude, "
-                + "datetaken, date_added, date_modified, bucket_id, "
-                + "bucket_display_name, _data, orientation) "
-                + "VALUES ('IMG_0072', 'image/jpeg', 12, 34, "
-                + dateTaken + ", 1280395646, 1275934796, '" + bucketId + "', "
-                + "'" + bucketName + "', "
-                + "'/mnt/sdcard/DCIM/100CANON/IMG_0072.JPG', 0)");
-    }
-
-    class TestZeroVideo extends TestLocalVideoAlbum {
-        @Override
-        public void prepareData(SQLiteDatabase db) {
-            createVideoTable(db);
-        }
-
-        @Override
-        public void verifyResult() {
-            assertEquals(0, mAlbumSet.getMediaItemCount());
-            assertEquals(0, mAlbumSet.getSubMediaSetCount());
-            assertEquals(0, mAlbumSet.getTotalMediaItemCount());
-        }
-    }
-
-    class TestOneVideo extends TestLocalVideoAlbum {
-        @Override
-        public void prepareData(SQLiteDatabase db) {
-            createVideoTable(db);
-            insertVideoData(db);
-        }
-
-        @Override
-        public void verifyResult() {
-            assertEquals(0, mAlbumSet.getMediaItemCount());
-            assertEquals(1, mAlbumSet.getSubMediaSetCount());
-            assertEquals(1, mAlbumSet.getTotalMediaItemCount());
-            MediaSet sub = mAlbumSet.getSubMediaSet(0);
-            assertEquals(1, sub.getMediaItemCount());
-            assertEquals(0, sub.getSubMediaSetCount());
-            LocalMediaItem item = (LocalMediaItem) sub.getMediaItem(0, 1).get(0);
-            assertEquals(1, item.id);
-            assertEquals("VID_20100811_051413", item.caption);
-            assertEquals("video/mp4", item.mimeType);
-            assertEquals(11.0, item.latitude);
-            assertEquals(22.0, item.longitude);
-            assertEquals(0xD000, item.dateTakenInMs);
-            assertEquals(1281503663L, item.dateAddedInSec);
-            assertEquals(1281503662L, item.dateModifiedInSec);
-            assertEquals("/mnt/sdcard/DCIM/Camera/VID_20100811_051413.3gp",
-                    item.filePath);
-        }
-    }
-
-    class TestMoreVideos extends TestLocalVideoAlbum {
-        @Override
-        public void prepareData(SQLiteDatabase db) {
-            // Albums are sorted by names, and items are sorted by
-            // dateTimeTaken (descending)
-            createVideoTable(db);
-            // bucket 0xB002
-            insertVideoData(db, 1000, 0xB000, "second");  // id 1
-            insertVideoData(db, 2000, 0xB000, "second");  // id 2
-            // bucket 0xB001
-            insertVideoData(db, 3000, 0xB001, "first");   // id 3
-        }
-
-        @Override
-        public void verifyResult() {
-            assertEquals(0, mAlbumSet.getMediaItemCount());
-            assertEquals(2, mAlbumSet.getSubMediaSetCount());
-            assertEquals(3, mAlbumSet.getTotalMediaItemCount());
-
-            MediaSet first = mAlbumSet.getSubMediaSet(0);
-            assertEquals(1, first.getMediaItemCount());
-            LocalMediaItem item = (LocalMediaItem) first.getMediaItem(0, 1).get(0);
-            assertEquals(3, item.id);
-            assertEquals(3000L, item.dateTakenInMs);
-
-            MediaSet second = mAlbumSet.getSubMediaSet(1);
-            assertEquals(2, second.getMediaItemCount());
-            item = (LocalMediaItem) second.getMediaItem(0, 1).get(0);
-            assertEquals(2, item.id);
-            assertEquals(2000L, item.dateTakenInMs);
-            item = (LocalMediaItem) second.getMediaItem(1, 1).get(0);
-            assertEquals(1, item.id);
-            assertEquals(1000L, item.dateTakenInMs);
-        }
-    }
-
-    static void createVideoTable(SQLiteDatabase db) {
-        db.execSQL("CREATE TABLE IF NOT EXISTS video (" +
-                   "_id INTEGER PRIMARY KEY," +
-                   "_data TEXT NOT NULL," +
-                   "_display_name TEXT," +
-                   "_size INTEGER," +
-                   "mime_type TEXT," +
-                   "date_added INTEGER," +
-                   "date_modified INTEGER," +
-                   "title TEXT," +
-                   "duration INTEGER," +
-                   "artist TEXT," +
-                   "album TEXT," +
-                   "resolution TEXT," +
-                   "description TEXT," +
-                   "isprivate INTEGER," +   // for YouTube videos
-                   "tags TEXT," +           // for YouTube videos
-                   "category TEXT," +       // for YouTube videos
-                   "language TEXT," +       // for YouTube videos
-                   "mini_thumb_data TEXT," +
-                   "latitude DOUBLE," +
-                   "longitude DOUBLE," +
-                   "datetaken INTEGER," +
-                   "mini_thumb_magic INTEGER" +
-                   ");");
-        db.execSQL("ALTER TABLE video ADD COLUMN bucket_id TEXT;");
-        db.execSQL("ALTER TABLE video ADD COLUMN bucket_display_name TEXT");
-    }
-
-    static void insertVideoData(SQLiteDatabase db) {
-        insertVideoData(db, 0xD000, 0xB000, "name");
-    }
-
-    static void insertVideoData(SQLiteDatabase db, long dateTaken,
-            int bucketId, String bucketName) {
-        db.execSQL("INSERT INTO video (title, mime_type, latitude, longitude, "
-                + "datetaken, date_added, date_modified, bucket_id, "
-                + "bucket_display_name, _data, duration) "
-                + "VALUES ('VID_20100811_051413', 'video/mp4', 11, 22, "
-                + dateTaken + ", 1281503663, 1281503662, '" + bucketId + "', "
-                + "'" + bucketName + "', "
-                + "'/mnt/sdcard/DCIM/Camera/VID_20100811_051413.3gp', 2964)");
-    }
-
-    static GalleryAppStub newGalleryContext(SQLiteDatabase db, Looper mainLooper) {
-        MockContentResolver cr = new MockContentResolver();
-        ContentProvider cp = new DbContentProvider(db, cr);
-        cr.addProvider("media", cp);
-        return new GalleryAppMock(null, cr, mainLooper);
-    }
-}
-
-class DbContentProvider extends MockContentProvider {
-    private static final String TAG = "DbContentProvider";
-    private SQLiteDatabase mDatabase;
-    private ContentResolver mContentResolver;
-
-    DbContentProvider(SQLiteDatabase db, ContentResolver cr) {
-        mDatabase = db;
-        mContentResolver = cr;
-    }
-
-    @Override
-    public Cursor query(Uri uri, String[] projection,
-            String selection, String[] selectionArgs, String sortOrder) {
-        // This is a simplified version extracted from MediaProvider.
-
-        String tableName = getTableName(uri);
-        if (tableName == null) return null;
-
-        SQLiteQueryBuilder qb = new SQLiteQueryBuilder();
-        qb.setTables(tableName);
-
-        String groupBy = null;
-        String limit = uri.getQueryParameter("limit");
-
-        if (uri.getQueryParameter("distinct") != null) {
-            qb.setDistinct(true);
-        }
-
-        Log.v(TAG, "query = " + qb.buildQuery(projection, selection,
-                selectionArgs, groupBy, null, sortOrder, limit));
-
-        if (selectionArgs != null) {
-            for (String s : selectionArgs) {
-                Log.v(TAG, "  selectionArgs = " + s);
-            }
-        }
-
-        Cursor c = qb.query(mDatabase, projection, selection,
-                selectionArgs, groupBy, null, sortOrder, limit);
-
-        return c;
-    }
-
-    @Override
-    public int delete(Uri uri, String whereClause, String[] whereArgs) {
-        Log.v(TAG, "delete " + uri + "," + whereClause + "," + whereArgs[0]);
-        String tableName = getTableName(uri);
-        if (tableName == null) return 0;
-        int count = mDatabase.delete(tableName, whereClause, whereArgs);
-        mContentResolver.notifyChange(uri, null);
-        return count;
-    }
-
-    private String getTableName(Uri uri) {
-        String uriString = uri.toString();
-        if (uriString.startsWith("content://media/external/images/media")) {
-            return "images";
-        } else if (uriString.startsWith("content://media/external/video/media")) {
-            return "video";
-        } else {
-            return null;
-        }
-    }
-}
diff --git a/tests/src/com/android/gallery3d/data/MediaSetTest.java b/tests/src/com/android/gallery3d/data/MediaSetTest.java
deleted file mode 100644
index 33dfe96..0000000
--- a/tests/src/com/android/gallery3d/data/MediaSetTest.java
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * Copyright (C) 2010 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.gallery3d.data;
-
-import com.android.gallery3d.app.GalleryApp;
-
-import android.test.AndroidTestCase;
-import android.test.suitebuilder.annotation.SmallTest;
-
-public class MediaSetTest extends AndroidTestCase {
-    @SuppressWarnings("unused")
-    private static final String TAG = "MediaSetTest";
-
-    @SmallTest
-    public void testComboAlbumSet() {
-        GalleryApp app = new GalleryAppMock(null, null, null);
-        Path.clearAll();
-        DataManager dataManager = app.getDataManager();
-
-        dataManager.addSource(new ComboSource(app));
-        dataManager.addSource(new MockSource(app));
-
-        MockSet set00 = new MockSet(Path.fromString("/mock/00"), dataManager, 0, 2000);
-        MockSet set01 = new MockSet(Path.fromString("/mock/01"), dataManager, 1, 3000);
-        MockSet set10 = new MockSet(Path.fromString("/mock/10"), dataManager, 2, 4000);
-        MockSet set11 = new MockSet(Path.fromString("/mock/11"), dataManager, 3, 5000);
-        MockSet set12 = new MockSet(Path.fromString("/mock/12"), dataManager, 4, 6000);
-
-        MockSet set0 = new MockSet(Path.fromString("/mock/0"), dataManager, 7, 7000);
-        set0.addMediaSet(set00);
-        set0.addMediaSet(set01);
-
-        MockSet set1 = new MockSet(Path.fromString("/mock/1"), dataManager, 8, 8000);
-        set1.addMediaSet(set10);
-        set1.addMediaSet(set11);
-        set1.addMediaSet(set12);
-
-        MediaSet combo = dataManager.getMediaSet("/combo/{/mock/0,/mock/1}");
-        assertEquals(5, combo.getSubMediaSetCount());
-        assertEquals(0, combo.getMediaItemCount());
-        assertEquals("/mock/00", combo.getSubMediaSet(0).getPath().toString());
-        assertEquals("/mock/01", combo.getSubMediaSet(1).getPath().toString());
-        assertEquals("/mock/10", combo.getSubMediaSet(2).getPath().toString());
-        assertEquals("/mock/11", combo.getSubMediaSet(3).getPath().toString());
-        assertEquals("/mock/12", combo.getSubMediaSet(4).getPath().toString());
-
-        assertEquals(10, combo.getTotalMediaItemCount());
-    }
-}
diff --git a/tests/src/com/android/gallery3d/data/MockItem.java b/tests/src/com/android/gallery3d/data/MockItem.java
deleted file mode 100644
index 2901979..0000000
--- a/tests/src/com/android/gallery3d/data/MockItem.java
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Copyright (C) 2010 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.gallery3d.data;
-
-import com.android.gallery3d.util.ThreadPool.Job;
-
-import android.graphics.Bitmap;
-import android.graphics.BitmapRegionDecoder;
-
-public class MockItem extends MediaItem {
-    public MockItem(Path path) {
-        super(path, nextVersionNumber());
-    }
-
-    @Override
-    public Job<Bitmap> requestImage(int type) {
-        return null;
-    }
-
-    @Override
-    public Job<BitmapRegionDecoder> requestLargeImage() {
-        return null;
-    }
-
-    @Override
-    public String getMimeType() {
-        return null;
-    }
-
-    @Override
-    public int getWidth() {
-        return 0;
-    }
-
-    @Override
-    public int getHeight() {
-        return 0;
-    }
-}
diff --git a/tests/src/com/android/gallery3d/data/MockSet.java b/tests/src/com/android/gallery3d/data/MockSet.java
deleted file mode 100644
index fa83c79..0000000
--- a/tests/src/com/android/gallery3d/data/MockSet.java
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- * Copyright (C) 2010 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.gallery3d.data;
-
-import java.util.ArrayList;
-
-public class MockSet extends MediaSet {
-    ArrayList<MediaItem> mItems = new ArrayList<MediaItem>();
-    ArrayList<MediaSet> mSets = new ArrayList<MediaSet>();
-    Path mItemPath;
-
-    public MockSet(Path path, DataManager dataManager) {
-        super(path, nextVersionNumber());
-        mItemPath = Path.fromString("/mock/item");
-    }
-
-    public MockSet(Path path, DataManager dataManager,
-            int items, int item_id_start) {
-        this(path, dataManager);
-        for (int i = 0; i < items; i++) {
-            Path childPath = mItemPath.getChild(item_id_start + i);
-            mItems.add(new MockItem(childPath));
-        }
-    }
-
-    public void addMediaSet(MediaSet sub) {
-        mSets.add(sub);
-    }
-
-    @Override
-    public int getMediaItemCount() {
-        return mItems.size();
-    }
-
-    @Override
-    public ArrayList<MediaItem> getMediaItem(int start, int count) {
-        ArrayList<MediaItem> result = new ArrayList<MediaItem>();
-        int end = Math.min(start + count, mItems.size());
-
-        for (int i = start; i < end; i++) {
-            result.add(mItems.get(i));
-        }
-        return result;
-    }
-
-    @Override
-    public int getSubMediaSetCount() {
-        return mSets.size();
-    }
-
-    @Override
-    public MediaSet getSubMediaSet(int index) {
-        return mSets.get(index);
-    }
-
-    @Override
-    public int getTotalMediaItemCount() {
-        int result = mItems.size();
-        for (MediaSet s : mSets) {
-            result += s.getTotalMediaItemCount();
-        }
-        return result;
-    }
-
-    @Override
-    public String getName() {
-        return "Set " + mPath;
-    }
-
-    @Override
-    public long reload() {
-        return 0;
-    }
-}
diff --git a/tests/src/com/android/gallery3d/data/MockSource.java b/tests/src/com/android/gallery3d/data/MockSource.java
deleted file mode 100644
index 27ed4d0..0000000
--- a/tests/src/com/android/gallery3d/data/MockSource.java
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Copyright (C) 2010 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.gallery3d.data;
-
-import com.android.gallery3d.app.GalleryApp;
-
-class MockSource extends MediaSource {
-    GalleryApp mApplication;
-    PathMatcher mMatcher;
-
-    private static final int MOCK_SET = 0;
-    private static final int MOCK_ITEM = 1;
-
-    public MockSource(GalleryApp context) {
-        super("mock");
-        mApplication = context;
-        mMatcher = new PathMatcher();
-        mMatcher.add("/mock/*", MOCK_SET);
-        mMatcher.add("/mock/item/*", MOCK_ITEM);
-    }
-
-    @Override
-    public MediaObject createMediaObject(Path path) {
-        MediaObject obj;
-        switch (mMatcher.match(path)) {
-            case MOCK_SET:
-                return new MockSet(path, mApplication.getDataManager());
-            case MOCK_ITEM:
-                return new MockItem(path);
-            default:
-                throw new RuntimeException("bad path: " + path);
-        }
-    }
-}
diff --git a/tests/src/com/android/gallery3d/data/PathTest.java b/tests/src/com/android/gallery3d/data/PathTest.java
deleted file mode 100644
index b43d109..0000000
--- a/tests/src/com/android/gallery3d/data/PathTest.java
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * Copyright (C) 2010 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.gallery3d.data;
-
-import android.test.AndroidTestCase;
-import android.test.suitebuilder.annotation.SmallTest;
-
-public class PathTest extends AndroidTestCase {
-    @SuppressWarnings("unused")
-    private static final String TAG = "PathTest";
-
-    @SmallTest
-    public void testToString() {
-        Path p = Path.fromString("/hello/world");
-        assertEquals("/hello/world", p.toString());
-
-        p = Path.fromString("/a");
-        assertEquals("/a", p.toString());
-
-        p = Path.fromString("");
-        assertEquals("", p.toString());
-    }
-
-    @SmallTest
-    public void testSplit() {
-        Path p = Path.fromString("/hello/world");
-        String[] s = p.split();
-        assertEquals(2, s.length);
-        assertEquals("hello", s[0]);
-        assertEquals("world", s[1]);
-
-        p = Path.fromString("");
-        assertEquals(0, p.split().length);
-    }
-
-    @SmallTest
-    public void testPrefix() {
-        Path p = Path.fromString("/hello/world");
-        assertEquals("hello", p.getPrefix());
-
-        p = Path.fromString("");
-        assertEquals("", p.getPrefix());
-    }
-
-    @SmallTest
-    public void testGetChild() {
-        Path p = Path.fromString("/hello");
-        Path q = Path.fromString("/hello/world");
-        assertSame(q, p.getChild("world"));
-        Path r = q.getChild(17);
-        assertEquals("/hello/world/17", r.toString());
-    }
-
-    @SmallTest
-    public void testSplitSequence() {
-        String[] s = Path.splitSequence("{a,bb,ccc}");
-        assertEquals(3, s.length);
-        assertEquals("a", s[0]);
-        assertEquals("bb", s[1]);
-        assertEquals("ccc", s[2]);
-
-        s = Path.splitSequence("{a,{bb,ccc},d}");
-        assertEquals(3, s.length);
-        assertEquals("a", s[0]);
-        assertEquals("{bb,ccc}", s[1]);
-        assertEquals("d", s[2]);
-    }
-}
diff --git a/tests/src/com/android/gallery3d/data/RealDataTest.java b/tests/src/com/android/gallery3d/data/RealDataTest.java
deleted file mode 100644
index 526cfe3..0000000
--- a/tests/src/com/android/gallery3d/data/RealDataTest.java
+++ /dev/null
@@ -1,110 +0,0 @@
-/*
- * Copyright (C) 2010 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.gallery3d.data;
-
-import com.android.gallery3d.app.GalleryApp;
-import com.android.gallery3d.picasasource.PicasaSource;
-
-import android.os.Looper;
-import android.test.AndroidTestCase;
-import android.test.suitebuilder.annotation.LargeTest;
-import android.util.Log;
-
-import java.util.ArrayList;
-import java.util.HashSet;
-
-// This test reads real data directly and dump information out in the log.
-public class RealDataTest extends AndroidTestCase {
-    private static final String TAG = "RealDataTest";
-
-    private HashSet<Path> mUsedId = new HashSet<Path>();
-    private GalleryApp mApplication;
-    private DataManager mDataManager;
-
-    @LargeTest
-    public void testRealData() {
-        mUsedId.clear();
-        mApplication = new GalleryAppMock(
-                mContext,
-                mContext.getContentResolver(),
-                Looper.myLooper());
-        mDataManager = mApplication.getDataManager();
-        mDataManager.addSource(new LocalSource(mApplication));
-        mDataManager.addSource(new PicasaSource(mApplication));
-        new TestLocalImage().run();
-        new TestLocalVideo().run();
-        new TestPicasa().run();
-    }
-
-    class TestLocalImage {
-        public void run() {
-            MediaSet set = mDataManager.getMediaSet("/local/image");
-            set.reload();
-            Log.v(TAG, "LocalAlbumSet (Image)");
-            dumpMediaSet(set, "");
-        }
-    }
-
-    class TestLocalVideo {
-        public void run() {
-            MediaSet set = mDataManager.getMediaSet("/local/video");
-            set.reload();
-            Log.v(TAG, "LocalAlbumSet (Video)");
-            dumpMediaSet(set, "");
-        }
-    }
-
-    class TestPicasa implements Runnable {
-        public void run() {
-            MediaSet set = mDataManager.getMediaSet("/picasa");
-            set.reload();
-            Log.v(TAG, "PicasaAlbumSet");
-            dumpMediaSet(set, "");
-        }
-    }
-
-    void dumpMediaSet(MediaSet set, String prefix) {
-        Log.v(TAG, "getName() = " + set.getName());
-        Log.v(TAG, "getPath() = " + set.getPath());
-        Log.v(TAG, "getMediaItemCount() = " + set.getMediaItemCount());
-        Log.v(TAG, "getSubMediaSetCount() = " + set.getSubMediaSetCount());
-        Log.v(TAG, "getTotalMediaItemCount() = " + set.getTotalMediaItemCount());
-        assertNewId(set.getPath());
-        for (int i = 0, n = set.getSubMediaSetCount(); i < n; i++) {
-            MediaSet sub = set.getSubMediaSet(i);
-            Log.v(TAG, prefix + "got set " + i);
-            dumpMediaSet(sub, prefix + "  ");
-        }
-        for (int i = 0, n = set.getMediaItemCount(); i < n; i += 10) {
-            ArrayList<MediaItem> list = set.getMediaItem(i, 10);
-            Log.v(TAG, prefix + "got item " + i + " (+" + list.size() + ")");
-            for (MediaItem item : list) {
-                dumpMediaItem(item, prefix + "..");
-            }
-        }
-    }
-
-    void dumpMediaItem(MediaItem item, String prefix) {
-        assertNewId(item.getPath());
-        Log.v(TAG, prefix + "getPath() = " + item.getPath());
-    }
-
-    void assertNewId(Path key) {
-        assertFalse(key + " has already appeared.", mUsedId.contains(key));
-        mUsedId.add(key);
-    }
-}
diff --git a/tests/src/com/android/gallery3d/exif/ExifDataTest.java b/tests/src/com/android/gallery3d/exif/ExifDataTest.java
deleted file mode 100644
index 142cc6b..0000000
--- a/tests/src/com/android/gallery3d/exif/ExifDataTest.java
+++ /dev/null
@@ -1,154 +0,0 @@
-/*
- * 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.gallery3d.exif;
-
-import android.test.suitebuilder.annotation.SmallTest;
-import junit.framework.TestCase;
-import java.nio.ByteOrder;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-public class ExifDataTest extends TestCase {
-    Map<Integer, ExifTag> mTestTags;
-    ExifInterface mInterface;
-    private ExifTag mVersionTag;
-    private ExifTag mGpsVersionTag;
-    private ExifTag mModelTag;
-    private ExifTag mDateTimeTag;
-    private ExifTag mCompressionTag;
-    private ExifTag mThumbnailFormatTag;
-    private ExifTag mLongitudeTag;
-    private ExifTag mShutterTag;
-    private ExifTag mInteropIndex;
-
-    @Override
-    public void setUp() throws Exception {
-        super.setUp();
-
-        mInterface = new ExifInterface();
-
-        // TYPE_UNDEFINED with 4 components
-        mVersionTag = mInterface.buildTag(ExifInterface.TAG_EXIF_VERSION, new byte[] {
-                5, 4, 3, 2
-        });
-        // TYPE_UNSIGNED_BYTE with 4 components
-        mGpsVersionTag = mInterface.buildTag(ExifInterface.TAG_GPS_VERSION_ID, new byte[] {
-                6, 7, 8, 9
-        });
-        // TYPE ASCII with arbitrary length
-        mModelTag = mInterface.buildTag(ExifInterface.TAG_MODEL, "helloworld");
-        // TYPE_ASCII with 20 components
-        mDateTimeTag = mInterface.buildTag(ExifInterface.TAG_DATE_TIME, "2013:02:11 20:20:20");
-        // TYPE_UNSIGNED_SHORT with 1 components
-        mCompressionTag = mInterface.buildTag(ExifInterface.TAG_COMPRESSION, 100);
-        // TYPE_UNSIGNED_LONG with 1 components
-        mThumbnailFormatTag =
-                mInterface.buildTag(ExifInterface.TAG_JPEG_INTERCHANGE_FORMAT, 100);
-        // TYPE_UNSIGNED_RATIONAL with 3 components
-        mLongitudeTag = mInterface.buildTag(ExifInterface.TAG_GPS_LONGITUDE, new Rational[] {
-                new Rational(2, 2), new Rational(11, 11),
-                new Rational(102, 102)
-        });
-        // TYPE_RATIONAL with 1 components
-        mShutterTag = mInterface
-                .buildTag(ExifInterface.TAG_SHUTTER_SPEED_VALUE, new Rational(4, 6));
-        // TYPE_ASCII with arbitrary length
-        mInteropIndex = mInterface.buildTag(ExifInterface.TAG_INTEROPERABILITY_INDEX, "foo");
-
-        mTestTags = new HashMap<Integer, ExifTag>();
-
-        mTestTags.put(ExifInterface.TAG_EXIF_VERSION, mVersionTag);
-        mTestTags.put(ExifInterface.TAG_GPS_VERSION_ID, mGpsVersionTag);
-        mTestTags.put(ExifInterface.TAG_MODEL, mModelTag);
-        mTestTags.put(ExifInterface.TAG_DATE_TIME, mDateTimeTag);
-        mTestTags.put(ExifInterface.TAG_COMPRESSION, mCompressionTag);
-        mTestTags.put(ExifInterface.TAG_JPEG_INTERCHANGE_FORMAT, mThumbnailFormatTag);
-        mTestTags.put(ExifInterface.TAG_GPS_LONGITUDE, mLongitudeTag);
-        mTestTags.put(ExifInterface.TAG_SHUTTER_SPEED_VALUE, mShutterTag);
-        mTestTags.put(ExifInterface.TAG_INTEROPERABILITY_INDEX, mInteropIndex);
-    }
-
-    @Override
-    public void tearDown() throws Exception {
-        super.tearDown();
-        mInterface = null;
-        mTestTags = null;
-    }
-
-    @SmallTest
-    public void testAddTag() {
-        ExifData exifData = new ExifData(ByteOrder.BIG_ENDIAN);
-
-        // Add all test tags
-        for (ExifTag t : mTestTags.values()) {
-            assertTrue(exifData.addTag(t) == null);
-        }
-
-        // Make sure no initial thumbnails
-        assertFalse(exifData.hasCompressedThumbnail());
-        assertFalse(exifData.hasUncompressedStrip());
-
-        // Check that we can set thumbnails
-        exifData.setStripBytes(3, new byte[] {
-                1, 2, 3, 4, 5
-        });
-        assertTrue(exifData.hasUncompressedStrip());
-        exifData.setCompressedThumbnail(new byte[] {
-            1
-        });
-        assertTrue(exifData.hasCompressedThumbnail());
-
-        // Check that we can clear thumbnails
-        exifData.clearThumbnailAndStrips();
-        assertFalse(exifData.hasCompressedThumbnail());
-        assertFalse(exifData.hasUncompressedStrip());
-
-        // Make sure ifds exist
-        for (int i : IfdData.getIfds()) {
-            assertTrue(exifData.getIfdData(i) != null);
-        }
-
-        // Get all test tags
-        List<ExifTag> allTags = exifData.getAllTags();
-        assertTrue(allTags != null);
-
-        // Make sure all test tags are in data
-        for (ExifTag t : mTestTags.values()) {
-            boolean check = false;
-            for (ExifTag i : allTags) {
-                if (t.equals(i)) {
-                    check = true;
-                    break;
-                }
-            }
-            assertTrue(check);
-        }
-
-        // Check if getting tags for a tid works
-        List<ExifTag> tidTags = exifData.getAllTagsForTagId(ExifInterface
-                .getTrueTagKey(ExifInterface.TAG_SHUTTER_SPEED_VALUE));
-        assertTrue(tidTags.size() == 1);
-        assertTrue(tidTags.get(0).equals(mShutterTag));
-
-        // Check if getting tags for an ifd works
-        List<ExifTag> ifdTags = exifData.getAllTagsForIfd(IfdId.TYPE_IFD_INTEROPERABILITY);
-        assertTrue(ifdTags.size() == 1);
-        assertTrue(ifdTags.get(0).equals(mInteropIndex));
-
-    }
-}
diff --git a/tests/src/com/android/gallery3d/exif/ExifInterfaceTest.java b/tests/src/com/android/gallery3d/exif/ExifInterfaceTest.java
deleted file mode 100644
index 01b2a32..0000000
--- a/tests/src/com/android/gallery3d/exif/ExifInterfaceTest.java
+++ /dev/null
@@ -1,533 +0,0 @@
-/*
- * Copyright (C) 2013 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.gallery3d.exif;
-
-import android.graphics.Bitmap;
-import android.graphics.BitmapFactory;
-
-import android.test.suitebuilder.annotation.MediumTest;
-
-import java.io.ByteArrayInputStream;
-
-import java.io.ByteArrayOutputStream;
-import java.io.File;
-import java.io.FileInputStream;
-
-import java.io.IOException;
-import java.io.InputStream;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-public class ExifInterfaceTest extends ExifXmlDataTestCase {
-
-    private File mTmpFile;
-    private List<Map<Short, List<String>>> mGroundTruth;
-    private ExifInterface mInterface;
-    private ExifTag mVersionTag;
-    private ExifTag mGpsVersionTag;
-    private ExifTag mModelTag;
-    private ExifTag mDateTimeTag;
-    private ExifTag mCompressionTag;
-    private ExifTag mThumbnailFormatTag;
-    private ExifTag mLongitudeTag;
-    private ExifTag mShutterTag;
-    Map<Integer, ExifTag> mTestTags;
-    Map<Integer, Integer> mTagDefinitions;
-
-    public ExifInterfaceTest(int imageRes, int xmlRes) {
-        super(imageRes, xmlRes);
-    }
-
-    public ExifInterfaceTest(String imagePath, String xmlPath) {
-        super(imagePath, xmlPath);
-    }
-
-    @MediumTest
-    public void testInterface() throws Exception {
-
-        InputStream imageInputStream = null;
-        try {
-            // Basic checks
-
-            // Check if bitmap is valid
-            byte[] imgData = Util.readToByteArray(getImageInputStream());
-            imageInputStream = new ByteArrayInputStream(imgData);
-            checkBitmap(imageInputStream);
-
-            // Check defines
-            int tag = ExifInterface.defineTag(1, (short) 0x0100);
-            assertTrue(getImageTitle(), tag == 0x00010100);
-            int tagDef = mInterface.getTagDefinition((short) 0x0100, IfdId.TYPE_IFD_0);
-            assertTrue(getImageTitle(), tagDef == 0x03040001);
-            int[] allowed = ExifInterface.getAllowedIfdsFromInfo(mInterface.getTagInfo().get(
-                    ExifInterface.TAG_IMAGE_WIDTH));
-            assertTrue(getImageTitle(), allowed.length == 2 && allowed[0] == IfdId.TYPE_IFD_0
-                    && allowed[1] == IfdId.TYPE_IFD_1);
-
-            // Check if there are any initial tags
-            assertTrue(getImageTitle(), mInterface.getAllTags() == null);
-
-            // ///////// Basic read/write testing
-
-            // Make sure we can read
-            imageInputStream = new ByteArrayInputStream(imgData);
-            mInterface.readExif(imageInputStream);
-
-            // Check tags against ground truth
-            checkTagsAgainstXml(mInterface.getAllTags());
-
-            // Make sure clearing Exif works
-            mInterface.clearExif();
-            assertTrue(getImageTitle(), mInterface.getAllTags() == null);
-
-            // Make sure setting tags works
-            mInterface.setTags(mTestTags.values());
-            checkTagsAgainstHash(mInterface.getAllTags(), mTestTags);
-
-            // Try writing over bitmap exif
-            ByteArrayOutputStream imgModified = new ByteArrayOutputStream();
-            mInterface.writeExif(imgData, imgModified);
-
-            // Check if bitmap is valid
-            byte[] imgData2 = imgModified.toByteArray();
-            imageInputStream = new ByteArrayInputStream(imgData2);
-            checkBitmap(imageInputStream);
-
-            // Make sure we get the same tags out
-            imageInputStream = new ByteArrayInputStream(imgData2);
-            mInterface.readExif(imageInputStream);
-            checkTagsAgainstHash(mInterface.getAllTags(), mTestTags);
-
-            // Reread original image
-            imageInputStream = new ByteArrayInputStream(imgData);
-            mInterface.readExif(imageInputStream);
-
-            // Write out with original exif
-            imgModified = new ByteArrayOutputStream();
-            mInterface.writeExif(imgData2, imgModified);
-
-            // Read back in exif and check tags
-            imgData2 = imgModified.toByteArray();
-            imageInputStream = new ByteArrayInputStream(imgData2);
-            mInterface.readExif(imageInputStream);
-            checkTagsAgainstXml(mInterface.getAllTags());
-
-            // Check if bitmap is valid
-            imageInputStream = new ByteArrayInputStream(imgData2);
-            checkBitmap(imageInputStream);
-
-        } catch (Exception e) {
-            throw new Exception(getImageTitle(), e);
-        } finally {
-            Util.closeSilently(imageInputStream);
-        }
-    }
-
-    @MediumTest
-    public void testInterfaceModify() throws Exception {
-
-        // TODO: This test is dependent on galaxy_nexus jpeg/xml file.
-        InputStream imageInputStream = null;
-        try {
-            // Check if bitmap is valid
-            byte[] imgData = Util.readToByteArray(getImageInputStream());
-            imageInputStream = new ByteArrayInputStream(imgData);
-            checkBitmap(imageInputStream);
-
-            // ///////// Exif modifier testing.
-
-            // Read exif and write to temp file
-            imageInputStream = new ByteArrayInputStream(imgData);
-            mInterface.readExif(imageInputStream);
-            mInterface.writeExif(imgData, mTmpFile.getPath());
-
-            // Check if bitmap is valid
-            imageInputStream = new FileInputStream(mTmpFile);
-            checkBitmap(imageInputStream);
-
-            // Create some tags to overwrite with
-            ArrayList<ExifTag> tags = new ArrayList<ExifTag>();
-            tags.add(mInterface.buildTag(ExifInterface.TAG_ORIENTATION,
-                    ExifInterface.Orientation.RIGHT_TOP));
-            tags.add(mInterface.buildTag(ExifInterface.TAG_USER_COMMENT, "goooooooooooooooooogle"));
-
-            // Attempt to rewrite tags
-            assertTrue(getImageTitle(), mInterface.rewriteExif(mTmpFile.getPath(), tags));
-
-            imageInputStream.close();
-            // Check if bitmap is valid
-            imageInputStream = new FileInputStream(mTmpFile);
-            checkBitmap(imageInputStream);
-
-            // Read tags and check against xml
-            mInterface.readExif(mTmpFile.getPath());
-            for (ExifTag t : mInterface.getAllTags()) {
-                short tid = t.getTagId();
-                if (tid != ExifInterface.getTrueTagKey(ExifInterface.TAG_ORIENTATION)
-                        && tid != ExifInterface.getTrueTagKey(ExifInterface.TAG_USER_COMMENT)) {
-                    checkTagAgainstXml(t);
-                }
-            }
-            assertTrue(getImageTitle(), mInterface.getTagIntValue(ExifInterface.TAG_ORIENTATION)
-                    .shortValue() == ExifInterface.Orientation.RIGHT_TOP);
-            String valString = mInterface.getTagStringValue(ExifInterface.TAG_USER_COMMENT);
-            assertTrue(getImageTitle(), valString.equals("goooooooooooooooooogle"));
-
-            // Test forced modify
-
-            // Create some tags to overwrite with
-            tags = new ArrayList<ExifTag>();
-            tags.add(mInterface.buildTag(ExifInterface.TAG_SOFTWARE, "magic super photomaker pro"));
-            tags.add(mInterface.buildTag(ExifInterface.TAG_USER_COMMENT, "noodles"));
-            tags.add(mInterface.buildTag(ExifInterface.TAG_ORIENTATION,
-                    ExifInterface.Orientation.TOP_LEFT));
-
-            // Force rewrite tags
-            mInterface.forceRewriteExif(mTmpFile.getPath(), tags);
-
-            imageInputStream.close();
-            // Check if bitmap is valid
-            imageInputStream = new FileInputStream(mTmpFile);
-            checkBitmap(imageInputStream);
-
-            // Read tags and check against xml
-            mInterface.readExif(mTmpFile.getPath());
-            for (ExifTag t : mInterface.getAllTags()) {
-                short tid = t.getTagId();
-                if (!ExifInterface.isOffsetTag(tid)
-                        && tid != ExifInterface.getTrueTagKey(ExifInterface.TAG_SOFTWARE)
-                        && tid != ExifInterface.getTrueTagKey(ExifInterface.TAG_USER_COMMENT)) {
-                    checkTagAgainstXml(t);
-                }
-            }
-            valString = mInterface.getTagStringValue(ExifInterface.TAG_SOFTWARE);
-            String compareString = "magic super photomaker pro\0";
-            assertTrue(getImageTitle(), valString.equals(compareString));
-            valString = mInterface.getTagStringValue(ExifInterface.TAG_USER_COMMENT);
-            assertTrue(getImageTitle(), valString.equals("noodles"));
-
-        } catch (Exception e) {
-            throw new Exception(getImageTitle(), e);
-        } finally {
-            Util.closeSilently(imageInputStream);
-        }
-    }
-
-    @MediumTest
-    public void testInterfaceDefines() throws Exception {
-
-        InputStream imageInputStream = null;
-        try {
-            // Check if bitmap is valid
-            byte[] imgData = Util.readToByteArray(getImageInputStream());
-            imageInputStream = new ByteArrayInputStream(imgData);
-            checkBitmap(imageInputStream);
-
-            // Set some tags.
-            mInterface.setTags(mTestTags.values());
-
-            // Check tag definitions against default
-            for (Integer i : mTestTags.keySet()) {
-                int check = mTagDefinitions.get(i).intValue();
-                int actual = mInterface.getTagInfo().get(i);
-                assertTrue(check == actual);
-            }
-
-            // Check defines
-            int tag1 = ExifInterface.defineTag(IfdId.TYPE_IFD_1, (short) 42);
-            int tag2 = ExifInterface.defineTag(IfdId.TYPE_IFD_INTEROPERABILITY, (short) 43);
-            assertTrue(tag1 == 0x0001002a);
-            assertTrue(tag2 == 0x0003002b);
-
-            // Define some non-standard tags
-            assertTrue(mInterface.setTagDefinition((short) 42, IfdId.TYPE_IFD_1,
-                    ExifTag.TYPE_UNSIGNED_BYTE, (short) 16, new int[] {
-                        IfdId.TYPE_IFD_1
-                    }) == tag1);
-            assertTrue(mInterface.getTagInfo().get(tag1) == 0x02010010);
-            assertTrue(mInterface.setTagDefinition((short) 43, IfdId.TYPE_IFD_INTEROPERABILITY,
-                    ExifTag.TYPE_ASCII, (short) 5, new int[] {
-                            IfdId.TYPE_IFD_GPS, IfdId.TYPE_IFD_INTEROPERABILITY
-                    }) == tag2);
-            assertTrue(mInterface.getTagInfo().get(tag2) == 0x18020005);
-
-            // Make sure these don't work
-            assertTrue(mInterface.setTagDefinition((short) 42, IfdId.TYPE_IFD_1,
-                    ExifTag.TYPE_UNSIGNED_BYTE, (short) 16, new int[] {
-                        IfdId.TYPE_IFD_0
-                    }) == ExifInterface.TAG_NULL);
-            assertTrue(mInterface.setTagDefinition((short) 42, IfdId.TYPE_IFD_1, (short) 0,
-                    (short) 16, new int[] {
-                        IfdId.TYPE_IFD_1
-                    }) == ExifInterface.TAG_NULL);
-            assertTrue(mInterface.setTagDefinition((short) 42, 5, ExifTag.TYPE_UNSIGNED_BYTE,
-                    (short) 16, new int[] {
-                        5
-                    }) == ExifInterface.TAG_NULL);
-            assertTrue(mInterface.setTagDefinition((short) 42, IfdId.TYPE_IFD_1,
-                    ExifTag.TYPE_UNSIGNED_BYTE, (short) 16, new int[] {
-                        -1
-                    }) == ExifInterface.TAG_NULL);
-            assertTrue(mInterface.setTagDefinition((short) 43, IfdId.TYPE_IFD_GPS,
-                    ExifTag.TYPE_ASCII, (short) 5, new int[] {
-                        IfdId.TYPE_IFD_GPS
-                    }) == ExifInterface.TAG_NULL);
-            assertTrue(mInterface.setTagDefinition((short) 43, IfdId.TYPE_IFD_0,
-                    ExifTag.TYPE_ASCII, (short) 5, new int[] {
-                            IfdId.TYPE_IFD_0, IfdId.TYPE_IFD_GPS
-                    }) == ExifInterface.TAG_NULL);
-
-            // Set some tags
-            mInterface.setTags(mTestTags.values());
-            checkTagsAgainstHash(mInterface.getAllTags(), mTestTags);
-
-            // Make some tags using new defines
-            ExifTag defTag0 = mInterface.buildTag(tag1, new byte[] {
-                    1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16
-            });
-            assertTrue(defTag0 != null);
-            ExifTag defTag1 = mInterface.buildTag(tag2, "hihi");
-            assertTrue(defTag1 != null);
-            ExifTag defTag2 = mInterface.buildTag(tag2, IfdId.TYPE_IFD_GPS, "byte");
-            assertTrue(defTag2 != null);
-
-            // Make sure these don't work
-            ExifTag badTag = mInterface.buildTag(tag1, new byte[] {
-                    1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15
-            });
-            assertTrue(badTag == null);
-            badTag = mInterface.buildTag(tag1, IfdId.TYPE_IFD_0, new byte[] {
-                    1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16
-            });
-            assertTrue(badTag == null);
-            badTag = mInterface.buildTag(0x0002002a, new byte[] {
-                    1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16
-            });
-            assertTrue(badTag == null);
-            badTag = mInterface.buildTag(tag2, new byte[] {
-                    1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17
-            });
-            assertTrue(badTag == null);
-
-            // Set the tags
-            assertTrue(mInterface.setTag(defTag0) == null);
-            assertTrue(mInterface.setTag(defTag1) == null);
-            assertTrue(mInterface.setTag(defTag2) == null);
-            assertTrue(mInterface.setTag(defTag0).equals(defTag0));
-            assertTrue(mInterface.setTag(null) == null);
-            assertTrue(mInterface.setTagValue(tag2, "yoyo") == true);
-            assertTrue(mInterface.setTagValue(tag2, "yaaarggg") == false);
-            assertTrue(mInterface.getTagStringValue(tag2).equals("yoyo\0"));
-
-            // Try writing over bitmap exif
-            ByteArrayOutputStream imgModified = new ByteArrayOutputStream();
-            mInterface.writeExif(imgData, imgModified);
-
-            // Check if bitmap is valid
-            byte[] imgData2 = imgModified.toByteArray();
-            imageInputStream = new ByteArrayInputStream(imgData2);
-            checkBitmap(imageInputStream);
-
-            // Read back in the tags
-            mInterface.readExif(imgData2);
-
-            // Check tags
-            for (ExifTag t : mInterface.getAllTags()) {
-                int tid = t.getTagId();
-                if (tid != ExifInterface.getTrueTagKey(tag1)
-                        && tid != ExifInterface.getTrueTagKey(tag2)) {
-                    checkTagAgainstHash(t, mTestTags);
-                }
-            }
-            assertTrue(Arrays.equals(mInterface.getTagByteValues(tag1), new byte[] {
-                    1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16
-            }));
-            assertTrue(mInterface.getTagStringValue(tag2).equals("yoyo\0"));
-            assertTrue(mInterface.getTagStringValue(tag2, IfdId.TYPE_IFD_GPS).equals("byte\0"));
-
-        } catch (Exception e) {
-            throw new Exception(getImageTitle(), e);
-        } finally {
-            Util.closeSilently(imageInputStream);
-        }
-    }
-
-    @MediumTest
-    public void testInterfaceThumbnails() throws Exception {
-
-        InputStream imageInputStream = null;
-        try {
-            // Check if bitmap is valid
-            byte[] imgData = Util.readToByteArray(getImageInputStream());
-            imageInputStream = new ByteArrayInputStream(imgData);
-            checkBitmap(imageInputStream);
-
-            // Check thumbnails
-            mInterface.readExif(imgData);
-            Bitmap bmap = mInterface.getThumbnailBitmap();
-            assertTrue(getImageTitle(), bmap != null);
-
-            // Make a new thumbnail and set it
-            BitmapFactory.Options opts = new BitmapFactory.Options();
-            opts.inSampleSize = 16;
-            Bitmap thumb = BitmapFactory.decodeByteArray(imgData, 0, imgData.length, opts);
-            assertTrue(getImageTitle(), thumb != null);
-            assertTrue(getImageTitle(), mInterface.setCompressedThumbnail(thumb) == true);
-
-            // Write out image
-            ByteArrayOutputStream outData = new ByteArrayOutputStream();
-            mInterface.writeExif(imgData, outData);
-
-            // Make sure bitmap is still valid
-            byte[] imgData2 = outData.toByteArray();
-            imageInputStream = new ByteArrayInputStream(imgData2);
-            checkBitmap(imageInputStream);
-
-            // Read in bitmap and make sure thumbnail is still valid
-            mInterface.readExif(imgData2);
-            bmap = mInterface.getThumbnailBitmap();
-            assertTrue(getImageTitle(), bmap != null);
-
-        } catch (Exception e) {
-            throw new Exception(getImageTitle(), e);
-        } finally {
-            Util.closeSilently(imageInputStream);
-        }
-    }
-
-    @Override
-    public void setUp() throws Exception {
-        super.setUp();
-        mTmpFile = File.createTempFile("exif_test", ".jpg");
-        mGroundTruth = ExifXmlReader.readXml(getXmlParser());
-
-        mInterface = new ExifInterface();
-
-        // TYPE_UNDEFINED with 4 components
-        mVersionTag = mInterface.buildTag(ExifInterface.TAG_EXIF_VERSION, new byte[] {
-                5, 4, 3, 2
-        });
-        // TYPE_UNSIGNED_BYTE with 4 components
-        mGpsVersionTag = mInterface.buildTag(ExifInterface.TAG_GPS_VERSION_ID, new byte[] {
-                6, 7, 8, 9
-        });
-        // TYPE ASCII with arbitary length
-        mModelTag = mInterface.buildTag(ExifInterface.TAG_MODEL, "helloworld");
-        // TYPE_ASCII with 20 components
-        mDateTimeTag = mInterface.buildTag(ExifInterface.TAG_DATE_TIME, "2013:02:11 20:20:20");
-        // TYPE_UNSIGNED_SHORT with 1 components
-        mCompressionTag = mInterface.buildTag(ExifInterface.TAG_COMPRESSION, 100);
-        // TYPE_UNSIGNED_LONG with 1 components
-        mThumbnailFormatTag =
-                mInterface.buildTag(ExifInterface.TAG_JPEG_INTERCHANGE_FORMAT, 100);
-        // TYPE_UNSIGNED_RATIONAL with 3 components
-        mLongitudeTag = mInterface.buildTag(ExifInterface.TAG_GPS_LONGITUDE, new Rational[] {
-                new Rational(2, 2), new Rational(11, 11),
-                new Rational(102, 102)
-        });
-        // TYPE_RATIONAL with 1 components
-        mShutterTag = mInterface
-                .buildTag(ExifInterface.TAG_SHUTTER_SPEED_VALUE, new Rational(4, 6));
-
-        mTestTags = new HashMap<Integer, ExifTag>();
-
-        mTestTags.put(ExifInterface.TAG_EXIF_VERSION, mVersionTag);
-        mTestTags.put(ExifInterface.TAG_GPS_VERSION_ID, mGpsVersionTag);
-        mTestTags.put(ExifInterface.TAG_MODEL, mModelTag);
-        mTestTags.put(ExifInterface.TAG_DATE_TIME, mDateTimeTag);
-        mTestTags.put(ExifInterface.TAG_COMPRESSION, mCompressionTag);
-        mTestTags.put(ExifInterface.TAG_JPEG_INTERCHANGE_FORMAT, mThumbnailFormatTag);
-        mTestTags.put(ExifInterface.TAG_GPS_LONGITUDE, mLongitudeTag);
-        mTestTags.put(ExifInterface.TAG_SHUTTER_SPEED_VALUE, mShutterTag);
-
-        mTagDefinitions = new HashMap<Integer, Integer>();
-        mTagDefinitions.put(ExifInterface.TAG_EXIF_VERSION, 0x04070004);
-        mTagDefinitions.put(ExifInterface.TAG_GPS_VERSION_ID, 0x10010004);
-        mTagDefinitions.put(ExifInterface.TAG_MODEL, 0x03020000);
-        mTagDefinitions.put(ExifInterface.TAG_DATE_TIME, 0x03020014);
-        mTagDefinitions.put(ExifInterface.TAG_COMPRESSION, 0x03030001);
-        mTagDefinitions.put(ExifInterface.TAG_JPEG_INTERCHANGE_FORMAT, 0x02040001);
-        mTagDefinitions.put(ExifInterface.TAG_GPS_LONGITUDE, 0x100a0003);
-        mTagDefinitions.put(ExifInterface.TAG_SHUTTER_SPEED_VALUE, 0x040a0001);
-    }
-
-    @Override
-    public void tearDown() throws Exception {
-        super.tearDown();
-        mTmpFile.delete();
-    }
-
-    // Helper functions
-
-    private void checkTagAgainstXml(ExifTag tag) {
-        List<String> truth = mGroundTruth.get(tag.getIfd()).get(tag.getTagId());
-
-        if (truth == null) {
-            fail(String.format("Unknown Tag %02x", tag.getTagId()) + ", " + getImageTitle());
-        }
-
-        // No value from exiftool.
-        if (truth.contains(null))
-            return;
-
-        String dataString = Util.tagValueToString(tag).trim();
-        assertTrue(String.format("Tag %02x", tag.getTagId()) + ", " + getImageTitle()
-                + ": " + dataString,
-                truth.contains(dataString));
-    }
-
-    private void checkTagsAgainstXml(List<ExifTag> tags) {
-        for (ExifTag t : tags) {
-            checkTagAgainstXml(t);
-        }
-    }
-
-    private void checkTagAgainstHash(ExifTag tag, Map<Integer, ExifTag> testTags) {
-        int tagdef = mInterface.getTagDefinitionForTag(tag);
-        assertTrue(getImageTitle(), tagdef != ExifInterface.TAG_NULL);
-        ExifTag t = testTags.get(tagdef);
-        // Ignore offset tags & other special tags
-        if (!ExifInterface.sBannedDefines.contains(tag.getTagId())) {
-            assertTrue(getImageTitle(), t != null);
-        } else {
-            return;
-        }
-        if (t == tag)
-            return;
-        assertTrue(getImageTitle(), tag.equals(t));
-        assertTrue(getImageTitle(), tag.getDataType() == t.getDataType());
-        assertTrue(getImageTitle(), tag.getTagId() == t.getTagId());
-        assertTrue(getImageTitle(), tag.getIfd() == t.getIfd());
-        assertTrue(getImageTitle(), tag.getComponentCount() == t.getComponentCount());
-    }
-
-    private void checkTagsAgainstHash(List<ExifTag> tags, Map<Integer, ExifTag> testTags) {
-        for (ExifTag t : tags) {
-            checkTagAgainstHash(t, testTags);
-        }
-    }
-
-    private void checkBitmap(InputStream inputStream) throws IOException {
-        Bitmap bmp = BitmapFactory.decodeStream(inputStream);
-        assertTrue(getImageTitle(), bmp != null);
-    }
-
-}
diff --git a/tests/src/com/android/gallery3d/exif/ExifModifierTest.java b/tests/src/com/android/gallery3d/exif/ExifModifierTest.java
deleted file mode 100644
index 96f405e..0000000
--- a/tests/src/com/android/gallery3d/exif/ExifModifierTest.java
+++ /dev/null
@@ -1,184 +0,0 @@
-/*
- * 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.gallery3d.exif;
-
-import android.test.suitebuilder.annotation.MediumTest;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
-import java.io.InputStream;
-import java.io.RandomAccessFile;
-import java.nio.MappedByteBuffer;
-import java.nio.channels.FileChannel.MapMode;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-public class ExifModifierTest extends ExifXmlDataTestCase {
-
-    private File mTmpFile;
-    private List<Map<Short, List<String>>> mGroundTruth;
-    private ExifInterface mInterface;
-    private Map<Short, ExifTag> mTestTags;
-    ExifTag mVersionTag;
-    ExifTag mGpsVersionTag;
-    ExifTag mModelTag;
-    ExifTag mDateTimeTag;
-    ExifTag mCompressionTag;
-    ExifTag mThumbnailFormatTag;
-    ExifTag mLongitudeTag;
-    ExifTag mShutterTag;
-
-    @Override
-    public void setUp() throws Exception {
-        super.setUp();
-        mGroundTruth = ExifXmlReader.readXml(getXmlParser());
-        mTmpFile = File.createTempFile("exif_test", ".jpg");
-        FileOutputStream os = null;
-        InputStream is = getImageInputStream();
-        try {
-            os = new FileOutputStream(mTmpFile);
-            byte[] buf = new byte[1024];
-            int n;
-            while ((n = is.read(buf)) > 0) {
-                os.write(buf, 0, n);
-            }
-        } finally {
-            Util.closeSilently(os);
-        }
-
-        // TYPE_UNDEFINED with 4 components
-        mVersionTag = mInterface.buildTag(ExifInterface.TAG_EXIF_VERSION, new byte[] {
-                1, 2, 3, 4
-        });
-        // TYPE_UNSIGNED_BYTE with 4 components
-        mGpsVersionTag = mInterface.buildTag(ExifInterface.TAG_GPS_VERSION_ID, new byte[] {
-                4, 3, 2, 1
-        });
-        // TYPE ASCII with arbitary length
-        mModelTag = mInterface.buildTag(ExifInterface.TAG_MODEL, "end-of-the-world");
-        // TYPE_ASCII with 20 components
-        mDateTimeTag = mInterface.buildTag(ExifInterface.TAG_DATE_TIME, "2012:12:31 23:59:59");
-        // TYPE_UNSIGNED_SHORT with 1 components
-        mCompressionTag = mInterface.buildTag(ExifInterface.TAG_COMPRESSION, 100);
-        // TYPE_UNSIGNED_LONG with 1 components
-        mThumbnailFormatTag =
-                mInterface.buildTag(ExifInterface.TAG_JPEG_INTERCHANGE_FORMAT, 100);
-        // TYPE_UNSIGNED_RATIONAL with 3 components
-        mLongitudeTag = mInterface.buildTag(ExifInterface.TAG_GPS_LONGITUDE, new Rational[] {
-                new Rational(1, 1), new Rational(10, 10),
-                new Rational(100, 100)
-        });
-        // TYPE_RATIONAL with 1 components
-        mShutterTag = mInterface
-                .buildTag(ExifInterface.TAG_SHUTTER_SPEED_VALUE, new Rational(1, 1));
-
-        mTestTags = new HashMap<Short, ExifTag>();
-
-        mTestTags.put(mVersionTag.getTagId(), mVersionTag);
-        mTestTags.put(mGpsVersionTag.getTagId(), mGpsVersionTag);
-        mTestTags.put(mModelTag.getTagId(), mModelTag);
-        mTestTags.put(mDateTimeTag.getTagId(), mDateTimeTag);
-        mTestTags.put(mCompressionTag.getTagId(), mCompressionTag);
-        mTestTags.put(mThumbnailFormatTag.getTagId(), mThumbnailFormatTag);
-        mTestTags.put(mLongitudeTag.getTagId(), mLongitudeTag);
-        mTestTags.put(mShutterTag.getTagId(), mShutterTag);
-    }
-
-    public ExifModifierTest(int imageRes, int xmlRes) {
-        super(imageRes, xmlRes);
-        mInterface = new ExifInterface();
-    }
-
-    public ExifModifierTest(String imagePath, String xmlPath) {
-        super(imagePath, xmlPath);
-        mInterface = new ExifInterface();
-    }
-
-    @MediumTest
-    public void testModify() throws Exception {
-        Map<Short, Boolean> results = new HashMap<Short, Boolean>();
-
-        RandomAccessFile file = null;
-        try {
-            file = new RandomAccessFile(mTmpFile, "rw");
-            MappedByteBuffer buf = file.getChannel().map(MapMode.READ_WRITE, 0, file.length());
-            for (ExifTag tag : mTestTags.values()) {
-                ExifModifier modifier = new ExifModifier(buf, mInterface);
-                modifier.modifyTag(tag);
-                boolean result = modifier.commit();
-                results.put(tag.getTagId(), result);
-                buf.force();
-                buf.position(0);
-
-                if (!result) {
-                    List<String> value = mGroundTruth.get(tag.getIfd()).get(tag.getTagId());
-                    assertTrue(String.format("Tag %x, ", tag.getTagId()) + getImageTitle(),
-                            value == null || tag.getTagId() == ExifInterface.TAG_MODEL);
-                }
-            }
-        } finally {
-            Util.closeSilently(file);
-        }
-
-        // Parse the new file and check the result
-        InputStream is = null;
-        try {
-            is = new FileInputStream(mTmpFile);
-            ExifData data = new ExifReader(mInterface).read(is);
-            for (int i = 0; i < IfdId.TYPE_IFD_COUNT; i++) {
-                checkIfd(data.getIfdData(i), mGroundTruth.get(i), results);
-            }
-        } finally {
-            Util.closeSilently(is);
-        }
-
-    }
-
-    private void checkIfd(IfdData ifd, Map<Short, List<String>> ifdValue,
-            Map<Short, Boolean> results) {
-        if (ifd == null) {
-            assertEquals(getImageTitle(), 0, ifdValue.size());
-            return;
-        }
-        ExifTag[] tags = ifd.getAllTags();
-        for (ExifTag tag : tags) {
-            List<String> truth = ifdValue.get(tag.getTagId());
-            assertNotNull(String.format("Tag %x, ", tag.getTagId()) + getImageTitle(), truth);
-            if (truth.contains(null)) {
-                continue;
-            }
-
-            ExifTag newTag = mTestTags.get(tag.getTagId());
-            if (newTag != null
-                    && results.get(tag.getTagId())) {
-                assertEquals(String.format("Tag %x, ", tag.getTagId()) + getImageTitle(),
-                        Util.tagValueToString(newTag), Util.tagValueToString(tag));
-            } else {
-                assertTrue(String.format("Tag %x, ", tag.getTagId()) + getImageTitle(),
-                        truth.contains(Util.tagValueToString(tag).trim()));
-            }
-        }
-        assertEquals(getImageTitle(), ifdValue.size(), tags.length);
-    }
-
-    @Override
-    public void tearDown() throws Exception {
-        super.tearDown();
-        mTmpFile.delete();
-    }
-}
diff --git a/tests/src/com/android/gallery3d/exif/ExifOutputStreamTest.java b/tests/src/com/android/gallery3d/exif/ExifOutputStreamTest.java
deleted file mode 100644
index 151bdbc..0000000
--- a/tests/src/com/android/gallery3d/exif/ExifOutputStreamTest.java
+++ /dev/null
@@ -1,198 +0,0 @@
-/*
- * 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.gallery3d.exif;
-
-import android.test.suitebuilder.annotation.MediumTest;
-
-import android.graphics.Bitmap;
-import android.graphics.BitmapFactory;
-import android.util.Log;
-
-import java.io.ByteArrayInputStream;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
-import java.io.InputStream;
-import java.io.OutputStream;
-
-public class ExifOutputStreamTest extends ExifXmlDataTestCase {
-
-    private File mTmpFile;
-
-    private ExifInterface mInterface;
-
-    @Override
-    public void setUp() throws Exception {
-        super.setUp();
-        mTmpFile = File.createTempFile("exif_test", ".jpg");
-    }
-
-    public ExifOutputStreamTest(int imgRes, int xmlRes) {
-        super(imgRes, xmlRes);
-        mInterface = new ExifInterface();
-    }
-
-    public ExifOutputStreamTest(String imgPath, String xmlPath) {
-        super(imgPath, xmlPath);
-        mInterface = new ExifInterface();
-    }
-
-    @MediumTest
-    public void testExifOutputStream() throws Exception {
-        InputStream imageInputStream = null;
-        InputStream exifInputStream = null;
-        FileInputStream reDecodeInputStream = null;
-        FileInputStream reParseInputStream = null;
-
-        InputStream dangerInputStream = null;
-        OutputStream dangerOutputStream = null;
-        try {
-            try {
-                byte[] imgData = Util.readToByteArray(getImageInputStream());
-                imageInputStream = new ByteArrayInputStream(imgData);
-                exifInputStream = new ByteArrayInputStream(imgData);
-
-                // Read the image data
-                Bitmap bmp = BitmapFactory.decodeStream(imageInputStream);
-                // The image is invalid
-                if (bmp == null) {
-                    return;
-                }
-
-                // Read exif data
-                ExifData exifData = new ExifReader(mInterface).read(exifInputStream);
-
-                // Encode the image with the exif data
-                FileOutputStream outputStream = new FileOutputStream(mTmpFile);
-                ExifOutputStream exifOutputStream = new ExifOutputStream(outputStream, mInterface);
-                exifOutputStream.setExifData(exifData);
-                bmp.compress(Bitmap.CompressFormat.JPEG, 90, exifOutputStream);
-                exifOutputStream.close();
-                exifOutputStream = null;
-
-                // Re-decode the temp file and check the data.
-                reDecodeInputStream = new FileInputStream(mTmpFile);
-                Bitmap decodedBmp = BitmapFactory.decodeStream(reDecodeInputStream);
-                assertNotNull(getImageTitle(), decodedBmp);
-                reDecodeInputStream.close();
-
-                // Re-parse the temp file the check EXIF tag
-                reParseInputStream = new FileInputStream(mTmpFile);
-                ExifData reExifData = new ExifReader(mInterface).read(reParseInputStream);
-                assertEquals(getImageTitle(), exifData, reExifData);
-                reParseInputStream.close();
-
-                // Try writing exif to file with existing exif.
-                dangerOutputStream = (OutputStream) new FileOutputStream(mTmpFile);
-                exifOutputStream = new ExifOutputStream(dangerOutputStream, mInterface);
-                exifOutputStream.setExifData(exifData);
-                exifOutputStream.write(imgData);
-                // exifOutputStream.write(strippedImgData);
-                exifOutputStream.close();
-                exifOutputStream = null;
-
-                // Make sure it still can be parsed into a bitmap.
-                dangerInputStream = (InputStream) new FileInputStream(mTmpFile);
-                decodedBmp = null;
-                decodedBmp = BitmapFactory.decodeStream(dangerInputStream);
-                assertNotNull(getImageTitle(), decodedBmp);
-                dangerInputStream.close();
-                dangerInputStream = null;
-
-                // Make sure exif is still well-formatted.
-                dangerInputStream = (InputStream) new FileInputStream(mTmpFile);
-                reExifData = null;
-                reExifData = new ExifReader(mInterface).read(dangerInputStream);
-                assertEquals(getImageTitle(), exifData, reExifData);
-                dangerInputStream.close();
-                dangerInputStream = null;
-
-            } finally {
-                Util.closeSilently(imageInputStream);
-                Util.closeSilently(exifInputStream);
-                Util.closeSilently(reDecodeInputStream);
-                Util.closeSilently(reParseInputStream);
-
-                Util.closeSilently(dangerInputStream);
-                Util.closeSilently(dangerOutputStream);
-            }
-        } catch (Exception e) {
-            throw new Exception(getImageTitle(), e);
-        }
-    }
-
-    @MediumTest
-    public void testOutputSpeed() throws Exception {
-        final String LOGTAG = "testOutputSpeed";
-        InputStream imageInputStream = null;
-        OutputStream imageOutputStream = null;
-        try {
-            try {
-                imageInputStream = getImageInputStream();
-                // Read the image data
-                Bitmap bmp = BitmapFactory.decodeStream(imageInputStream);
-                // The image is invalid
-                if (bmp == null) {
-                    return;
-                }
-                imageInputStream.close();
-                int nLoops = 20;
-                long totalReadDuration = 0;
-                long totalWriteDuration = 0;
-                for (int i = 0; i < nLoops; i++) {
-                    imageInputStream = reopenFileStream();
-                    // Read exif data
-                    long startTime = System.nanoTime();
-                    ExifData exifData = new ExifReader(mInterface).read(imageInputStream);
-                    long endTime = System.nanoTime();
-                    long duration = endTime - startTime;
-                    totalReadDuration += duration;
-                    Log.v(LOGTAG, " read time: " + duration);
-                    imageInputStream.close();
-
-                    // Encode the image with the exif data
-                    imageOutputStream = (OutputStream) new FileOutputStream(mTmpFile);
-                    ExifOutputStream exifOutputStream = new ExifOutputStream(imageOutputStream,
-                            mInterface);
-                    exifOutputStream.setExifData(exifData);
-                    startTime = System.nanoTime();
-                    bmp.compress(Bitmap.CompressFormat.JPEG, 90, exifOutputStream);
-                    endTime = System.nanoTime();
-                    duration = endTime - startTime;
-                    totalWriteDuration += duration;
-                    Log.v(LOGTAG, " write time: " + duration);
-                    exifOutputStream.close();
-                }
-                Log.v(LOGTAG, "======================= normal");
-                Log.v(LOGTAG, "avg read time: " + totalReadDuration / nLoops);
-                Log.v(LOGTAG, "avg write time: " + totalWriteDuration / nLoops);
-                Log.v(LOGTAG, "=======================");
-            } finally {
-                Util.closeSilently(imageInputStream);
-                Util.closeSilently(imageOutputStream);
-            }
-        } catch (Exception e) {
-            throw new Exception(getImageTitle(), e);
-        }
-    }
-
-    @Override
-    public void tearDown() throws Exception {
-        super.tearDown();
-        mTmpFile.delete();
-    }
-}
diff --git a/tests/src/com/android/gallery3d/exif/ExifParserTest.java b/tests/src/com/android/gallery3d/exif/ExifParserTest.java
deleted file mode 100644
index 247ea02..0000000
--- a/tests/src/com/android/gallery3d/exif/ExifParserTest.java
+++ /dev/null
@@ -1,243 +0,0 @@
-/*
- * 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.gallery3d.exif;
-
-import android.test.suitebuilder.annotation.MediumTest;
-
-import android.graphics.Bitmap;
-import android.graphics.BitmapFactory;
-
-import java.util.List;
-import java.util.Map;
-
-public class ExifParserTest extends ExifXmlDataTestCase {
-    private static final String TAG = "ExifParserTest";
-
-    private ExifInterface mInterface;
-
-    public ExifParserTest(int imgRes, int xmlRes) {
-        super(imgRes, xmlRes);
-        mInterface = new ExifInterface();
-    }
-
-    public ExifParserTest(String imgPath, String xmlPath) {
-        super(imgPath, xmlPath);
-        mInterface = new ExifInterface();
-    }
-
-    private List<Map<Short, List<String>>> mGroundTruth;
-
-    @Override
-    public void setUp() throws Exception {
-        super.setUp();
-        mGroundTruth = ExifXmlReader.readXml(getXmlParser());
-    }
-
-    @MediumTest
-    public void testParse() throws Exception {
-        try {
-            ExifParser parser = ExifParser.parse(getImageInputStream(), mInterface);
-            int event = parser.next();
-            while (event != ExifParser.EVENT_END) {
-                switch (event) {
-                    case ExifParser.EVENT_START_OF_IFD:
-                        break;
-                    case ExifParser.EVENT_NEW_TAG:
-                        ExifTag tag = parser.getTag();
-                        if (!tag.hasValue()) {
-                            parser.registerForTagValue(tag);
-                        } else {
-                            checkTag(tag);
-                        }
-                        break;
-                    case ExifParser.EVENT_VALUE_OF_REGISTERED_TAG:
-                        tag = parser.getTag();
-                        if (tag.getDataType() == ExifTag.TYPE_UNDEFINED) {
-                            byte[] buf = new byte[tag.getComponentCount()];
-                            parser.read(buf);
-                            assertTrue(TAG, tag.setValue(buf));
-                        }
-                        checkTag(tag);
-                        break;
-                }
-                event = parser.next();
-            }
-        } catch (Exception e) {
-            throw new Exception(getImageTitle(), e);
-        }
-    }
-
-    private void checkTag(ExifTag tag) {
-        List<String> truth = mGroundTruth.get(tag.getIfd()).get(tag.getTagId());
-
-        if (truth == null) {
-            fail(String.format("Unknown Tag %02x", tag.getTagId()) + ", " + getImageTitle());
-        }
-
-        // No value from exiftool.
-        if (truth.contains(null)) {
-            return;
-        }
-
-        String dataString = Util.tagValueToString(tag).trim();
-        assertTrue(String.format("Tag %02x", tag.getTagId()) + ", " + getImageTitle()
-                + ": " + dataString,
-                truth.contains(dataString));
-    }
-
-    private void parseOneIfd(int ifd, int options) throws Exception {
-        try {
-            Map<Short, List<String>> expectedResult = mGroundTruth.get(ifd);
-            int numOfTag = 0;
-            ExifParser parser = ExifParser.parse(getImageInputStream(), options, mInterface);
-            int event = parser.next();
-            while (event != ExifParser.EVENT_END) {
-                switch (event) {
-                    case ExifParser.EVENT_START_OF_IFD:
-                        assertEquals(getImageTitle(), ifd, parser.getCurrentIfd());
-                        break;
-                    case ExifParser.EVENT_NEW_TAG:
-                        ExifTag tag = parser.getTag();
-                        numOfTag++;
-                        if (tag.hasValue()) {
-                            checkTag(tag);
-                        } else {
-                            parser.registerForTagValue(tag);
-                        }
-                        break;
-                    case ExifParser.EVENT_VALUE_OF_REGISTERED_TAG:
-                        tag = parser.getTag();
-                        if (tag.getDataType() == ExifTag.TYPE_UNDEFINED) {
-                            byte[] buf = new byte[tag.getComponentCount()];
-                            parser.read(buf);
-                            tag.setValue(buf);
-                        }
-                        checkTag(tag);
-                        break;
-                    case ExifParser.EVENT_COMPRESSED_IMAGE:
-                    case ExifParser.EVENT_UNCOMPRESSED_STRIP:
-                        fail("Invalid Event type: " + event + ", " + getImageTitle());
-                        break;
-                }
-                event = parser.next();
-            }
-            assertEquals(getImageTitle(), ExifXmlReader.getTrueTagNumber(expectedResult), numOfTag);
-        } catch (Exception e) {
-            throw new Exception(getImageTitle(), e);
-        }
-    }
-
-    @MediumTest
-    public void testOnlyExifIfd() throws Exception {
-        parseOneIfd(IfdId.TYPE_IFD_EXIF, ExifParser.OPTION_IFD_EXIF);
-    }
-
-    @MediumTest
-    public void testOnlyIfd0() throws Exception {
-        parseOneIfd(IfdId.TYPE_IFD_0, ExifParser.OPTION_IFD_0);
-    }
-
-    @MediumTest
-    public void testOnlyIfd1() throws Exception {
-        parseOneIfd(IfdId.TYPE_IFD_1, ExifParser.OPTION_IFD_1);
-    }
-
-    @MediumTest
-    public void testOnlyInteroperabilityIfd() throws Exception {
-        parseOneIfd(IfdId.TYPE_IFD_INTEROPERABILITY, ExifParser.OPTION_IFD_INTEROPERABILITY);
-    }
-
-    @MediumTest
-    public void testOnlyReadSomeTag() throws Exception {
-        // Do not do this test if there is no model tag.
-        if (mGroundTruth.get(IfdId.TYPE_IFD_0).get(ExifInterface.TAG_MODEL) == null) {
-            return;
-        }
-
-        try {
-            ExifParser parser = ExifParser.parse(getImageInputStream(), ExifParser.OPTION_IFD_0,
-                    mInterface);
-            int event = parser.next();
-            boolean isTagFound = false;
-            while (event != ExifParser.EVENT_END) {
-                switch (event) {
-                    case ExifParser.EVENT_START_OF_IFD:
-                        assertEquals(getImageTitle(), IfdId.TYPE_IFD_0, parser.getCurrentIfd());
-                        break;
-                    case ExifParser.EVENT_NEW_TAG:
-                        ExifTag tag = parser.getTag();
-                        if (tag.getTagId() == ExifInterface.TAG_MODEL) {
-                            if (tag.hasValue()) {
-                                isTagFound = true;
-                                checkTag(tag);
-                            } else {
-                                parser.registerForTagValue(tag);
-                            }
-                            parser.skipRemainingTagsInCurrentIfd();
-                        }
-                        break;
-                    case ExifParser.EVENT_VALUE_OF_REGISTERED_TAG:
-                        tag = parser.getTag();
-                        assertEquals(getImageTitle(), ExifInterface.TAG_MODEL, tag.getTagId());
-                        checkTag(tag);
-                        isTagFound = true;
-                        break;
-                }
-                event = parser.next();
-            }
-            assertTrue(getImageTitle(), isTagFound);
-        } catch (Exception e) {
-            throw new Exception(getImageTitle(), e);
-        }
-    }
-
-    @MediumTest
-    public void testReadThumbnail() throws Exception {
-        try {
-            ExifParser parser = ExifParser.parse(getImageInputStream(),
-                    ExifParser.OPTION_IFD_1 | ExifParser.OPTION_THUMBNAIL, mInterface);
-
-            int event = parser.next();
-            Bitmap bmp = null;
-            boolean mIsContainCompressedImage = false;
-            while (event != ExifParser.EVENT_END) {
-                switch (event) {
-                    case ExifParser.EVENT_NEW_TAG:
-                        ExifTag tag = parser.getTag();
-                        if (tag.getTagId() == ExifInterface.TAG_COMPRESSION) {
-                            if (tag.getValueAt(0) == ExifInterface.Compression.JPEG) {
-                                mIsContainCompressedImage = true;
-                            }
-                        }
-                        break;
-                    case ExifParser.EVENT_COMPRESSED_IMAGE:
-                        int imageSize = parser.getCompressedImageSize();
-                        byte buf[] = new byte[imageSize];
-                        parser.read(buf);
-                        bmp = BitmapFactory.decodeByteArray(buf, 0, imageSize);
-                        break;
-                }
-                event = parser.next();
-            }
-            if (mIsContainCompressedImage) {
-                assertNotNull(getImageTitle(), bmp);
-            }
-        } catch (Exception e) {
-            throw new Exception(getImageTitle(), e);
-        }
-    }
-}
diff --git a/tests/src/com/android/gallery3d/exif/ExifReaderTest.java b/tests/src/com/android/gallery3d/exif/ExifReaderTest.java
deleted file mode 100644
index 4b5c029..0000000
--- a/tests/src/com/android/gallery3d/exif/ExifReaderTest.java
+++ /dev/null
@@ -1,165 +0,0 @@
-/*
- * 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.gallery3d.exif;
-
-import android.test.suitebuilder.annotation.MediumTest;
-
-import android.graphics.BitmapFactory;
-
-import java.util.List;
-import java.util.Map;
-
-public class ExifReaderTest extends ExifXmlDataTestCase {
-    private static final String TAG = "ExifReaderTest";
-
-    private ExifInterface mInterface;
-    private List<Map<Short, List<String>>> mGroundTruth;
-
-    @Override
-    public void setUp() throws Exception {
-        super.setUp();
-        mGroundTruth = ExifXmlReader.readXml(getXmlParser());
-    }
-
-    public ExifReaderTest(int imgRes, int xmlRes) {
-        super(imgRes, xmlRes);
-        mInterface = new ExifInterface();
-    }
-
-    public ExifReaderTest(String imgPath, String xmlPath) {
-        super(imgPath, xmlPath);
-        mInterface = new ExifInterface();
-    }
-
-    @MediumTest
-    public void testRead() throws Exception {
-        try {
-            ExifReader reader = new ExifReader(mInterface);
-            ExifData exifData = reader.read(getImageInputStream());
-            for (int i = 0; i < IfdId.TYPE_IFD_COUNT; i++) {
-                checkIfd(exifData.getIfdData(i), mGroundTruth.get(i));
-            }
-            checkThumbnail(exifData);
-        } catch (Exception e) {
-            throw new Exception(getImageTitle(), e);
-        }
-    }
-
-    private void checkThumbnail(ExifData exifData) {
-        Map<Short, List<String>> ifd1Truth = mGroundTruth.get(IfdId.TYPE_IFD_1);
-
-        List<String> typeTagValue = ifd1Truth.get(ExifInterface.TAG_COMPRESSION);
-        if (typeTagValue == null)
-            return;
-
-        IfdData ifd1 = exifData.getIfdData(IfdId.TYPE_IFD_1);
-        if (ifd1 == null)
-            fail(getImageTitle() + ": failed to find IFD1");
-
-        String typeTagTruth = typeTagValue.get(0);
-
-        int type = (int) ifd1.getTag(ExifInterface.getTrueTagKey(ExifInterface.TAG_COMPRESSION))
-                .getValueAt(0);
-
-        if (String.valueOf(ExifInterface.Compression.JPEG).equals(typeTagTruth)) {
-            assertTrue(getImageTitle(), type == ExifInterface.Compression.JPEG);
-            assertTrue(getImageTitle(), exifData.hasCompressedThumbnail());
-            byte[] thumbnail = exifData.getCompressedThumbnail();
-            assertTrue(getImageTitle(),
-                    BitmapFactory.decodeByteArray(thumbnail, 0, thumbnail.length) != null);
-        } else if (String.valueOf(ExifInterface.Compression.UNCOMPRESSION).equals(typeTagTruth)) {
-            assertTrue(getImageTitle(), type == ExifInterface.Compression.UNCOMPRESSION);
-            // Try to check the strip count with the formula provided by EXIF spec.
-            int planarType = ExifInterface.PlanarConfiguration.CHUNKY;
-            ExifTag planarTag = ifd1.getTag(ExifInterface
-                    .getTrueTagKey(ExifInterface.TAG_PLANAR_CONFIGURATION));
-            if (planarTag != null) {
-                planarType = (int) planarTag.getValueAt(0);
-            }
-
-            if (!ifd1Truth.containsKey(ExifInterface.TAG_IMAGE_LENGTH) ||
-                    !ifd1Truth.containsKey(ExifInterface.TAG_ROWS_PER_STRIP)) {
-                return;
-            }
-
-            ExifTag heightTag = ifd1.getTag(ExifInterface
-                    .getTrueTagKey(ExifInterface.TAG_IMAGE_LENGTH));
-            ExifTag rowPerStripTag = ifd1.getTag(ExifInterface
-                    .getTrueTagKey(ExifInterface.TAG_ROWS_PER_STRIP));
-
-            // Fail the test if required tags are missing
-            if (heightTag == null || rowPerStripTag == null) {
-                fail(getImageTitle());
-            }
-
-            int imageLength = (int) heightTag.getValueAt(0);
-            int rowsPerStrip = (int) rowPerStripTag.getValueAt(0);
-            int stripCount = ifd1.getTag(
-                    ExifInterface.getTrueTagKey(ExifInterface.TAG_STRIP_OFFSETS))
-                    .getComponentCount();
-
-            if (planarType == ExifInterface.PlanarConfiguration.CHUNKY) {
-                assertTrue(getImageTitle(),
-                        stripCount == (imageLength + rowsPerStrip - 1) / rowsPerStrip);
-            } else {
-                if (!ifd1Truth.containsKey(ExifInterface.TAG_SAMPLES_PER_PIXEL)) {
-                    return;
-                }
-                ExifTag samplePerPixelTag = ifd1.getTag(ExifInterface
-                        .getTrueTagKey(ExifInterface.TAG_SAMPLES_PER_PIXEL));
-                int samplePerPixel = (int) samplePerPixelTag.getValueAt(0);
-                assertTrue(getImageTitle(),
-                        stripCount ==
-                        (imageLength + rowsPerStrip - 1) / rowsPerStrip * samplePerPixel);
-            }
-
-            if (!ifd1Truth.containsKey(ExifInterface.TAG_STRIP_BYTE_COUNTS)) {
-                return;
-            }
-            ExifTag byteCountTag = ifd1.getTag(ExifInterface
-                    .getTrueTagKey(ExifInterface.TAG_STRIP_BYTE_COUNTS));
-            short byteCountDataType = byteCountTag.getDataType();
-            for (int i = 0; i < stripCount; i++) {
-                if (byteCountDataType == ExifTag.TYPE_UNSIGNED_SHORT) {
-                    assertEquals(getImageTitle(),
-                            byteCountTag.getValueAt(i), exifData.getStrip(i).length);
-                } else {
-                    assertEquals(getImageTitle(),
-                            byteCountTag.getValueAt(i), exifData.getStrip(i).length);
-                }
-            }
-        }
-    }
-
-    private void checkIfd(IfdData ifd, Map<Short, List<String>> ifdValue) {
-        if (ifd == null) {
-            assertEquals(getImageTitle(), 0, ifdValue.size());
-            return;
-        }
-        ExifTag[] tags = ifd.getAllTags();
-        for (ExifTag tag : tags) {
-            List<String> truth = ifdValue.get(tag.getTagId());
-            assertNotNull(String.format("Tag %x, ", tag.getTagId()) + getImageTitle(), truth);
-            if (truth.contains(null)) {
-                continue;
-            }
-            assertTrue(String.format("Tag %x, ", tag.getTagId()) + getImageTitle(),
-                    truth.contains(Util.tagValueToString(tag).trim()));
-        }
-        assertEquals(getImageTitle(), ifdValue.size(), tags.length);
-    }
-}
diff --git a/tests/src/com/android/gallery3d/exif/ExifTagTest.java b/tests/src/com/android/gallery3d/exif/ExifTagTest.java
deleted file mode 100644
index e6a41ec..0000000
--- a/tests/src/com/android/gallery3d/exif/ExifTagTest.java
+++ /dev/null
@@ -1,219 +0,0 @@
-/*
- * 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.gallery3d.exif;
-
-import android.test.suitebuilder.annotation.SmallTest;
-
-import junit.framework.TestCase;
-
-import java.util.HashMap;
-import java.util.Map;
-
-public class ExifTagTest extends TestCase {
-
-    private static long MAX_UNSIGNED_LONG = (1L << 32) - 1;
-    private static int MAX_LONG = Integer.MAX_VALUE;
-    private static int MIN_LONG = Integer.MIN_VALUE;
-
-    Map<Integer, ExifTag> mTestTags;
-    ExifInterface mInterface;
-    private ExifTag mVersionTag;
-    private ExifTag mGpsVersionTag;
-    private ExifTag mModelTag;
-    private ExifTag mDateTimeTag;
-    private ExifTag mCompressionTag;
-    private ExifTag mThumbnailFormatTag;
-    private ExifTag mLongitudeTag;
-    private ExifTag mShutterTag;
-    private ExifTag mInteropIndex;
-
-    @Override
-    public void setUp() throws Exception {
-        super.setUp();
-        mInterface = new ExifInterface();
-
-        // TYPE_UNDEFINED with 4 components
-        mVersionTag = mInterface.buildTag(ExifInterface.TAG_EXIF_VERSION, new byte[] {
-                5, 4, 3, 2
-        });
-        // TYPE_UNSIGNED_BYTE with 4 components
-        mGpsVersionTag = mInterface.buildTag(ExifInterface.TAG_GPS_VERSION_ID, new byte[] {
-                6, 7, 8, 9
-        });
-        // TYPE ASCII with arbitrary length
-        mModelTag = mInterface.buildTag(ExifInterface.TAG_MODEL, "helloworld");
-        // TYPE_ASCII with 20 components
-        mDateTimeTag = mInterface.buildTag(ExifInterface.TAG_DATE_TIME, "2013:02:11 20:20:20");
-        // TYPE_UNSIGNED_SHORT with 1 components
-        mCompressionTag = mInterface.buildTag(ExifInterface.TAG_COMPRESSION, 100);
-        // TYPE_UNSIGNED_LONG with 1 components
-        mThumbnailFormatTag =
-                mInterface.buildTag(ExifInterface.TAG_JPEG_INTERCHANGE_FORMAT, 100);
-        // TYPE_UNSIGNED_RATIONAL with 3 components
-        mLongitudeTag = mInterface.buildTag(ExifInterface.TAG_GPS_LONGITUDE, new Rational[] {
-                new Rational(2, 2), new Rational(11, 11),
-                new Rational(102, 102)
-        });
-        // TYPE_RATIONAL with 1 components
-        mShutterTag = mInterface
-                .buildTag(ExifInterface.TAG_SHUTTER_SPEED_VALUE, new Rational(4, 6));
-        // TYPE_ASCII with arbitrary length
-        mInteropIndex = mInterface.buildTag(ExifInterface.TAG_INTEROPERABILITY_INDEX, "foo");
-
-        mTestTags = new HashMap<Integer, ExifTag>();
-
-        mTestTags.put(ExifInterface.TAG_EXIF_VERSION, mVersionTag);
-        mTestTags.put(ExifInterface.TAG_GPS_VERSION_ID, mGpsVersionTag);
-        mTestTags.put(ExifInterface.TAG_MODEL, mModelTag);
-        mTestTags.put(ExifInterface.TAG_DATE_TIME, mDateTimeTag);
-        mTestTags.put(ExifInterface.TAG_COMPRESSION, mCompressionTag);
-        mTestTags.put(ExifInterface.TAG_JPEG_INTERCHANGE_FORMAT, mThumbnailFormatTag);
-        mTestTags.put(ExifInterface.TAG_GPS_LONGITUDE, mLongitudeTag);
-        mTestTags.put(ExifInterface.TAG_SHUTTER_SPEED_VALUE, mShutterTag);
-        mTestTags.put(ExifInterface.TAG_INTEROPERABILITY_INDEX, mInteropIndex);
-    }
-
-    @Override
-    public void tearDown() throws Exception {
-        super.tearDown();
-        mInterface = null;
-        mTestTags = null;
-    }
-
-    @SmallTest
-    public void testValueType() {
-        for (ExifTag tag : mTestTags.values()) {
-            assertTrue(tag != null);
-            int count = tag.getComponentCount();
-            int intBuf[] = new int[count];
-            long longBuf[] = new long[count];
-            byte byteBuf[] = new byte[count];
-            Rational rationalBuf[] = new Rational[count];
-            StringBuilder sb = new StringBuilder();
-            for (int i = 0; i < count; i++) {
-                intBuf[i] = 0;
-                longBuf[i] = 0;
-                byteBuf[i] = 0;
-                rationalBuf[i] = new Rational(0, 0);
-                // The string size should equal to component count - 1
-                if (i != count - 1) {
-                    sb.append("*");
-                } else {
-                    sb.append("\0");
-                }
-            }
-            String strBuf = sb.toString();
-
-            checkTypeByte(tag, byteBuf);
-            checkTypeAscii(tag, strBuf);
-            checkTypeUnsignedShort(tag, intBuf);
-            checkTypeUnsignedLong(tag, intBuf, longBuf);
-            checkTypeLong(tag, intBuf);
-            checkTypeRational(tag, rationalBuf);
-            checkTypeUnsignedRational(tag, rationalBuf);
-        }
-    }
-
-    private void checkTypeByte(ExifTag tag, byte[] buf) {
-        short type = tag.getDataType();
-        assertFalse("\nTag: " + tag.toString(), tag.setValue(buf)
-                ^ (type == ExifTag.TYPE_UNDEFINED || type == ExifTag.TYPE_UNSIGNED_BYTE));
-    }
-
-    private void checkTypeAscii(ExifTag tag, String str) {
-        short type = tag.getDataType();
-        assertFalse("\nTag: " + tag.toString(), tag.setValue(str)
-                ^ (type == ExifTag.TYPE_ASCII || type == ExifTag.TYPE_UNDEFINED));
-    }
-
-    private void checkTypeUnsignedShort(ExifTag tag, int[] intBuf) {
-        short type = tag.getDataType();
-        assertFalse("\nTag: " + tag.toString(),
-                tag.setValue(intBuf)
-                        ^ (type == ExifTag.TYPE_UNSIGNED_SHORT
-                                || type == ExifTag.TYPE_UNSIGNED_LONG
-                                || type == ExifTag.TYPE_LONG));
-    }
-
-    private void checkTypeUnsignedLong(ExifTag tag, int[] intBuf, long[] longBuf) {
-
-        // Test value only for unsigned long.
-        int count = intBuf.length;
-        intBuf[count - 1] = MAX_LONG;
-        tag.setValue(intBuf);
-        longBuf[count - 1] = MAX_UNSIGNED_LONG;
-
-        assertFalse("\nTag: " + tag.toString(), tag.setValue(longBuf)
-                ^ (tag.getDataType() == ExifTag.TYPE_UNSIGNED_LONG));
-
-        intBuf[count - 1] = 0;
-        // Test invalid value for all type.
-        longBuf[count - 1] = MAX_UNSIGNED_LONG + 1;
-        assertFalse(tag.setValue(longBuf));
-        longBuf[count - 1] = 0;
-    }
-
-    private void checkTypeLong(ExifTag tag, int[] intBuf) {
-        int count = intBuf.length;
-        intBuf[count - 1] = MAX_LONG;
-        tag.setValue(intBuf);
-        intBuf[count - 1] = MIN_LONG;
-
-        assertFalse("\nTag: " + tag.toString(), tag.setValue(intBuf)
-                ^ (tag.getDataType() == ExifTag.TYPE_LONG));
-        intBuf[count - 1] = 0;
-    }
-
-    private void checkTypeRational(ExifTag tag, Rational rationalBuf[]) {
-        int count = rationalBuf.length;
-        Rational r = rationalBuf[count - 1];
-        rationalBuf[count - 1] = new Rational(MAX_LONG, MIN_LONG);
-
-        assertFalse("\nTag: " + tag.toString(), tag.setValue(rationalBuf)
-                ^ (tag.getDataType() == ExifTag.TYPE_RATIONAL));
-
-        if (tag.getDataType() == ExifTag.TYPE_RATIONAL) {
-            // check overflow
-
-            rationalBuf[count - 1] = new Rational(MAX_LONG + 1L, MIN_LONG);
-            assertFalse(tag.setValue(rationalBuf));
-
-            rationalBuf[count - 1] = new Rational(MAX_LONG, MIN_LONG - 1L);
-            assertFalse(tag.setValue(rationalBuf));
-        }
-        rationalBuf[count - 1] = r;
-    }
-
-    private void checkTypeUnsignedRational(ExifTag tag, Rational rationalBuf[]) {
-        int count = rationalBuf.length;
-        Rational r = rationalBuf[count - 1];
-        rationalBuf[count - 1] = new Rational(MAX_UNSIGNED_LONG, MAX_UNSIGNED_LONG);
-
-        assertFalse("\nTag: " + tag.toString(), tag.setValue(rationalBuf)
-                ^ (tag.getDataType() == ExifTag.TYPE_UNSIGNED_RATIONAL));
-
-        if (tag.getDataType() == ExifTag.TYPE_UNSIGNED_RATIONAL) {
-            // check overflow
-            rationalBuf[count - 1] = new Rational(MAX_UNSIGNED_LONG + 1, 0);
-            assertFalse(tag.setValue(rationalBuf));
-
-            rationalBuf[count - 1] = new Rational(MAX_UNSIGNED_LONG, -1);
-            assertFalse(tag.setValue(rationalBuf));
-        }
-        rationalBuf[count - 1] = r;
-    }
-}
diff --git a/tests/src/com/android/gallery3d/exif/ExifTestRunner.java b/tests/src/com/android/gallery3d/exif/ExifTestRunner.java
deleted file mode 100644
index 162baea..0000000
--- a/tests/src/com/android/gallery3d/exif/ExifTestRunner.java
+++ /dev/null
@@ -1,135 +0,0 @@
-/*
- * 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.gallery3d.exif;
-
-import android.content.Context;
-import android.os.Environment;
-import android.test.InstrumentationTestRunner;
-import android.test.InstrumentationTestSuite;
-import android.util.Log;
-
-import com.android.gallery3d.tests.R;
-
-import junit.framework.TestCase;
-import junit.framework.TestSuite;
-
-import java.io.File;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-import java.util.ArrayList;
-import java.util.List;
-
-public class ExifTestRunner extends InstrumentationTestRunner {
-    private static final String TAG = "ExifTestRunner";
-
-    private static final int[] IMG_RESOURCE = {
-            R.raw.galaxy_nexus
-    };
-
-    private static final int[] EXIF_DATA_RESOURCE = {
-            R.xml.galaxy_nexus
-    };
-
-    private static List<String> mTestImgPath = new ArrayList<String>();
-    private static List<String> mTestXmlPath = new ArrayList<String>();
-
-    @Override
-    public TestSuite getAllTests() {
-        getTestImagePath();
-        TestSuite suite = new InstrumentationTestSuite(this);
-        suite.addTestSuite(ExifDataTest.class);
-        suite.addTestSuite(ExifTagTest.class);
-        addAllTestsFromExifTestCase(ExifParserTest.class, suite);
-        addAllTestsFromExifTestCase(ExifReaderTest.class, suite);
-        addAllTestsFromExifTestCase(ExifOutputStreamTest.class, suite);
-        addAllTestsFromExifTestCase(ExifModifierTest.class, suite);
-        addAllTestsFromExifTestCase(ExifInterfaceTest.class, suite);
-        return suite;
-    }
-
-    private void getTestImagePath() {
-        Context context = getContext();
-        File imgDir = context.getExternalFilesDir(Environment.DIRECTORY_PICTURES);
-        File xmlDir = new File(context.getExternalFilesDir(null).getPath(), "Xml");
-
-        if (imgDir != null && xmlDir != null) {
-            String[] imgs = imgDir.list();
-            if (imgs == null) {
-                return;
-            }
-            for (String imgName : imgs) {
-                String xmlName = imgName.substring(0, imgName.lastIndexOf('.')) + ".xml";
-                File xmlFile = new File(xmlDir, xmlName);
-                if (xmlFile.exists()) {
-                    mTestImgPath.add(new File(imgDir, imgName).getAbsolutePath());
-                    mTestXmlPath.add(xmlFile.getAbsolutePath());
-                }
-            }
-        }
-    }
-
-    private void addAllTestsFromExifTestCase(Class<? extends ExifXmlDataTestCase> testClass,
-            TestSuite suite) {
-        for (Method method : testClass.getDeclaredMethods()) {
-            if (method.getName().startsWith("test") && method.getParameterTypes().length == 0) {
-                for (int i = 0; i < IMG_RESOURCE.length; i++) {
-                    TestCase test;
-                    try {
-                        test = testClass.getDeclaredConstructor(int.class, int.class).
-                                newInstance(IMG_RESOURCE[i], EXIF_DATA_RESOURCE[i]);
-                        test.setName(method.getName());
-                        suite.addTest(test);
-                    } catch (IllegalArgumentException e) {
-                        Log.e(TAG, "Failed to create test case", e);
-                    } catch (InstantiationException e) {
-                        Log.e(TAG, "Failed to create test case", e);
-                    } catch (IllegalAccessException e) {
-                        Log.e(TAG, "Failed to create test case", e);
-                    } catch (InvocationTargetException e) {
-                        Log.e(TAG, "Failed to create test case", e);
-                    } catch (NoSuchMethodException e) {
-                        Log.e(TAG, "Failed to create test case", e);
-                    }
-                }
-                for (int i = 0, n = mTestImgPath.size(); i < n; i++) {
-                    TestCase test;
-                    try {
-                        test = testClass.getDeclaredConstructor(String.class, String.class).
-                                newInstance(mTestImgPath.get(i), mTestXmlPath.get(i));
-                        test.setName(method.getName());
-                        suite.addTest(test);
-                    } catch (IllegalArgumentException e) {
-                        Log.e(TAG, "Failed to create test case", e);
-                    } catch (InstantiationException e) {
-                        Log.e(TAG, "Failed to create test case", e);
-                    } catch (IllegalAccessException e) {
-                        Log.e(TAG, "Failed to create test case", e);
-                    } catch (InvocationTargetException e) {
-                        Log.e(TAG, "Failed to create test case", e);
-                    } catch (NoSuchMethodException e) {
-                        Log.e(TAG, "Failed to create test case", e);
-                    }
-                }
-            }
-        }
-    }
-
-    @Override
-    public ClassLoader getLoader() {
-        return ExifTestRunner.class.getClassLoader();
-    }
-}
diff --git a/tests/src/com/android/gallery3d/exif/ExifXmlDataTestCase.java b/tests/src/com/android/gallery3d/exif/ExifXmlDataTestCase.java
deleted file mode 100644
index da86020..0000000
--- a/tests/src/com/android/gallery3d/exif/ExifXmlDataTestCase.java
+++ /dev/null
@@ -1,108 +0,0 @@
-/*
- * 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.gallery3d.exif;
-
-import android.content.res.Resources;
-import android.test.InstrumentationTestCase;
-import android.util.Xml;
-
-import org.xmlpull.v1.XmlPullParser;
-
-import java.io.FileInputStream;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-
-public class ExifXmlDataTestCase extends InstrumentationTestCase {
-
-    private static final String RES_ID_TITLE = "Resource ID: %x";
-
-    private InputStream mImageInputStream;
-    private InputStream mXmlInputStream;
-    private XmlPullParser mXmlParser;
-    private final String mImagePath;
-    private final String mXmlPath;
-    private final int mImageResourceId;
-    private final int mXmlResourceId;
-
-    public ExifXmlDataTestCase(int imageRes, int xmlRes) {
-        mImagePath = null;
-        mXmlPath = null;
-        mImageResourceId = imageRes;
-        mXmlResourceId = xmlRes;
-    }
-
-    public ExifXmlDataTestCase(String imagePath, String xmlPath) {
-        mImagePath = imagePath;
-        mXmlPath = xmlPath;
-        mImageResourceId = 0;
-        mXmlResourceId = 0;
-    }
-
-    protected InputStream getImageInputStream() {
-        return mImageInputStream;
-    }
-
-    protected XmlPullParser getXmlParser() {
-        return mXmlParser;
-    }
-
-    @Override
-    public void setUp() throws Exception {
-        try {
-            if (mImagePath != null) {
-                mImageInputStream = new FileInputStream(mImagePath);
-                mXmlInputStream = new FileInputStream(mXmlPath);
-                mXmlParser = Xml.newPullParser();
-                mXmlParser.setInput(new InputStreamReader(mXmlInputStream));
-            } else {
-                Resources res = getInstrumentation().getContext().getResources();
-                mImageInputStream = res.openRawResource(mImageResourceId);
-                mXmlParser = res.getXml(mXmlResourceId);
-            }
-        } catch (Exception e) {
-            throw new Exception(getImageTitle(), e);
-        }
-    }
-
-    @Override
-    public void tearDown() throws Exception {
-        Util.closeSilently(mImageInputStream);
-        Util.closeSilently(mXmlInputStream);
-        mXmlParser = null;
-    }
-
-    protected String getImageTitle() {
-        if (mImagePath != null) {
-            return mImagePath;
-        } else {
-            return String.format(RES_ID_TITLE, mImageResourceId);
-        }
-    }
-
-    protected InputStream reopenFileStream() throws Exception {
-        try {
-            if (mImagePath != null) {
-                return new FileInputStream(mImagePath);
-            } else {
-                Resources res = getInstrumentation().getContext().getResources();
-                return res.openRawResource(mImageResourceId);
-            }
-        } catch (Exception e) {
-            throw new Exception(getImageTitle(), e);
-        }
-    }
-}
diff --git a/tests/src/com/android/gallery3d/exif/ExifXmlReader.java b/tests/src/com/android/gallery3d/exif/ExifXmlReader.java
deleted file mode 100644
index 12e9cf7..0000000
--- a/tests/src/com/android/gallery3d/exif/ExifXmlReader.java
+++ /dev/null
@@ -1,125 +0,0 @@
-/*
- * 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.gallery3d.exif;
-
-import org.xmlpull.v1.XmlPullParser;
-import org.xmlpull.v1.XmlPullParserException;
-
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-public class ExifXmlReader {
-    private static final String TAG_EXIF = "exif";
-    private static final String TAG_TAG = "tag";
-
-    private static final String IFD0 = "IFD0";
-    private static final String EXIF_IFD = "ExifIFD";
-    private static final String GPS_IFD = "GPS";
-    private static final String IFD1 = "IFD1";
-    private static final String INTEROP_IFD = "InteropIFD";
-
-    private static final String ATTR_ID = "id";
-    private static final String ATTR_IFD = "ifd";
-
-    private static final String NO_VALUE = "NO_VALUE";
-
-    /**
-     * This function read the ground truth XML.
-     *
-     * @throws XmlPullParserException
-     * @throws IOException
-     */
-    static public List<Map<Short, List<String>>> readXml(XmlPullParser parser)
-            throws XmlPullParserException, IOException {
-
-        List<Map<Short, List<String>>> exifData =
-                new ArrayList<Map<Short, List<String>>>(IfdId.TYPE_IFD_COUNT);
-        for (int i = 0; i < IfdId.TYPE_IFD_COUNT; i++) {
-            exifData.add(new HashMap<Short, List<String>>());
-        }
-
-        while (parser.next() != XmlPullParser.END_DOCUMENT) {
-            if (parser.getEventType() == XmlPullParser.START_TAG) {
-                break;
-            }
-        }
-        parser.require(XmlPullParser.START_TAG, null, TAG_EXIF);
-
-        while (parser.next() != XmlPullParser.END_TAG) {
-            if (parser.getEventType() != XmlPullParser.START_TAG) {
-                continue;
-            }
-
-            parser.require(XmlPullParser.START_TAG, null, TAG_TAG);
-
-            int ifdId = getIfdIdFromString(parser.getAttributeValue(null, ATTR_IFD));
-            short id = Integer.decode(parser.getAttributeValue(null, ATTR_ID)).shortValue();
-
-            String value = "";
-            if (parser.next() == XmlPullParser.TEXT) {
-                value = parser.getText();
-                parser.next();
-            }
-
-            if (ifdId < 0) {
-                // TODO: the MarkerNote segment.
-            } else {
-                List<String> tagData = exifData.get(ifdId).get(id);
-                if (tagData == null) {
-                    tagData = new ArrayList<String>();
-                    exifData.get(ifdId).put(id, tagData);
-                }
-                if (NO_VALUE.equals(value)) {
-                    tagData.add(null);
-                } else {
-                    tagData.add(value.trim());
-                }
-            }
-
-            parser.require(XmlPullParser.END_TAG, null, null);
-        }
-        return exifData;
-    }
-
-    static private int getIfdIdFromString(String prefix) {
-        if (IFD0.equals(prefix)) {
-            return IfdId.TYPE_IFD_0;
-        } else if (EXIF_IFD.equals(prefix)) {
-            return IfdId.TYPE_IFD_EXIF;
-        } else if (GPS_IFD.equals(prefix)) {
-            return IfdId.TYPE_IFD_GPS;
-        } else if (IFD1.equals(prefix)) {
-            return IfdId.TYPE_IFD_1;
-        } else if (INTEROP_IFD.equals(prefix)) {
-            return IfdId.TYPE_IFD_INTEROPERABILITY;
-        } else {
-            assert (false);
-            return -1;
-        }
-    }
-
-    static public int getTrueTagNumber(Map<Short, List<String>> ifdData) {
-        int size = 0;
-        for (List<String> tag : ifdData.values()) {
-            size += tag.size();
-        }
-        return size;
-    }
-}
diff --git a/tests/src/com/android/gallery3d/exif/Util.java b/tests/src/com/android/gallery3d/exif/Util.java
deleted file mode 100644
index 15de007..0000000
--- a/tests/src/com/android/gallery3d/exif/Util.java
+++ /dev/null
@@ -1,195 +0,0 @@
-/*
- * 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.gallery3d.exif;
-
-import java.io.ByteArrayOutputStream;
-import java.io.Closeable;
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.Arrays;
-
-class Util {
-    public static boolean equals(Object a, Object b) {
-        return (a == b) || (a == null ? false : a.equals(b));
-    }
-
-    public static void closeSilently(Closeable c) {
-        if (c == null)
-            return;
-        try {
-            c.close();
-        } catch (Throwable t) {
-            // do nothing
-        }
-    }
-
-    public static byte[] readToByteArray(InputStream is) throws IOException {
-        ByteArrayOutputStream bos = new ByteArrayOutputStream();
-        int len;
-        byte[] buf = new byte[1024];
-        while ((len = is.read(buf)) > -1) {
-            bos.write(buf, 0, len);
-        }
-        bos.flush();
-        return bos.toByteArray();
-    }
-
-    /**
-     * Tags that are not defined in the spec.
-     */
-    static final short TAG_XP_TITLE = (short) 0x9c9b;
-    static final short TAG_XP_COMMENT = (short) 0x9c9c;
-    static final short TAG_XP_AUTHOR = (short) 0x9c9d;
-    static final short TAG_XP_KEYWORDS = (short) 0x9c9e;
-    static final short TAG_XP_SUBJECT = (short) 0x9c9f;
-
-    private static String tagUndefinedTypeValueToString(ExifTag tag) {
-        StringBuilder sbuilder = new StringBuilder();
-        byte[] buf = new byte[tag.getComponentCount()];
-        tag.getBytes(buf);
-        short tagId = tag.getTagId();
-        if (tagId == ExifInterface.getTrueTagKey(ExifInterface.TAG_COMPONENTS_CONFIGURATION)) {
-            for (int i = 0, n = tag.getComponentCount(); i < n; i++) {
-                if (i != 0) {
-                    sbuilder.append(" ");
-                }
-                sbuilder.append(buf[i]);
-            }
-        } else {
-            if (buf.length == 1) {
-                sbuilder.append(buf[0]);
-            } else {
-                for (int i = 0, n = buf.length; i < n; i++) {
-                    byte code = buf[i];
-                    if (code == 0) {
-                        continue;
-                    }
-                    if (code > 31 && code < 127) {
-                        sbuilder.append((char) code);
-                    } else {
-                        sbuilder.append('.');
-                    }
-                }
-            }
-        }
-        return sbuilder.toString();
-    }
-
-    /**
-     * Returns a string representation of the value of this tag.
-     */
-    public static String tagValueToString(ExifTag tag) {
-        StringBuilder sbuilder = new StringBuilder();
-        short id = tag.getTagId();
-        switch (tag.getDataType()) {
-            case ExifTag.TYPE_UNDEFINED:
-                sbuilder.append(tagUndefinedTypeValueToString(tag));
-                break;
-            case ExifTag.TYPE_UNSIGNED_BYTE:
-                if (id == ExifInterface.TAG_MAKER_NOTE || id == TAG_XP_TITLE ||
-                        id == TAG_XP_COMMENT || id == TAG_XP_AUTHOR ||
-                        id == TAG_XP_KEYWORDS || id == TAG_XP_SUBJECT) {
-                    sbuilder.append(tagUndefinedTypeValueToString(tag));
-                } else {
-                    byte[] buf = new byte[tag.getComponentCount()];
-                    tag.getBytes(buf);
-                    for (int i = 0, n = tag.getComponentCount(); i < n; i++) {
-                        if (i != 0)
-                            sbuilder.append(" ");
-                        sbuilder.append(buf[i]);
-                    }
-                }
-                break;
-            case ExifTag.TYPE_ASCII:
-                byte[] buf = tag.getStringByte();
-                for (int i = 0, n = buf.length; i < n; i++) {
-                    byte code = buf[i];
-                    if (code == 0) {
-                        // Treat some tag as undefined type data.
-                        if (id == ExifInterface.TAG_COPYRIGHT
-                                || id == ExifInterface.TAG_GPS_DATE_STAMP) {
-                            continue;
-                        } else {
-                            break;
-                        }
-                    }
-                    if (code > 31 && code < 127) {
-                        sbuilder.append((char) code);
-                    } else {
-                        sbuilder.append('.');
-                    }
-                }
-                break;
-            case ExifTag.TYPE_UNSIGNED_LONG:
-                for (int i = 0, n = tag.getComponentCount(); i < n; i++) {
-                    if (i != 0) {
-                        sbuilder.append(" ");
-                    }
-                    sbuilder.append(tag.getValueAt(i));
-                }
-                break;
-            case ExifTag.TYPE_RATIONAL:
-            case ExifTag.TYPE_UNSIGNED_RATIONAL:
-                for (int i = 0, n = tag.getComponentCount(); i < n; i++) {
-                    Rational r = tag.getRational(i);
-                    if (i != 0) {
-                        sbuilder.append(" ");
-                    }
-                    sbuilder.append(r.getNumerator()).append("/").append(r.getDenominator());
-                }
-                break;
-            case ExifTag.TYPE_UNSIGNED_SHORT:
-                for (int i = 0, n = tag.getComponentCount(); i < n; i++) {
-                    if (i != 0) {
-                        sbuilder.append(" ");
-                    }
-                    sbuilder.append((int) tag.getValueAt(i));
-                }
-                break;
-            case ExifTag.TYPE_LONG:
-                for (int i = 0, n = tag.getComponentCount(); i < n; i++) {
-                    if (i != 0) {
-                        sbuilder.append(" ");
-                    }
-                    sbuilder.append((int) tag.getValueAt(i));
-                }
-                break;
-        }
-        return sbuilder.toString();
-    }
-
-    public static String valueToString(Object obj) {
-        if (obj instanceof int[]) {
-            return Arrays.toString((int[]) obj);
-        } else if (obj instanceof Integer[]) {
-            return Arrays.toString((Integer[]) obj);
-        } else if (obj instanceof long[]) {
-            return Arrays.toString((long[]) obj);
-        } else if (obj instanceof Long[]) {
-            return Arrays.toString((Long[]) obj);
-        } else if (obj instanceof Rational) {
-            return ((Rational) obj).toString();
-        } else if (obj instanceof Rational[]) {
-            return Arrays.toString((Rational[]) obj);
-        } else if (obj instanceof byte[]) {
-            return Arrays.toString((byte[]) obj);
-        } else if (obj != null) {
-            return obj.toString();
-        }
-        return "";
-    }
-}
diff --git a/tests/src/com/android/gallery3d/functional/CameraTest.java b/tests/src/com/android/gallery3d/functional/CameraTest.java
deleted file mode 100644
index c293c0d..0000000
--- a/tests/src/com/android/gallery3d/functional/CameraTest.java
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * Copyright (C) 2010 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.gallery3d.functional;
-
-import com.android.camera.CameraActivity;
-
-import android.app.Activity;
-import android.content.Intent;
-import android.net.Uri;
-import android.os.Environment;
-import android.os.Process;
-import android.provider.MediaStore;
-import android.test.InstrumentationTestCase;
-import android.test.suitebuilder.annotation.LargeTest;
-
-import java.io.File;
-import java.lang.ref.WeakReference;
-import java.util.ArrayList;
-
-public class CameraTest extends InstrumentationTestCase {
-    @LargeTest
-    public void testVideoCaptureIntentFdLeak() throws Exception {
-        Intent intent = new Intent(MediaStore.ACTION_VIDEO_CAPTURE);
-        intent.setClass(getInstrumentation().getTargetContext(), CameraActivity.class);
-        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
-        intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.parse("file://"
-                + Environment.getExternalStorageDirectory().toString()
-                + "test_fd_leak.3gp"));
-        getInstrumentation().startActivitySync(intent).finish();
-        // Test if the fd is closed.
-        for (File f: new File("/proc/" + Process.myPid() + "/fd").listFiles()) {
-            assertEquals(-1, f.getCanonicalPath().indexOf("test_fd_leak.3gp"));
-        }
-    }
-
-    @LargeTest
-    public void testActivityLeak() throws Exception {
-        checkActivityLeak(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA);
-        checkActivityLeak(MediaStore.INTENT_ACTION_VIDEO_CAMERA);
-    }
-
-    private void checkActivityLeak(String action) throws Exception {
-        final int TEST_COUNT = 5;
-        Intent intent = new Intent(action);
-        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
-        intent.setClass(getInstrumentation().getTargetContext(),
-                CameraActivity.class);
-        ArrayList<WeakReference<Activity>> refs =
-                new ArrayList<WeakReference<Activity>>();
-        for (int i = 0; i < TEST_COUNT; i++) {
-            Activity activity = getInstrumentation().startActivitySync(intent);
-            refs.add(new WeakReference<Activity>(activity));
-            activity.finish();
-            getInstrumentation().waitForIdleSync();
-            activity = null;
-        }
-        Runtime.getRuntime().gc();
-        Runtime.getRuntime().runFinalization();
-        Runtime.getRuntime().gc();
-        int refCount = 0;
-        for (WeakReference<Activity> c: refs) {
-            if (c.get() != null) refCount++;
-        }
-        // If applications are leaking activity, every reference is reachable.
-        assertTrue(refCount != TEST_COUNT);
-    }
-}
diff --git a/tests/src/com/android/gallery3d/functional/ImageCaptureIntentTest.java b/tests/src/com/android/gallery3d/functional/ImageCaptureIntentTest.java
deleted file mode 100644
index 8d394b5..0000000
--- a/tests/src/com/android/gallery3d/functional/ImageCaptureIntentTest.java
+++ /dev/null
@@ -1,148 +0,0 @@
-/*
- * Copyright (C) 2011 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.gallery3d.functional;
-
-import com.android.camera.CameraActivity;
-import com.android.gallery3d.R;
-
-import android.app.Activity;
-import android.content.Intent;
-import android.graphics.Bitmap;
-import android.graphics.BitmapFactory;
-import android.net.Uri;
-import android.os.Environment;
-import android.provider.MediaStore;
-import android.test.ActivityInstrumentationTestCase2;
-import android.test.suitebuilder.annotation.LargeTest;
-import android.view.KeyEvent;
-
-import java.io.BufferedInputStream;
-import java.io.File;
-import java.io.FileInputStream;
-
-public class ImageCaptureIntentTest extends ActivityInstrumentationTestCase2 <CameraActivity> {
-    private Intent mIntent;
-
-    public ImageCaptureIntentTest() {
-        super(CameraActivity.class);
-    }
-
-    @Override
-    protected void setUp() throws Exception {
-        super.setUp();
-        mIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
-    }
-
-    @LargeTest
-    public void testNoExtraOutput() throws Exception {
-        setActivityIntent(mIntent);
-        getActivity();
-
-        takePicture();
-        pressDone();
-
-        assertTrue(getActivity().isFinishing());
-        assertEquals(Activity.RESULT_OK, getActivity().getResultCode());
-        Intent resultData = getActivity().getResultData();
-        Bitmap bitmap = (Bitmap) resultData.getParcelableExtra("data");
-        assertNotNull(bitmap);
-        assertTrue(bitmap.getWidth() > 0);
-        assertTrue(bitmap.getHeight() > 0);
-    }
-
-    @LargeTest
-    public void testExtraOutput() throws Exception {
-        File file = new File(Environment.getExternalStorageDirectory(),
-            "test.jpg");
-        BufferedInputStream stream = null;
-        byte[] jpegData;
-
-        try {
-            mIntent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(file));
-            setActivityIntent(mIntent);
-            getActivity();
-
-            takePicture();
-            pressDone();
-
-            assertTrue(getActivity().isFinishing());
-            assertEquals(Activity.RESULT_OK, getActivity().getResultCode());
-
-            // Verify the jpeg file
-            int fileLength = (int) file.length();
-            assertTrue(fileLength > 0);
-            jpegData = new byte[fileLength];
-            stream = new BufferedInputStream(new FileInputStream(file));
-            stream.read(jpegData);
-        } finally {
-            if (stream != null) stream.close();
-            file.delete();
-        }
-
-        Bitmap b = BitmapFactory.decodeByteArray(jpegData, 0, jpegData.length);
-        assertTrue(b.getWidth() > 0);
-        assertTrue(b.getHeight() > 0);
-    }
-
-    @LargeTest
-    public void testCancel() throws Exception {
-        setActivityIntent(mIntent);
-        getActivity();
-
-        pressCancel();
-
-        assertTrue(getActivity().isFinishing());
-        assertEquals(Activity.RESULT_CANCELED, getActivity().getResultCode());
-    }
-
-    @LargeTest
-    public void testSnapshotCancel() throws Exception {
-        setActivityIntent(mIntent);
-        getActivity();
-
-        takePicture();
-        pressCancel();
-
-        assertTrue(getActivity().isFinishing());
-        assertEquals(Activity.RESULT_CANCELED, getActivity().getResultCode());
-    }
-
-    private void takePicture() throws Exception {
-        getInstrumentation().sendKeySync(
-                new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_FOCUS));
-        getInstrumentation().sendCharacterSync(KeyEvent.KEYCODE_CAMERA);
-        Thread.sleep(4000);
-    }
-
-    private void pressDone() {
-        getInstrumentation().runOnMainSync(new Runnable() {
-            @Override
-            public void run() {
-                getActivity().findViewById(R.id.btn_done).performClick();
-            }
-        });
-    }
-
-    private void pressCancel() {
-        getInstrumentation().runOnMainSync(new Runnable() {
-            @Override
-            public void run() {
-                getActivity().findViewById(R.id.btn_cancel).performClick();
-            }
-        });
-    }
-}
diff --git a/tests/src/com/android/gallery3d/functional/VideoCaptureIntentTest.java b/tests/src/com/android/gallery3d/functional/VideoCaptureIntentTest.java
deleted file mode 100644
index c8d7bbb..0000000
--- a/tests/src/com/android/gallery3d/functional/VideoCaptureIntentTest.java
+++ /dev/null
@@ -1,258 +0,0 @@
-/*
- * Copyright (C) 2011 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.gallery3d.functional;
-
-import com.android.camera.CameraActivity;
-import com.android.gallery3d.R;
-
-import android.app.Activity;
-import android.content.ContentResolver;
-import android.content.Intent;
-import android.database.Cursor;
-import android.media.MediaMetadataRetriever;
-import android.net.Uri;
-import android.os.Environment;
-import android.provider.MediaStore;
-import android.provider.MediaStore.Video.VideoColumns;
-import android.test.ActivityInstrumentationTestCase2;
-import android.test.suitebuilder.annotation.LargeTest;
-import android.util.Log;
-import android.view.KeyEvent;
-
-import java.io.File;
-
-public class VideoCaptureIntentTest extends ActivityInstrumentationTestCase2 <CameraActivity> {
-    private static final String TAG = "VideoCaptureIntentTest";
-    private Intent mIntent;
-    private Uri mVideoUri;
-    private File mFile, mFile2;
-
-    public VideoCaptureIntentTest() {
-        super(CameraActivity.class);
-    }
-
-    @Override
-    protected void setUp() throws Exception {
-        super.setUp();
-        mIntent = new Intent(MediaStore.ACTION_VIDEO_CAPTURE);
-    }
-
-    @Override
-    protected void tearDown() throws Exception {
-        if (mVideoUri != null) {
-            ContentResolver resolver = getActivity().getContentResolver();
-            Uri query = mVideoUri.buildUpon().build();
-            String[] projection = new String[] {VideoColumns.DATA};
-
-            Cursor cursor = null;
-            try {
-                cursor = resolver.query(query, projection, null, null, null);
-                if (cursor != null && cursor.moveToFirst()) {
-                    new File(cursor.getString(0)).delete();
-                }
-            } finally {
-                if (cursor != null) cursor.close();
-            }
-
-            resolver.delete(mVideoUri, null, null);
-        }
-        if (mFile != null) mFile.delete();
-        if (mFile2 != null) mFile2.delete();
-        super.tearDown();
-    }
-
-    @LargeTest
-    public void testNoExtraOutput() throws Exception {
-        setActivityIntent(mIntent);
-        getActivity();
-
-        recordVideo();
-        pressDone();
-
-        Intent resultData = getActivity().getResultData();
-        mVideoUri = resultData.getData();
-        assertNotNull(mVideoUri);
-        verify(getActivity(), mVideoUri);
-    }
-
-    @LargeTest
-    public void testExtraOutput() throws Exception {
-        mFile = new File(Environment.getExternalStorageDirectory(), "video.tmp");
-
-        Uri uri = Uri.fromFile(mFile);
-        mIntent.putExtra(MediaStore.EXTRA_OUTPUT, uri);
-        setActivityIntent(mIntent);
-        getActivity();
-
-        recordVideo();
-        pressDone();
-
-        verify(getActivity(), uri);
-    }
-
-    @LargeTest
-    public void testCancel() throws Exception {
-        setActivityIntent(mIntent);
-        getActivity();
-
-        pressCancel();
-
-        assertTrue(getActivity().isFinishing());
-        assertEquals(Activity.RESULT_CANCELED, getActivity().getResultCode());
-    }
-
-    @LargeTest
-    public void testRecordCancel() throws Exception {
-        setActivityIntent(mIntent);
-        getActivity();
-
-        recordVideo();
-        pressCancel();
-
-        assertTrue(getActivity().isFinishing());
-        assertEquals(Activity.RESULT_CANCELED, getActivity().getResultCode());
-    }
-
-    @LargeTest
-    public void testExtraSizeLimit() throws Exception {
-        mFile = new File(Environment.getExternalStorageDirectory(), "video.tmp");
-        final long sizeLimit = 500000;  // bytes
-
-        Uri uri = Uri.fromFile(mFile);
-        mIntent.putExtra(MediaStore.EXTRA_OUTPUT, uri);
-        mIntent.putExtra(MediaStore.EXTRA_SIZE_LIMIT, sizeLimit);
-        mIntent.putExtra(MediaStore.EXTRA_VIDEO_QUALITY, 0);  // use low quality to speed up
-        setActivityIntent(mIntent);
-        getActivity();
-
-        recordVideo(5000);
-        pressDone();
-
-        verify(getActivity(), uri);
-        long length = mFile.length();
-        Log.v(TAG, "Video size is " + length + " bytes.");
-        assertTrue(length > 0);
-        assertTrue("Actual size=" + length, length <= sizeLimit);
-    }
-
-    @LargeTest
-    public void testExtraDurationLimit() throws Exception {
-        mFile = new File(Environment.getExternalStorageDirectory(), "video.tmp");
-        final int durationLimit = 2;  // seconds
-
-        Uri uri = Uri.fromFile(mFile);
-        mIntent.putExtra(MediaStore.EXTRA_OUTPUT, uri);
-        mIntent.putExtra(MediaStore.EXTRA_DURATION_LIMIT, durationLimit);
-        setActivityIntent(mIntent);
-        getActivity();
-
-        recordVideo(5000);
-        pressDone();
-
-        int duration = verify(getActivity(), uri);
-        // The duraion should be close to to the limit. The last video duration
-        // also has duration, so the total duration may exceeds the limit a
-        // little bit.
-        Log.v(TAG, "Video length is " + duration + " ms.");
-        assertTrue(duration  < (durationLimit + 1) * 1000);
-    }
-
-    @LargeTest
-    public void testExtraVideoQuality() throws Exception {
-        mFile = new File(Environment.getExternalStorageDirectory(), "video.tmp");
-        mFile2 = new File(Environment.getExternalStorageDirectory(), "video2.tmp");
-
-        Uri uri = Uri.fromFile(mFile);
-        mIntent.putExtra(MediaStore.EXTRA_OUTPUT, uri);
-        mIntent.putExtra(MediaStore.EXTRA_VIDEO_QUALITY, 0);  // low quality
-        setActivityIntent(mIntent);
-        getActivity();
-
-        recordVideo();
-        pressDone();
-
-        verify(getActivity(), uri);
-        setActivity(null);
-
-        uri = Uri.fromFile(mFile2);
-        mIntent.putExtra(MediaStore.EXTRA_OUTPUT, uri);
-        mIntent.putExtra(MediaStore.EXTRA_VIDEO_QUALITY, 1);  // high quality
-        setActivityIntent(mIntent);
-        getActivity();
-
-        recordVideo();
-        pressDone();
-
-        verify(getActivity(), uri);
-        assertTrue(mFile.length() <= mFile2.length());
-    }
-
-    // Verify result code, result data, and the duration.
-    private int verify(CameraActivity activity, Uri uri) throws Exception {
-        assertTrue(activity.isFinishing());
-        assertEquals(Activity.RESULT_OK, activity.getResultCode());
-
-        // Verify the video file
-        MediaMetadataRetriever retriever = new MediaMetadataRetriever();
-        retriever.setDataSource(activity, uri);
-        String duration = retriever.extractMetadata(
-                MediaMetadataRetriever.METADATA_KEY_DURATION);
-        assertNotNull(duration);
-        int durationValue = Integer.parseInt(duration);
-        Log.v(TAG, "Video duration is " + durationValue);
-        assertTrue(durationValue > 0);
-        return durationValue;
-    }
-
-    private void recordVideo(int ms) throws Exception {
-        getInstrumentation().sendCharacterSync(KeyEvent.KEYCODE_CAMERA);
-        Thread.sleep(ms);
-        getInstrumentation().runOnMainSync(new Runnable() {
-            @Override
-            public void run() {
-                // If recording is in progress, stop it. Run these atomically in
-                // UI thread.
-                CameraActivity activity = getActivity();
-                if (activity.isRecording()) {
-                    activity.findViewById(R.id.shutter_button).performClick();
-                }
-            }
-        });
-    }
-
-    private void recordVideo() throws Exception {
-        recordVideo(2000);
-    }
-
-    private void pressDone() {
-        getInstrumentation().runOnMainSync(new Runnable() {
-            @Override
-            public void run() {
-                getActivity().findViewById(R.id.btn_done).performClick();
-            }
-        });
-    }
-
-    private void pressCancel() {
-        getInstrumentation().runOnMainSync(new Runnable() {
-            @Override
-            public void run() {
-                getActivity().findViewById(R.id.btn_cancel).performClick();
-            }
-        });
-    }
-}
diff --git a/tests/src/com/android/gallery3d/glrenderer/GLCanvasMock.java b/tests/src/com/android/gallery3d/glrenderer/GLCanvasMock.java
deleted file mode 100644
index a57c188..0000000
--- a/tests/src/com/android/gallery3d/glrenderer/GLCanvasMock.java
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * Copyright (C) 2010 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.gallery3d.glrenderer;
-
-import com.android.gallery3d.glrenderer.BasicTexture;
-import com.android.gallery3d.ui.GLCanvasStub;
-
-import javax.microedition.khronos.opengles.GL11;
-
-public class GLCanvasMock extends GLCanvasStub {
-    // fillRect
-    int mFillRectCalled;
-    float mFillRectWidth;
-    float mFillRectHeight;
-    int mFillRectColor;
-    // drawMixed
-    int mDrawMixedCalled;
-    float mDrawMixedRatio;
-    // drawTexture;
-    int mDrawTextureCalled;
-
-    private GL11 mGL;
-
-    public GLCanvasMock(GL11 gl) {
-        mGL = gl;
-    }
-
-    public GLCanvasMock() {
-        mGL = new GLStub();
-    }
-
-    @Override
-    public GL11 getGLInstance() {
-        return mGL;
-    }
-
-    @Override
-    public void fillRect(float x, float y, float width, float height, int color) {
-        mFillRectCalled++;
-        mFillRectWidth = width;
-        mFillRectHeight = height;
-        mFillRectColor = color;
-    }
-
-    @Override
-    public void drawTexture(
-                BasicTexture texture, int x, int y, int width, int height) {
-        mDrawTextureCalled++;
-    }
-
-    @Override
-    public void drawMixed(BasicTexture from, BasicTexture to,
-            float ratio, int x, int y, int w, int h) {
-        mDrawMixedCalled++;
-        mDrawMixedRatio = ratio;
-    }
-}
diff --git a/tests/src/com/android/gallery3d/glrenderer/GLCanvasTest.java b/tests/src/com/android/gallery3d/glrenderer/GLCanvasTest.java
deleted file mode 100644
index 416c114..0000000
--- a/tests/src/com/android/gallery3d/glrenderer/GLCanvasTest.java
+++ /dev/null
@@ -1,386 +0,0 @@
-/*
- * Copyright (C) 2010 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.gallery3d.glrenderer;
-
-import android.test.suitebuilder.annotation.SmallTest;
-import android.util.Log;
-
-import junit.framework.TestCase;
-
-import java.util.Arrays;
-
-import javax.microedition.khronos.opengles.GL10;
-import javax.microedition.khronos.opengles.GL11;
-
-public class GLCanvasTest extends TestCase {
-    private static final String TAG = "GLCanvasTest";
-
-    private static GLPaint newColorPaint(int color) {
-        GLPaint paint = new GLPaint();
-        paint.setColor(color);
-        return paint;
-    }
-
-    @SmallTest
-    public void testSetSize() {
-        GL11 glStub = new GLStub();
-        GLCanvas canvas = new GLES11Canvas(glStub);
-        canvas.setSize(100, 200);
-        canvas.setSize(1000, 100);
-        try {
-            canvas.setSize(-1, 100);
-            fail();
-        } catch (Throwable ex) {
-            // expected.
-        }
-    }
-
-    @SmallTest
-    public void testClearBuffer() {
-        new ClearBufferTest().run();
-    }
-
-    private static class ClearBufferTest extends GLMock {
-        void run() {
-            GLCanvas canvas = new GLES11Canvas(this);
-            assertEquals(0, mGLClearCalled);
-            canvas.clearBuffer();
-            assertEquals(GL10.GL_COLOR_BUFFER_BIT, mGLClearMask);
-            assertEquals(1, mGLClearCalled);
-        }
-    }
-
-    @SmallTest
-    public void testSetColor() {
-        new SetColorTest().run();
-    }
-
-    // This test assumes we use pre-multipled alpha blending and should
-    // set the blending function and color correctly.
-    private static class SetColorTest extends GLMock {
-        void run() {
-            int[] testColors = new int[] {
-                0, 0xFFFFFFFF, 0xFF000000, 0x00FFFFFF, 0x80FF8001,
-                0x7F010101, 0xFEFEFDFC, 0x017F8081, 0x027F8081, 0x2ADE4C4D
-            };
-
-            GLCanvas canvas = new GLES11Canvas(this);
-            canvas.setSize(400, 300);
-            // Test one color to make sure blend function is set.
-            assertEquals(0, mGLColorCalled);
-            canvas.drawLine(0, 0, 1, 1, newColorPaint(0x7F804020));
-            assertEquals(1, mGLColorCalled);
-            assertEquals(0x7F402010, mGLColor);
-            assertPremultipliedBlending(this);
-
-            // Test other colors to make sure premultiplication is right
-            for (int c : testColors) {
-                float a = (c >>> 24) / 255f;
-                float r = ((c >> 16) & 0xff) / 255f;
-                float g = ((c >> 8) & 0xff) / 255f;
-                float b = (c & 0xff) / 255f;
-                int pre = makeColor4f(a * r, a * g, a * b, a);
-
-                mGLColorCalled = 0;
-                canvas.drawLine(0, 0, 1, 1, newColorPaint(c));
-                assertEquals(1, mGLColorCalled);
-                assertEquals(pre, mGLColor);
-            }
-        }
-    }
-
-    @SmallTest
-    public void testSetGetMultiplyAlpha() {
-        GL11 glStub = new GLStub();
-        GLCanvas canvas = new GLES11Canvas(glStub);
-
-        canvas.setAlpha(1f);
-        assertEquals(1f, canvas.getAlpha());
-
-        canvas.setAlpha(0f);
-        assertEquals(0f, canvas.getAlpha());
-
-        canvas.setAlpha(0.5f);
-        assertEquals(0.5f, canvas.getAlpha());
-
-        canvas.multiplyAlpha(0.5f);
-        assertEquals(0.25f, canvas.getAlpha());
-
-        canvas.multiplyAlpha(0f);
-        assertEquals(0f, canvas.getAlpha());
-
-        try {
-            canvas.setAlpha(-0.01f);
-            fail();
-        } catch (Throwable ex) {
-            // expected.
-        }
-
-        try {
-            canvas.setAlpha(1.01f);
-            fail();
-        } catch (Throwable ex) {
-            // expected.
-        }
-    }
-
-    @SmallTest
-    public void testAlpha() {
-        new AlphaTest().run();
-    }
-
-    private static class AlphaTest extends GLMock {
-        void run() {
-            GLCanvas canvas = new GLES11Canvas(this);
-            canvas.setSize(400, 300);
-
-            assertEquals(0, mGLColorCalled);
-            canvas.setAlpha(0.48f);
-            canvas.drawLine(0, 0, 1, 1, newColorPaint(0xFF804020));
-            assertPremultipliedBlending(this);
-            assertEquals(1, mGLColorCalled);
-            assertEquals(0x7A3D1F0F, mGLColor);
-        }
-    }
-
-    @SmallTest
-    public void testDrawLine() {
-        new DrawLineTest().run();
-    }
-
-    // This test assumes the drawLine() function use glDrawArrays() with
-    // GL_LINE_STRIP mode to draw the line and the input coordinates are used
-    // directly.
-    private static class DrawLineTest extends GLMock {
-        private int mDrawArrayCalled = 0;
-        private final int[] mResult = new int[4];
-
-        @Override
-        public void glDrawArrays(int mode, int first, int count) {
-            assertNotNull(mGLVertexPointer);
-            assertEquals(GL10.GL_LINE_STRIP, mode);
-            assertEquals(2, count);
-            mGLVertexPointer.bindByteBuffer();
-
-            double[] coord = new double[4];
-            mGLVertexPointer.getArrayElement(first, coord);
-            mResult[0] = (int) coord[0];
-            mResult[1] = (int) coord[1];
-            mGLVertexPointer.getArrayElement(first + 1, coord);
-            mResult[2] = (int) coord[0];
-            mResult[3] = (int) coord[1];
-            mDrawArrayCalled++;
-        }
-
-        void run() {
-            GLCanvas canvas = new GLES11Canvas(this);
-            canvas.setSize(400, 300);
-            canvas.drawLine(2, 7, 1, 8, newColorPaint(0) /* color */);
-            assertTrue(mGLVertexArrayEnabled);
-            assertEquals(1, mDrawArrayCalled);
-
-            Log.v(TAG, "result = " + Arrays.toString(mResult));
-            int[] answer = new int[] {2, 7, 1, 8};
-            for (int i = 0; i < answer.length; i++) {
-                assertEquals(answer[i], mResult[i]);
-            }
-        }
-    }
-
-    @SmallTest
-    public void testFillRect() {
-        new FillRectTest().run();
-    }
-
-    // This test assumes the drawLine() function use glDrawArrays() with
-    // GL_TRIANGLE_STRIP mode to draw the line and the input coordinates
-    // are used directly.
-    private static class FillRectTest extends GLMock {
-        private int mDrawArrayCalled = 0;
-        private final int[] mResult = new int[8];
-
-        @Override
-        public void glDrawArrays(int mode, int first, int count) {
-            assertNotNull(mGLVertexPointer);
-            assertEquals(GL10.GL_TRIANGLE_STRIP, mode);
-            assertEquals(4, count);
-            mGLVertexPointer.bindByteBuffer();
-
-            double[] coord = new double[4];
-            for (int i = 0; i < 4; i++) {
-                mGLVertexPointer.getArrayElement(first + i, coord);
-                mResult[i * 2 + 0] = (int) coord[0];
-                mResult[i * 2 + 1] = (int) coord[1];
-            }
-
-            mDrawArrayCalled++;
-        }
-
-        void run() {
-            GLCanvas canvas = new GLES11Canvas(this);
-            canvas.setSize(400, 300);
-            canvas.fillRect(2, 7, 1, 8, 0 /* color */);
-            assertTrue(mGLVertexArrayEnabled);
-            assertEquals(1, mDrawArrayCalled);
-            Log.v(TAG, "result = " + Arrays.toString(mResult));
-
-            // These are the four vertics that should be used.
-            int[] answer = new int[] {
-                2, 7,
-                3, 7,
-                3, 15,
-                2, 15};
-            int count[] = new int[4];
-
-            // Count the number of appearances for each vertex.
-            for (int i = 0; i < 4; i++) {
-                for (int j = 0; j < 4; j++) {
-                    if (answer[i * 2] == mResult[j * 2] &&
-                        answer[i * 2 + 1] == mResult[j * 2 + 1]) {
-                        count[i]++;
-                    }
-                }
-            }
-
-            // Each vertex should appear exactly once.
-            for (int i = 0; i < 4; i++) {
-                assertEquals(1, count[i]);
-            }
-        }
-    }
-
-    @SmallTest
-    public void testTransform() {
-        new TransformTest().run();
-    }
-
-    // This test assumes glLoadMatrixf is used to load the model view matrix,
-    // and glOrthof is used to load the projection matrix.
-    //
-    // The projection matrix is set to an orthogonal projection which is the
-    // inverse of viewport transform. So the model view matrix maps input
-    // directly to screen coordinates (default no scaling, and the y-axis is
-    // reversed).
-    //
-    // The matrix here are all listed in column major order.
-    //
-    private static class TransformTest extends GLMock {
-        private final float[] mModelViewMatrixUsed = new float[16];
-        private final float[] mProjectionMatrixUsed = new float[16];
-
-        @Override
-        public void glDrawArrays(int mode, int first, int count) {
-            copy(mModelViewMatrixUsed, mGLModelViewMatrix);
-            copy(mProjectionMatrixUsed, mGLProjectionMatrix);
-        }
-
-        private void copy(float[] dest, float[] src) {
-            System.arraycopy(src, 0, dest, 0, 16);
-        }
-
-        void run() {
-            GLCanvas canvas = new GLES11Canvas(this);
-            canvas.setSize(40, 50);
-            int color = 0;
-
-            // Initial matrix
-            canvas.drawLine(0, 0, 1, 1, newColorPaint(color));
-            assertMatrixEq(new float[] {
-                    1,  0, 0, 0,
-                    0, -1, 0, 0,
-                    0,  0, 1, 0,
-                    0, 50, 0, 1
-                    }, mModelViewMatrixUsed);
-
-            assertMatrixEq(new float[] {
-                    2f / 40,       0,  0, 0,
-                          0, 2f / 50,  0, 0,
-                          0,       0, -1, 0,
-                         -1,      -1,  0, 1
-                    }, mProjectionMatrixUsed);
-
-            // Translation
-            canvas.translate(3, 4, 5);
-            canvas.drawLine(0, 0, 1, 1, newColorPaint(color));
-            assertMatrixEq(new float[] {
-                    1,  0, 0, 0,
-                    0, -1, 0, 0,
-                    0,  0, 1, 0,
-                    3, 46, 5, 1
-                    }, mModelViewMatrixUsed);
-            canvas.save();
-
-            // Scaling
-            canvas.scale(0.7f, 0.6f, 0.5f);
-            canvas.drawLine(0, 0, 1, 1, newColorPaint(color));
-            assertMatrixEq(new float[] {
-                    0.7f,     0,    0, 0,
-                    0,    -0.6f,    0, 0,
-                    0,        0, 0.5f, 0,
-                    3,       46,    5, 1
-                    }, mModelViewMatrixUsed);
-
-            // Rotation
-            canvas.rotate(90, 0, 0, 1);
-            canvas.drawLine(0, 0, 1, 1, newColorPaint(color));
-            assertMatrixEq(new float[] {
-                        0, -0.6f,    0, 0,
-                    -0.7f,     0,    0, 0,
-                        0,     0, 0.5f, 0,
-                        3,    46,    5, 1
-                    }, mModelViewMatrixUsed);
-            canvas.restore();
-
-            // After restoring to the point just after translation,
-            // do rotation again.
-            canvas.rotate(180, 1, 0, 0);
-            canvas.drawLine(0, 0, 1, 1, newColorPaint(color));
-            assertMatrixEq(new float[] {
-                    1,  0,  0, 0,
-                    0,  1,  0, 0,
-                    0,  0, -1, 0,
-                    3, 46,  5, 1
-                    }, mModelViewMatrixUsed);
-        }
-    }
-
-    private static void assertPremultipliedBlending(GLMock mock) {
-        assertTrue(mock.mGLBlendFuncCalled > 0);
-        assertTrue(mock.mGLBlendEnabled);
-        assertEquals(GL11.GL_ONE, mock.mGLBlendFuncSFactor);
-        assertEquals(GL11.GL_ONE_MINUS_SRC_ALPHA, mock.mGLBlendFuncDFactor);
-    }
-
-    private static void assertMatrixEq(float[] expected, float[] actual) {
-        try {
-            for (int i = 0; i < 16; i++) {
-                assertFloatEq(expected[i], actual[i]);
-            }
-        } catch (Throwable t) {
-            Log.v(TAG, "expected = " + Arrays.toString(expected) +
-                    ", actual = " + Arrays.toString(actual));
-            fail();
-        }
-    }
-
-    public static void assertFloatEq(float expected, float actual) {
-        if (Math.abs(actual - expected) > 1e-6) {
-            Log.v(TAG, "expected: " + expected + ", actual: " + actual);
-            fail();
-        }
-    }
-}
diff --git a/tests/src/com/android/gallery3d/glrenderer/GLMock.java b/tests/src/com/android/gallery3d/glrenderer/GLMock.java
deleted file mode 100644
index b242217..0000000
--- a/tests/src/com/android/gallery3d/glrenderer/GLMock.java
+++ /dev/null
@@ -1,197 +0,0 @@
-/*
- * Copyright (C) 2010 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.gallery3d.glrenderer;
-
-import com.android.gallery3d.ui.PointerInfo;
-
-import java.nio.Buffer;
-import java.util.HashMap;
-import javax.microedition.khronos.opengles.GL10;
-import javax.microedition.khronos.opengles.GL11;
-
-public class GLMock extends GLStub {
-    @SuppressWarnings("unused")
-    private static final String TAG = "GLMock";
-
-    // glClear
-    int mGLClearCalled;
-    int mGLClearMask;
-    // glBlendFunc
-    int mGLBlendFuncCalled;
-    int mGLBlendFuncSFactor;
-    int mGLBlendFuncDFactor;
-    // glColor4[fx]
-    int mGLColorCalled;
-    int mGLColor;
-    // glEnable, glDisable
-    boolean mGLBlendEnabled;
-    boolean mGLStencilEnabled;
-    // glEnableClientState
-    boolean mGLVertexArrayEnabled;
-    // glVertexPointer
-    PointerInfo mGLVertexPointer;
-    // glMatrixMode
-    int mGLMatrixMode = GL10.GL_MODELVIEW;
-    // glLoadMatrixf
-    float[] mGLModelViewMatrix = new float[16];
-    float[] mGLProjectionMatrix = new float[16];
-    // glBindTexture
-    int mGLBindTextureId;
-    // glTexEnvf
-    HashMap<Integer, Float> mGLTexEnv0 = new HashMap<Integer, Float>();
-    HashMap<Integer, Float> mGLTexEnv1 = new HashMap<Integer, Float>();
-    // glActiveTexture
-    int mGLActiveTexture = GL11.GL_TEXTURE0;
-
-    @Override
-    public void glClear(int mask) {
-        mGLClearCalled++;
-        mGLClearMask = mask;
-    }
-
-    @Override
-    public void glBlendFunc(int sfactor, int dfactor) {
-        mGLBlendFuncSFactor = sfactor;
-        mGLBlendFuncDFactor = dfactor;
-        mGLBlendFuncCalled++;
-    }
-
-    @Override
-    public void glColor4f(float red, float green, float blue,
-        float alpha) {
-        mGLColorCalled++;
-        mGLColor = makeColor4f(red, green, blue, alpha);
-    }
-
-    @Override
-    public void glColor4x(int red, int green, int blue, int alpha) {
-        mGLColorCalled++;
-        mGLColor = makeColor4x(red, green, blue, alpha);
-    }
-
-    @Override
-    public void glEnable(int cap) {
-        if (cap == GL11.GL_BLEND) {
-            mGLBlendEnabled = true;
-        } else if (cap == GL11.GL_STENCIL_TEST) {
-            mGLStencilEnabled = true;
-        }
-    }
-
-    @Override
-    public void glDisable(int cap) {
-        if (cap == GL11.GL_BLEND) {
-            mGLBlendEnabled = false;
-        } else if (cap == GL11.GL_STENCIL_TEST) {
-            mGLStencilEnabled = false;
-        }
-    }
-
-    @Override
-    public void glEnableClientState(int array) {
-        if (array == GL10.GL_VERTEX_ARRAY) {
-           mGLVertexArrayEnabled = true;
-        }
-    }
-
-    @Override
-    public void glVertexPointer(int size, int type, int stride, Buffer pointer) {
-        mGLVertexPointer = new PointerInfo(size, type, stride, pointer);
-    }
-
-    @Override
-    public void glMatrixMode(int mode) {
-        mGLMatrixMode = mode;
-    }
-
-    @Override
-    public void glLoadMatrixf(float[] m, int offset) {
-        if (mGLMatrixMode == GL10.GL_MODELVIEW) {
-            System.arraycopy(m, offset, mGLModelViewMatrix, 0, 16);
-        } else if (mGLMatrixMode == GL10.GL_PROJECTION) {
-            System.arraycopy(m, offset, mGLProjectionMatrix, 0, 16);
-        }
-    }
-
-    @Override
-    public void glOrthof(
-        float left, float right, float bottom, float top,
-        float zNear, float zFar) {
-        float tx = -(right + left) / (right - left);
-        float ty = -(top + bottom) / (top - bottom);
-            float tz = - (zFar + zNear) / (zFar - zNear);
-            float[] m = new float[] {
-                    2 / (right - left), 0, 0,  0,
-                    0, 2 / (top - bottom), 0,  0,
-                    0, 0, -2 / (zFar - zNear), 0,
-                    tx, ty, tz, 1
-            };
-            glLoadMatrixf(m, 0);
-    }
-
-    @Override
-    public void glBindTexture(int target, int texture) {
-        if (target == GL11.GL_TEXTURE_2D) {
-            mGLBindTextureId = texture;
-        }
-    }
-
-    @Override
-    public void glTexEnvf(int target, int pname, float param) {
-        if (target == GL11.GL_TEXTURE_ENV) {
-            if (mGLActiveTexture == GL11.GL_TEXTURE0) {
-                mGLTexEnv0.put(pname, param);
-            } else if (mGLActiveTexture == GL11.GL_TEXTURE1) {
-                mGLTexEnv1.put(pname, param);
-            } else {
-                throw new AssertionError();
-            }
-        }
-    }
-
-    public int getTexEnvi(int pname) {
-        return getTexEnvi(mGLActiveTexture, pname);
-    }
-
-    public int getTexEnvi(int activeTexture, int pname) {
-        if (activeTexture == GL11.GL_TEXTURE0) {
-            return (int) mGLTexEnv0.get(pname).floatValue();
-        } else if (activeTexture == GL11.GL_TEXTURE1) {
-            return (int) mGLTexEnv1.get(pname).floatValue();
-        } else {
-            throw new AssertionError();
-        }
-    }
-
-    @Override
-    public void glActiveTexture(int texture) {
-        mGLActiveTexture = texture;
-    }
-
-    public static int makeColor4f(float red, float green, float blue,
-            float alpha) {
-        return (Math.round(alpha * 255) << 24) |
-                (Math.round(red * 255) << 16) |
-                (Math.round(green * 255) << 8) |
-                Math.round(blue * 255);
-    }
-
-    public static int makeColor4x(int red, int green, int blue, int alpha) {
-        final float X = 65536f;
-        return makeColor4f(red / X, green / X, blue / X, alpha / X);
-    }
-}
diff --git a/tests/src/com/android/gallery3d/glrenderer/GLStub.java b/tests/src/com/android/gallery3d/glrenderer/GLStub.java
deleted file mode 100644
index 4b66040..0000000
--- a/tests/src/com/android/gallery3d/glrenderer/GLStub.java
+++ /dev/null
@@ -1,1490 +0,0 @@
-/*
- * Copyright (C) 2010 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.gallery3d.glrenderer;
-
-import javax.microedition.khronos.opengles.GL;
-import javax.microedition.khronos.opengles.GL10;
-import javax.microedition.khronos.opengles.GL10Ext;
-import javax.microedition.khronos.opengles.GL11;
-import javax.microedition.khronos.opengles.GL11Ext;
-
-public class GLStub implements GL, GL10, GL10Ext, GL11, GL11Ext {
-    @SuppressWarnings("unused")
-    private static final String TAG = "GLStub";
-
-    public void glActiveTexture(
-        int texture
-    ){}
-
-    public void glAlphaFunc(
-        int func,
-        float ref
-    ){}
-
-    public void glAlphaFuncx(
-        int func,
-        int ref
-    ){}
-
-    public void glBindTexture(
-        int target,
-        int texture
-    ){}
-
-    public void glBlendFunc(
-        int sfactor,
-        int dfactor
-    ){}
-
-    public void glClear(
-        int mask
-    ){}
-
-    public void glClearColor(
-        float red,
-        float green,
-        float blue,
-        float alpha
-    ){}
-
-    public void glClearColorx(
-        int red,
-        int green,
-        int blue,
-        int alpha
-    ){}
-
-    public void glClearDepthf(
-        float depth
-    ){}
-
-    public void glClearDepthx(
-        int depth
-    ){}
-
-    public void glClearStencil(
-        int s
-    ){}
-
-    public void glClientActiveTexture(
-        int texture
-    ){}
-
-    public void glColor4f(
-        float red,
-        float green,
-        float blue,
-        float alpha
-    ){}
-
-    public void glColor4x(
-        int red,
-        int green,
-        int blue,
-        int alpha
-    ){}
-
-    public void glColorMask(
-        boolean red,
-        boolean green,
-        boolean blue,
-        boolean alpha
-    ){}
-
-    public void glColorPointer(
-        int size,
-        int type,
-        int stride,
-        java.nio.Buffer pointer
-    ){}
-
-    public void glCompressedTexImage2D(
-        int target,
-        int level,
-        int internalformat,
-        int width,
-        int height,
-        int border,
-        int imageSize,
-        java.nio.Buffer data
-    ){}
-
-    public void glCompressedTexSubImage2D(
-        int target,
-        int level,
-        int xoffset,
-        int yoffset,
-        int width,
-        int height,
-        int format,
-        int imageSize,
-        java.nio.Buffer data
-    ){}
-
-    public void glCopyTexImage2D(
-        int target,
-        int level,
-        int internalformat,
-        int x,
-        int y,
-        int width,
-        int height,
-        int border
-    ){}
-
-    public void glCopyTexSubImage2D(
-        int target,
-        int level,
-        int xoffset,
-        int yoffset,
-        int x,
-        int y,
-        int width,
-        int height
-    ){}
-
-    public void glCullFace(
-        int mode
-    ){}
-
-    public void glDeleteTextures(
-        int n,
-        int[] textures,
-        int offset
-    ){}
-
-    public void glDeleteTextures(
-        int n,
-        java.nio.IntBuffer textures
-    ){}
-
-    public void glDepthFunc(
-        int func
-    ){}
-
-    public void glDepthMask(
-        boolean flag
-    ){}
-
-    public void glDepthRangef(
-        float zNear,
-        float zFar
-    ){}
-
-    public void glDepthRangex(
-        int zNear,
-        int zFar
-    ){}
-
-    public void glDisable(
-        int cap
-    ){}
-
-    public void glDisableClientState(
-        int array
-    ){}
-
-    public void glDrawArrays(
-        int mode,
-        int first,
-        int count
-    ){}
-
-    public void glDrawElements(
-        int mode,
-        int count,
-        int type,
-        java.nio.Buffer indices
-    ){}
-
-    public void glEnable(
-        int cap
-    ){}
-
-    public void glEnableClientState(
-        int array
-    ){}
-
-    public void glFinish(
-    ){}
-
-    public void glFlush(
-    ){}
-
-    public void glFogf(
-        int pname,
-        float param
-    ){}
-
-    public void glFogfv(
-        int pname,
-        float[] params,
-        int offset
-    ){}
-
-    public void glFogfv(
-        int pname,
-        java.nio.FloatBuffer params
-    ){}
-
-    public void glFogx(
-        int pname,
-        int param
-    ){}
-
-    public void glFogxv(
-        int pname,
-        int[] params,
-        int offset
-    ){}
-
-    public void glFogxv(
-        int pname,
-        java.nio.IntBuffer params
-    ){}
-
-    public void glFrontFace(
-        int mode
-    ){}
-
-    public void glFrustumf(
-        float left,
-        float right,
-        float bottom,
-        float top,
-        float zNear,
-        float zFar
-    ){}
-
-    public void glFrustumx(
-        int left,
-        int right,
-        int bottom,
-        int top,
-        int zNear,
-        int zFar
-    ){}
-
-    public void glGenTextures(
-        int n,
-        int[] textures,
-        int offset
-    ){}
-
-    public void glGenTextures(
-        int n,
-        java.nio.IntBuffer textures
-    ){}
-
-    public int glGetError(
-    ){ throw new UnsupportedOperationException(); }
-
-    public void glGetIntegerv(
-        int pname,
-        int[] params,
-        int offset
-    ){}
-
-    public void glGetIntegerv(
-        int pname,
-        java.nio.IntBuffer params
-    ){}
-
-    public String glGetString(
-        int name
-    ){ throw new UnsupportedOperationException(); }
-
-    public void glHint(
-        int target,
-        int mode
-    ){}
-
-    public void glLightModelf(
-        int pname,
-        float param
-    ){}
-
-    public void glLightModelfv(
-        int pname,
-        float[] params,
-        int offset
-    ){}
-
-    public void glLightModelfv(
-        int pname,
-        java.nio.FloatBuffer params
-    ){}
-
-    public void glLightModelx(
-        int pname,
-        int param
-    ){}
-
-    public void glLightModelxv(
-        int pname,
-        int[] params,
-        int offset
-    ){}
-
-    public void glLightModelxv(
-        int pname,
-        java.nio.IntBuffer params
-    ){}
-
-    public void glLightf(
-        int light,
-        int pname,
-        float param
-    ){}
-
-    public void glLightfv(
-        int light,
-        int pname,
-        float[] params,
-        int offset
-    ){}
-
-    public void glLightfv(
-        int light,
-        int pname,
-        java.nio.FloatBuffer params
-    ){}
-
-    public void glLightx(
-        int light,
-        int pname,
-        int param
-    ){}
-
-    public void glLightxv(
-        int light,
-        int pname,
-        int[] params,
-        int offset
-    ){}
-
-    public void glLightxv(
-        int light,
-        int pname,
-        java.nio.IntBuffer params
-    ){}
-
-    public void glLineWidth(
-        float width
-    ){}
-
-    public void glLineWidthx(
-        int width
-    ){}
-
-    public void glLoadIdentity(
-    ){}
-
-    public void glLoadMatrixf(
-        float[] m,
-        int offset
-    ){}
-
-    public void glLoadMatrixf(
-        java.nio.FloatBuffer m
-    ){}
-
-    public void glLoadMatrixx(
-        int[] m,
-        int offset
-    ){}
-
-    public void glLoadMatrixx(
-        java.nio.IntBuffer m
-    ){}
-
-    public void glLogicOp(
-        int opcode
-    ){}
-
-    public void glMaterialf(
-        int face,
-        int pname,
-        float param
-    ){}
-
-    public void glMaterialfv(
-        int face,
-        int pname,
-        float[] params,
-        int offset
-    ){}
-
-    public void glMaterialfv(
-        int face,
-        int pname,
-        java.nio.FloatBuffer params
-    ){}
-
-    public void glMaterialx(
-        int face,
-        int pname,
-        int param
-    ){}
-
-    public void glMaterialxv(
-        int face,
-        int pname,
-        int[] params,
-        int offset
-    ){}
-
-    public void glMaterialxv(
-        int face,
-        int pname,
-        java.nio.IntBuffer params
-    ){}
-
-    public void glMatrixMode(
-        int mode
-    ){}
-
-    public void glMultMatrixf(
-        float[] m,
-        int offset
-    ){}
-
-    public void glMultMatrixf(
-        java.nio.FloatBuffer m
-    ){}
-
-    public void glMultMatrixx(
-        int[] m,
-        int offset
-    ){}
-
-    public void glMultMatrixx(
-        java.nio.IntBuffer m
-    ){}
-
-    public void glMultiTexCoord4f(
-        int target,
-        float s,
-        float t,
-        float r,
-        float q
-    ){}
-
-    public void glMultiTexCoord4x(
-        int target,
-        int s,
-        int t,
-        int r,
-        int q
-    ){}
-
-    public void glNormal3f(
-        float nx,
-        float ny,
-        float nz
-    ){}
-
-    public void glNormal3x(
-        int nx,
-        int ny,
-        int nz
-    ){}
-
-    public void glNormalPointer(
-        int type,
-        int stride,
-        java.nio.Buffer pointer
-    ){}
-
-    public void glOrthof(
-        float left,
-        float right,
-        float bottom,
-        float top,
-        float zNear,
-        float zFar
-    ){}
-
-    public void glOrthox(
-        int left,
-        int right,
-        int bottom,
-        int top,
-        int zNear,
-        int zFar
-    ){}
-
-    public void glPixelStorei(
-        int pname,
-        int param
-    ){}
-
-    public void glPointSize(
-        float size
-    ){}
-
-    public void glPointSizex(
-        int size
-    ){}
-
-    public void glPolygonOffset(
-        float factor,
-        float units
-    ){}
-
-    public void glPolygonOffsetx(
-        int factor,
-        int units
-    ){}
-
-    public void glPopMatrix(
-    ){}
-
-    public void glPushMatrix(
-    ){}
-
-    public void glReadPixels(
-        int x,
-        int y,
-        int width,
-        int height,
-        int format,
-        int type,
-        java.nio.Buffer pixels
-    ){}
-
-    public void glRotatef(
-        float angle,
-        float x,
-        float y,
-        float z
-    ){}
-
-    public void glRotatex(
-        int angle,
-        int x,
-        int y,
-        int z
-    ){}
-
-    public void glSampleCoverage(
-        float value,
-        boolean invert
-    ){}
-
-    public void glSampleCoveragex(
-        int value,
-        boolean invert
-    ){}
-
-    public void glScalef(
-        float x,
-        float y,
-        float z
-    ){}
-
-    public void glScalex(
-        int x,
-        int y,
-        int z
-    ){}
-
-    public void glScissor(
-        int x,
-        int y,
-        int width,
-        int height
-    ){}
-
-    public void glShadeModel(
-        int mode
-    ){}
-
-    public void glStencilFunc(
-        int func,
-        int ref,
-        int mask
-    ){}
-
-    public void glStencilMask(
-        int mask
-    ){}
-
-    public void glStencilOp(
-        int fail,
-        int zfail,
-        int zpass
-    ){}
-
-    public void glTexCoordPointer(
-        int size,
-        int type,
-        int stride,
-        java.nio.Buffer pointer
-    ){}
-
-    public void glTexEnvf(
-        int target,
-        int pname,
-        float param
-    ){}
-
-    public void glTexEnvfv(
-        int target,
-        int pname,
-        float[] params,
-        int offset
-    ){}
-
-    public void glTexEnvfv(
-        int target,
-        int pname,
-        java.nio.FloatBuffer params
-    ){}
-
-    public void glTexEnvx(
-        int target,
-        int pname,
-        int param
-    ){}
-
-    public void glTexEnvxv(
-        int target,
-        int pname,
-        int[] params,
-        int offset
-    ){}
-
-    public void glTexEnvxv(
-        int target,
-        int pname,
-        java.nio.IntBuffer params
-    ){}
-
-    public void glTexImage2D(
-        int target,
-        int level,
-        int internalformat,
-        int width,
-        int height,
-        int border,
-        int format,
-        int type,
-        java.nio.Buffer pixels
-    ){}
-
-    public void glTexParameterf(
-        int target,
-        int pname,
-        float param
-    ){}
-
-    public void glTexParameterx(
-        int target,
-        int pname,
-        int param
-    ){}
-
-    public void glTexSubImage2D(
-        int target,
-        int level,
-        int xoffset,
-        int yoffset,
-        int width,
-        int height,
-        int format,
-        int type,
-        java.nio.Buffer pixels
-    ){}
-
-    public void glTranslatef(
-        float x,
-        float y,
-        float z
-    ){}
-
-    public void glTranslatex(
-        int x,
-        int y,
-        int z
-    ){}
-
-    public void glVertexPointer(
-        int size,
-        int type,
-        int stride,
-        java.nio.Buffer pointer
-    ){}
-
-    public void glViewport(
-        int x,
-        int y,
-        int width,
-        int height
-    ){}
-
-    public int glQueryMatrixxOES(
-        int[] mantissa,
-        int mantissaOffset,
-        int[] exponent,
-        int exponentOffset
-    ){ throw new UnsupportedOperationException(); }
-
-    public int glQueryMatrixxOES(
-        java.nio.IntBuffer mantissa,
-        java.nio.IntBuffer exponent
-    ){ throw new UnsupportedOperationException(); }
-
-    public void glGetPointerv(int pname, java.nio.Buffer[] params){}
-    public void glBindBuffer(
-        int target,
-        int buffer
-    ){}
-
-    public void glBufferData(
-        int target,
-        int size,
-        java.nio.Buffer data,
-        int usage
-    ){}
-
-    public void glBufferSubData(
-        int target,
-        int offset,
-        int size,
-        java.nio.Buffer data
-    ){}
-
-    public void glClipPlanef(
-        int plane,
-        float[] equation,
-        int offset
-    ){}
-
-    public void glClipPlanef(
-        int plane,
-        java.nio.FloatBuffer equation
-    ){}
-
-    public void glClipPlanex(
-        int plane,
-        int[] equation,
-        int offset
-    ){}
-
-    public void glClipPlanex(
-        int plane,
-        java.nio.IntBuffer equation
-    ){}
-
-    public void glColor4ub(
-        byte red,
-        byte green,
-        byte blue,
-        byte alpha
-    ){}
-
-    public void glColorPointer(
-        int size,
-        int type,
-        int stride,
-        int offset
-    ){}
-
-    public void glDeleteBuffers(
-        int n,
-        int[] buffers,
-        int offset
-    ){}
-
-    public void glDeleteBuffers(
-        int n,
-        java.nio.IntBuffer buffers
-    ){}
-
-    public void glDrawElements(
-        int mode,
-        int count,
-        int type,
-        int offset
-    ){}
-
-    public void glGenBuffers(
-        int n,
-        int[] buffers,
-        int offset
-    ){}
-
-    public void glGenBuffers(
-        int n,
-        java.nio.IntBuffer buffers
-    ){}
-
-    public void glGetBooleanv(
-        int pname,
-        boolean[] params,
-        int offset
-    ){}
-
-    public void glGetBooleanv(
-        int pname,
-        java.nio.IntBuffer params
-    ){}
-
-    public void glGetBufferParameteriv(
-        int target,
-        int pname,
-        int[] params,
-        int offset
-    ){}
-
-    public void glGetBufferParameteriv(
-        int target,
-        int pname,
-        java.nio.IntBuffer params
-    ){}
-
-    public void glGetClipPlanef(
-        int pname,
-        float[] eqn,
-        int offset
-    ){}
-
-    public void glGetClipPlanef(
-        int pname,
-        java.nio.FloatBuffer eqn
-    ){}
-
-    public void glGetClipPlanex(
-        int pname,
-        int[] eqn,
-        int offset
-    ){}
-
-    public void glGetClipPlanex(
-        int pname,
-        java.nio.IntBuffer eqn
-    ){}
-
-    public void glGetFixedv(
-        int pname,
-        int[] params,
-        int offset
-    ){}
-
-    public void glGetFixedv(
-        int pname,
-        java.nio.IntBuffer params
-    ){}
-
-    public void glGetFloatv(
-        int pname,
-        float[] params,
-        int offset
-    ){}
-
-    public void glGetFloatv(
-        int pname,
-        java.nio.FloatBuffer params
-    ){}
-
-    public void glGetLightfv(
-        int light,
-        int pname,
-        float[] params,
-        int offset
-    ){}
-
-    public void glGetLightfv(
-        int light,
-        int pname,
-        java.nio.FloatBuffer params
-    ){}
-
-    public void glGetLightxv(
-        int light,
-        int pname,
-        int[] params,
-        int offset
-    ){}
-
-    public void glGetLightxv(
-        int light,
-        int pname,
-        java.nio.IntBuffer params
-    ){}
-
-    public void glGetMaterialfv(
-        int face,
-        int pname,
-        float[] params,
-        int offset
-    ){}
-
-    public void glGetMaterialfv(
-        int face,
-        int pname,
-        java.nio.FloatBuffer params
-    ){}
-
-    public void glGetMaterialxv(
-        int face,
-        int pname,
-        int[] params,
-        int offset
-    ){}
-
-    public void glGetMaterialxv(
-        int face,
-        int pname,
-        java.nio.IntBuffer params
-    ){}
-
-    public void glGetTexEnviv(
-        int env,
-        int pname,
-        int[] params,
-        int offset
-    ){}
-
-    public void glGetTexEnviv(
-        int env,
-        int pname,
-        java.nio.IntBuffer params
-    ){}
-
-    public void glGetTexEnvxv(
-        int env,
-        int pname,
-        int[] params,
-        int offset
-    ){}
-
-    public void glGetTexEnvxv(
-        int env,
-        int pname,
-        java.nio.IntBuffer params
-    ){}
-
-    public void glGetTexParameterfv(
-        int target,
-        int pname,
-        float[] params,
-        int offset
-    ){}
-
-    public void glGetTexParameterfv(
-        int target,
-        int pname,
-        java.nio.FloatBuffer params
-    ){}
-
-    public void glGetTexParameteriv(
-        int target,
-        int pname,
-        int[] params,
-        int offset
-    ){}
-
-    public void glGetTexParameteriv(
-        int target,
-        int pname,
-        java.nio.IntBuffer params
-    ){}
-
-    public void glGetTexParameterxv(
-        int target,
-        int pname,
-        int[] params,
-        int offset
-    ){}
-
-    public void glGetTexParameterxv(
-        int target,
-        int pname,
-        java.nio.IntBuffer params
-    ){}
-
-    public boolean glIsBuffer(
-        int buffer
-    ){ throw new UnsupportedOperationException(); }
-
-    public boolean glIsEnabled(
-        int cap
-    ){ throw new UnsupportedOperationException(); }
-
-    public boolean glIsTexture(
-        int texture
-    ){ throw new UnsupportedOperationException(); }
-
-    public void glNormalPointer(
-        int type,
-        int stride,
-        int offset
-    ){}
-
-    public void glPointParameterf(
-        int pname,
-        float param
-    ){}
-
-    public void glPointParameterfv(
-        int pname,
-        float[] params,
-        int offset
-    ){}
-
-    public void glPointParameterfv(
-        int pname,
-        java.nio.FloatBuffer params
-    ){}
-
-    public void glPointParameterx(
-        int pname,
-        int param
-    ){}
-
-    public void glPointParameterxv(
-        int pname,
-        int[] params,
-        int offset
-    ){}
-
-    public void glPointParameterxv(
-        int pname,
-        java.nio.IntBuffer params
-    ){}
-
-    public void glPointSizePointerOES(
-        int type,
-        int stride,
-        java.nio.Buffer pointer
-    ){}
-
-    public void glTexCoordPointer(
-        int size,
-        int type,
-        int stride,
-        int offset
-    ){}
-
-    public void glTexEnvi(
-        int target,
-        int pname,
-        int param
-    ){}
-
-    public void glTexEnviv(
-        int target,
-        int pname,
-        int[] params,
-        int offset
-    ){}
-
-    public void glTexEnviv(
-        int target,
-        int pname,
-        java.nio.IntBuffer params
-    ){}
-
-    public void glTexParameterfv(
-        int target,
-        int pname,
-        float[] params,
-        int offset
-    ){}
-
-    public void glTexParameterfv(
-        int target,
-        int pname,
-        java.nio.FloatBuffer params
-    ){}
-
-    public void glTexParameteri(
-        int target,
-        int pname,
-        int param
-    ){}
-
-    public void glTexParameteriv(
-        int target,
-        int pname,
-        int[] params,
-        int offset
-    ){}
-
-    public void glTexParameteriv(
-        int target,
-        int pname,
-        java.nio.IntBuffer params
-    ){}
-
-    public void glTexParameterxv(
-        int target,
-        int pname,
-        int[] params,
-        int offset
-    ){}
-
-    public void glTexParameterxv(
-        int target,
-        int pname,
-        java.nio.IntBuffer params
-    ){}
-
-    public void glVertexPointer(
-        int size,
-        int type,
-        int stride,
-        int offset
-    ){}
-
-    public void glCurrentPaletteMatrixOES(
-        int matrixpaletteindex
-    ){}
-
-    public void glDrawTexfOES(
-        float x,
-        float y,
-        float z,
-        float width,
-        float height
-    ){}
-
-    public void glDrawTexfvOES(
-        float[] coords,
-        int offset
-    ){}
-
-    public void glDrawTexfvOES(
-        java.nio.FloatBuffer coords
-    ){}
-
-    public void glDrawTexiOES(
-        int x,
-        int y,
-        int z,
-        int width,
-        int height
-    ){}
-
-    public void glDrawTexivOES(
-        int[] coords,
-        int offset
-    ){}
-
-    public void glDrawTexivOES(
-        java.nio.IntBuffer coords
-    ){}
-
-    public void glDrawTexsOES(
-        short x,
-        short y,
-        short z,
-        short width,
-        short height
-    ){}
-
-    public void glDrawTexsvOES(
-        short[] coords,
-        int offset
-    ){}
-
-    public void glDrawTexsvOES(
-        java.nio.ShortBuffer coords
-    ){}
-
-    public void glDrawTexxOES(
-        int x,
-        int y,
-        int z,
-        int width,
-        int height
-    ){}
-
-    public void glDrawTexxvOES(
-        int[] coords,
-        int offset
-    ){}
-
-    public void glDrawTexxvOES(
-        java.nio.IntBuffer coords
-    ){}
-
-    public void glLoadPaletteFromModelViewMatrixOES(
-    ){}
-
-    public void glMatrixIndexPointerOES(
-        int size,
-        int type,
-        int stride,
-        java.nio.Buffer pointer
-    ){}
-
-    public void glMatrixIndexPointerOES(
-        int size,
-        int type,
-        int stride,
-        int offset
-    ){}
-
-    public void glWeightPointerOES(
-        int size,
-        int type,
-        int stride,
-        java.nio.Buffer pointer
-    ){}
-
-    public void glWeightPointerOES(
-        int size,
-        int type,
-        int stride,
-        int offset
-    ){}
-
-    public void glBindFramebufferOES(
-        int target,
-        int framebuffer
-    ){}
-
-    public void glBindRenderbufferOES(
-        int target,
-        int renderbuffer
-    ){}
-
-    public void glBlendEquation(
-        int mode
-    ){}
-
-    public void glBlendEquationSeparate(
-        int modeRGB,
-        int modeAlpha
-    ){}
-
-    public void glBlendFuncSeparate(
-        int srcRGB,
-        int dstRGB,
-        int srcAlpha,
-        int dstAlpha
-    ){}
-
-    public int glCheckFramebufferStatusOES(
-        int target
-    ){ throw new UnsupportedOperationException(); }
-
-    public void glDeleteFramebuffersOES(
-        int n,
-        int[] framebuffers,
-        int offset
-    ){}
-
-    public void glDeleteFramebuffersOES(
-        int n,
-        java.nio.IntBuffer framebuffers
-    ){}
-
-    public void glDeleteRenderbuffersOES(
-        int n,
-        int[] renderbuffers,
-        int offset
-    ){}
-
-    public void glDeleteRenderbuffersOES(
-        int n,
-        java.nio.IntBuffer renderbuffers
-    ){}
-
-    public void glFramebufferRenderbufferOES(
-        int target,
-        int attachment,
-        int renderbuffertarget,
-        int renderbuffer
-    ){}
-
-    public void glFramebufferTexture2DOES(
-        int target,
-        int attachment,
-        int textarget,
-        int texture,
-        int level
-    ){}
-
-    public void glGenerateMipmapOES(
-        int target
-    ){}
-
-    public void glGenFramebuffersOES(
-        int n,
-        int[] framebuffers,
-        int offset
-    ){}
-
-    public void glGenFramebuffersOES(
-        int n,
-        java.nio.IntBuffer framebuffers
-    ){}
-
-    public void glGenRenderbuffersOES(
-        int n,
-        int[] renderbuffers,
-        int offset
-    ){}
-
-    public void glGenRenderbuffersOES(
-        int n,
-        java.nio.IntBuffer renderbuffers
-    ){}
-
-    public void glGetFramebufferAttachmentParameterivOES(
-        int target,
-        int attachment,
-        int pname,
-        int[] params,
-        int offset
-    ){}
-
-    public void glGetFramebufferAttachmentParameterivOES(
-        int target,
-        int attachment,
-        int pname,
-        java.nio.IntBuffer params
-    ){}
-
-    public void glGetRenderbufferParameterivOES(
-        int target,
-        int pname,
-        int[] params,
-        int offset
-    ){}
-
-    public void glGetRenderbufferParameterivOES(
-        int target,
-        int pname,
-        java.nio.IntBuffer params
-    ){}
-
-    public void glGetTexGenfv(
-        int coord,
-        int pname,
-        float[] params,
-        int offset
-    ){}
-
-    public void glGetTexGenfv(
-        int coord,
-        int pname,
-        java.nio.FloatBuffer params
-    ){}
-
-    public void glGetTexGeniv(
-        int coord,
-        int pname,
-        int[] params,
-        int offset
-    ){}
-
-    public void glGetTexGeniv(
-        int coord,
-        int pname,
-        java.nio.IntBuffer params
-    ){}
-
-    public void glGetTexGenxv(
-        int coord,
-        int pname,
-        int[] params,
-        int offset
-    ){}
-
-    public void glGetTexGenxv(
-        int coord,
-        int pname,
-        java.nio.IntBuffer params
-    ){}
-
-    public boolean glIsFramebufferOES(
-        int framebuffer
-    ){ throw new UnsupportedOperationException(); }
-
-    public boolean glIsRenderbufferOES(
-        int renderbuffer
-    ){ throw new UnsupportedOperationException(); }
-
-    public void glRenderbufferStorageOES(
-        int target,
-        int internalformat,
-        int width,
-        int height
-    ){}
-
-    public void glTexGenf(
-        int coord,
-        int pname,
-        float param
-    ){}
-
-    public void glTexGenfv(
-        int coord,
-        int pname,
-        float[] params,
-        int offset
-    ){}
-
-    public void glTexGenfv(
-        int coord,
-        int pname,
-        java.nio.FloatBuffer params
-    ){}
-
-    public void glTexGeni(
-        int coord,
-        int pname,
-        int param
-    ){}
-
-    public void glTexGeniv(
-        int coord,
-        int pname,
-        int[] params,
-        int offset
-    ){}
-
-    public void glTexGeniv(
-        int coord,
-        int pname,
-        java.nio.IntBuffer params
-    ){}
-
-    public void glTexGenx(
-        int coord,
-        int pname,
-        int param
-    ){}
-
-    public void glTexGenxv(
-        int coord,
-        int pname,
-        int[] params,
-        int offset
-    ){}
-
-    public void glTexGenxv(
-        int coord,
-        int pname,
-        java.nio.IntBuffer params
-    ){}
-}
diff --git a/tests/src/com/android/gallery3d/glrenderer/TextureTest.java b/tests/src/com/android/gallery3d/glrenderer/TextureTest.java
deleted file mode 100644
index 9e79554..0000000
--- a/tests/src/com/android/gallery3d/glrenderer/TextureTest.java
+++ /dev/null
@@ -1,208 +0,0 @@
-/*
- * Copyright (C) 2010 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.gallery3d.glrenderer;
-
-import android.graphics.Bitmap;
-import android.graphics.Bitmap.Config;
-import android.test.suitebuilder.annotation.SmallTest;
-
-import com.android.gallery3d.glrenderer.BasicTexture;
-import com.android.gallery3d.glrenderer.BitmapTexture;
-import com.android.gallery3d.glrenderer.ColorTexture;
-import com.android.gallery3d.glrenderer.GLCanvas;
-import com.android.gallery3d.glrenderer.GLES11Canvas;
-import com.android.gallery3d.glrenderer.UploadedTexture;
-
-import junit.framework.TestCase;
-
-import javax.microedition.khronos.opengles.GL11;
-
-public class TextureTest extends TestCase {
-    @SuppressWarnings("unused")
-    private static final String TAG = "TextureTest";
-
-    class MyBasicTexture extends BasicTexture {
-        int mOnBindCalled;
-        int mOpaqueCalled;
-
-        MyBasicTexture(GLCanvas canvas, int id) {
-            super(canvas, id, 0);
-        }
-
-        @Override
-        protected boolean onBind(GLCanvas canvas) {
-            mOnBindCalled++;
-            return true;
-        }
-
-        @Override
-        protected int getTarget() {
-            return GL11.GL_TEXTURE_2D;
-        }
-
-        @Override
-        public boolean isOpaque() {
-            mOpaqueCalled++;
-            return true;
-        }
-
-        void upload() {
-            mState = STATE_LOADED;
-        }
-    }
-
-    @SmallTest
-    public void testBasicTexture() {
-        GL11 glStub = new GLStub();
-        GLCanvas canvas = new GLES11Canvas(glStub);
-        MyBasicTexture texture = new MyBasicTexture(canvas, 47);
-
-        assertEquals(47, texture.getId());
-        texture.setSize(1, 1);
-        assertEquals(1, texture.getWidth());
-        assertEquals(1, texture.getHeight());
-        assertEquals(1, texture.getTextureWidth());
-        assertEquals(1, texture.getTextureHeight());
-        texture.setSize(3, 5);
-        assertEquals(3, texture.getWidth());
-        assertEquals(5, texture.getHeight());
-        assertEquals(4, texture.getTextureWidth());
-        assertEquals(8, texture.getTextureHeight());
-
-        assertFalse(texture.isLoaded());
-        texture.upload();
-        assertTrue(texture.isLoaded());
-
-        // For a different GL, it's not loaded.
-        GLCanvas canvas2 = new GLES11Canvas(glStub);
-        assertFalse(texture.isLoaded());
-
-        assertEquals(0, texture.mOnBindCalled);
-        assertEquals(0, texture.mOpaqueCalled);
-        texture.draw(canvas, 100, 200, 1, 1);
-        assertEquals(1, texture.mOnBindCalled);
-        assertEquals(1, texture.mOpaqueCalled);
-        texture.draw(canvas, 0, 0);
-        assertEquals(2, texture.mOnBindCalled);
-        assertEquals(2, texture.mOpaqueCalled);
-    }
-
-    @SmallTest
-    public void testColorTexture() {
-        GLCanvasMock canvas = new GLCanvasMock();
-        ColorTexture texture = new ColorTexture(0x12345678);
-
-        texture.setSize(42, 47);
-        assertEquals(texture.getWidth(), 42);
-        assertEquals(texture.getHeight(), 47);
-        assertEquals(0, canvas.mFillRectCalled);
-        texture.draw(canvas, 0, 0);
-        assertEquals(1, canvas.mFillRectCalled);
-        assertEquals(0x12345678, canvas.mFillRectColor);
-        assertEquals(42f, canvas.mFillRectWidth);
-        assertEquals(47f, canvas.mFillRectHeight);
-        assertFalse(texture.isOpaque());
-        assertTrue(new ColorTexture(0xFF000000).isOpaque());
-    }
-
-    private class MyUploadedTexture extends UploadedTexture {
-        int mGetCalled;
-        int mFreeCalled;
-        Bitmap mBitmap;
-        @Override
-        protected Bitmap onGetBitmap() {
-            mGetCalled++;
-            Config config = Config.ARGB_8888;
-            mBitmap = Bitmap.createBitmap(47, 42, config);
-            return mBitmap;
-        }
-        @Override
-        protected void onFreeBitmap(Bitmap bitmap) {
-            mFreeCalled++;
-            assertSame(mBitmap, bitmap);
-            mBitmap.recycle();
-            mBitmap = null;
-        }
-    }
-
-    @SmallTest
-    public void testUploadedTexture() {
-        GL11 glStub = new GLStub();
-        GLCanvas canvas = new GLES11Canvas(glStub);
-        MyUploadedTexture texture = new MyUploadedTexture();
-
-        // draw it and the bitmap should be fetched.
-        assertEquals(0, texture.mFreeCalled);
-        assertEquals(0, texture.mGetCalled);
-        texture.draw(canvas, 0, 0);
-        assertEquals(1, texture.mGetCalled);
-        assertTrue(texture.isLoaded());
-        assertTrue(texture.isContentValid());
-
-        // invalidate content and it should be freed.
-        texture.invalidateContent();
-        assertFalse(texture.isContentValid());
-        assertEquals(1, texture.mFreeCalled);
-        assertTrue(texture.isLoaded());  // But it's still loaded
-
-        // draw it again and the bitmap should be fetched again.
-        texture.draw(canvas, 0, 0);
-        assertEquals(2, texture.mGetCalled);
-        assertTrue(texture.isLoaded());
-        assertTrue(texture.isContentValid());
-
-        // recycle the texture and it should be freed again.
-        texture.recycle();
-        assertEquals(2, texture.mFreeCalled);
-        // TODO: these two are broken and waiting for fix.
-        //assertFalse(texture.isLoaded(canvas));
-        //assertFalse(texture.isContentValid(canvas));
-    }
-
-    class MyTextureForMixed extends BasicTexture {
-        MyTextureForMixed(GLCanvas canvas, int id) {
-            super(canvas, id, 0);
-        }
-
-        @Override
-        protected boolean onBind(GLCanvas canvas) {
-            return true;
-        }
-
-        @Override
-        protected int getTarget() {
-            return GL11.GL_TEXTURE_2D;
-        }
-
-        @Override
-        public boolean isOpaque() {
-            return true;
-        }
-    }
-
-    @SmallTest
-    public void testBitmapTexture() {
-        Config config = Config.ARGB_8888;
-        Bitmap bitmap = Bitmap.createBitmap(47, 42, config);
-        assertFalse(bitmap.isRecycled());
-        BitmapTexture texture = new BitmapTexture(bitmap);
-        texture.recycle();
-        assertFalse(bitmap.isRecycled());
-        bitmap.recycle();
-        assertTrue(bitmap.isRecycled());
-    }
-}
diff --git a/tests/src/com/android/gallery3d/jpegstream/JpegStreamReaderTest.java b/tests/src/com/android/gallery3d/jpegstream/JpegStreamReaderTest.java
deleted file mode 100644
index ae60a91..0000000
--- a/tests/src/com/android/gallery3d/jpegstream/JpegStreamReaderTest.java
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * Copyright (C) 2013 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.gallery3d.jpegstream;
-
-import android.test.suitebuilder.annotation.MediumTest;
-
-import android.graphics.Bitmap;
-import android.graphics.BitmapFactory;
-import android.graphics.Point;
-import android.os.Environment;
-import android.util.Log;
-
-import com.android.gallery3d.common.Utils;
-import com.android.gallery3d.tests.R;
-
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.File;
-import java.io.FileOutputStream;
-import java.nio.ByteBuffer;
-import java.nio.ByteOrder;
-import java.util.Arrays;
-
-public class JpegStreamReaderTest extends JpegStreamTestCase {
-    public static final String TAG = "JpegStreamReaderTest";
-    private JPEGInputStream mStream;
-    private Bitmap mBitmap;
-
-    public JpegStreamReaderTest(int imageRes) {
-        super(imageRes);
-    }
-
-    @Override
-    public void setUp() throws Exception {
-        super.setUp();
-        mBitmap = BitmapFactory.decodeStream(getImageInputStream());
-    }
-
-    @Override
-    public void tearDown() throws Exception {
-        super.tearDown();
-        Utils.closeSilently(mStream);
-        mStream = null;
-        if (mBitmap != null) {
-            mBitmap.recycle();
-            mBitmap = null;
-        }
-    }
-
-    @MediumTest
-    public void testBasicReads() throws Exception {
-
-        // Setup input stream.
-        mStream = new JPEGInputStream(reopenFileStream(), JpegConfig.FORMAT_RGBA);
-        Point dimens = mStream.getDimensions();
-
-        // Read whole stream into array.
-        byte[] bytes = new byte[dimens.x * StreamUtils.pixelSize(JpegConfig.FORMAT_RGBA) * dimens.y];
-        assertTrue(mStream.read(bytes, 0, bytes.length) == bytes.length);
-
-        // Set pixels in bitmap
-        Bitmap test = Bitmap.createBitmap(dimens.x, dimens.y, Bitmap.Config.ARGB_8888);
-        ByteBuffer buf = ByteBuffer.wrap(bytes);
-        test.copyPixelsFromBuffer(buf);
-        assertTrue(test.getWidth() == mBitmap.getWidth() && test.getHeight() == mBitmap.getHeight());
-        assertTrue(mStream.read(bytes, 0, bytes.length) == -1);
-    }
-
-    // TODO : more tests
-}
diff --git a/tests/src/com/android/gallery3d/jpegstream/JpegStreamTestCase.java b/tests/src/com/android/gallery3d/jpegstream/JpegStreamTestCase.java
deleted file mode 100644
index ed3b08a..0000000
--- a/tests/src/com/android/gallery3d/jpegstream/JpegStreamTestCase.java
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * Copyright (C) 2013 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.gallery3d.jpegstream;
-
-import android.content.res.Resources;
-import android.test.InstrumentationTestCase;
-import android.util.Log;
-
-import com.android.gallery3d.common.Utils;
-
-import java.io.InputStream;
-
-public class JpegStreamTestCase extends InstrumentationTestCase {
-    public static final String TAG = "JpegStreamTestCase";
-
-    private static final String RES_ID_TITLE = "Resource ID: %x";
-
-    private InputStream mImageInputStream;
-    private final int mImageResourceId;
-
-    public JpegStreamTestCase(int imageRes) {
-        mImageResourceId = imageRes;
-    }
-
-    protected InputStream getImageInputStream() {
-        return mImageInputStream;
-    }
-
-    @Override
-    public void setUp() throws Exception {
-        Log.d(TAG, "doing setUp...");
-        mImageInputStream = reopenFileStream();
-    }
-
-    @Override
-    public void tearDown() throws Exception {
-        Log.d(TAG, "doing tearDown...");
-        Utils.closeSilently(mImageInputStream);
-        mImageInputStream = null;
-    }
-
-    protected String getImageTitle() {
-        return String.format(RES_ID_TITLE, mImageResourceId);
-    }
-
-    protected InputStream reopenFileStream() throws Exception {
-        return openResource(mImageResourceId);
-    }
-
-    protected InputStream openResource(int resourceID) throws Exception {
-        try {
-            Resources res = getInstrumentation().getContext().getResources();
-            return res.openRawResource(resourceID);
-        } catch (Exception e) {
-            throw new Exception(getImageTitle(), e);
-        }
-    }
-}
diff --git a/tests/src/com/android/gallery3d/jpegstream/JpegStreamTestRunner.java b/tests/src/com/android/gallery3d/jpegstream/JpegStreamTestRunner.java
deleted file mode 100644
index 2afaf39..0000000
--- a/tests/src/com/android/gallery3d/jpegstream/JpegStreamTestRunner.java
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * Copyright (C) 2013 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.gallery3d.jpegstream;
-
-import android.test.InstrumentationTestRunner;
-import android.test.InstrumentationTestSuite;
-import android.util.Log;
-
-import com.android.gallery3d.exif.ExifTestRunner;
-import com.android.gallery3d.tests.R;
-
-import junit.framework.TestCase;
-import junit.framework.TestSuite;
-
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-
-public class JpegStreamTestRunner extends InstrumentationTestRunner {
-    private static final String TAG = "JpegStreamTestRunner";
-
-    private static final int[] IMG_RESOURCE = {
-            R.raw.galaxy_nexus
-    };
-
-    @Override
-    public TestSuite getAllTests() {
-        TestSuite suite = new InstrumentationTestSuite(this);
-        addAllTestsFromTestCase(JpegStreamReaderTest.class, suite);
-        addAllTestsFromTestCase(JpegStreamWriterTest.class, suite);
-        return suite;
-    }
-
-    private void addAllTestsFromTestCase(Class<? extends JpegStreamTestCase> testClass,
-            TestSuite suite) {
-        for (Method method : testClass.getDeclaredMethods()) {
-            if (method.getName().startsWith("test") && method.getParameterTypes().length == 0) {
-                for (int i = 0; i < IMG_RESOURCE.length; i++) {
-                    TestCase test;
-                    try {
-                        test = testClass.getDeclaredConstructor(int.class).
-                                newInstance(IMG_RESOURCE[i]);
-                        test.setName(method.getName());
-                        suite.addTest(test);
-                    } catch (IllegalArgumentException e) {
-                        Log.e(TAG, "Failed to create test case", e);
-                    } catch (InstantiationException e) {
-                        Log.e(TAG, "Failed to create test case", e);
-                    } catch (IllegalAccessException e) {
-                        Log.e(TAG, "Failed to create test case", e);
-                    } catch (InvocationTargetException e) {
-                        Log.e(TAG, "Failed to create test case", e);
-                    } catch (NoSuchMethodException e) {
-                        Log.e(TAG, "Failed to create test case", e);
-                    }
-                }
-            }
-        }
-    }
-
-    @Override
-    public ClassLoader getLoader() {
-        return ExifTestRunner.class.getClassLoader();
-    }
-}
diff --git a/tests/src/com/android/gallery3d/jpegstream/JpegStreamWriterTest.java b/tests/src/com/android/gallery3d/jpegstream/JpegStreamWriterTest.java
deleted file mode 100644
index befba4c..0000000
--- a/tests/src/com/android/gallery3d/jpegstream/JpegStreamWriterTest.java
+++ /dev/null
@@ -1,138 +0,0 @@
-/*
- * Copyright (C) 2013 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.gallery3d.jpegstream;
-
-import android.graphics.Bitmap;
-import android.graphics.BitmapFactory;
-import android.os.Environment;
-import android.util.Log;
-
-import com.android.gallery3d.common.Utils;
-import com.android.gallery3d.tests.R;
-
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.File;
-import java.io.FileOutputStream;
-import java.nio.ByteBuffer;
-
-public class JpegStreamWriterTest extends JpegStreamTestCase {
-    public static final String TAG = "JpegStreamWriterTest";
-    private JPEGOutputStream mStream;
-    private ByteArrayOutputStream mWrappedStream;
-    private Bitmap mBitmap;
-    private Bitmap mControl;
-
-    // galaxy_nexus.jpg image compressed with q=20
-    private static final int CONTROL_RID = R.raw.jpeg_control;
-
-    public JpegStreamWriterTest(int imageRes) {
-        super(imageRes);
-    }
-
-    @Override
-    public void setUp() throws Exception {
-        super.setUp();
-        mBitmap = BitmapFactory.decodeStream(getImageInputStream());
-        mControl = BitmapFactory.decodeStream(openResource(CONTROL_RID));
-        mWrappedStream = new ByteArrayOutputStream();
-
-    }
-
-    @Override
-    public void tearDown() throws Exception {
-        super.tearDown();
-        Utils.closeSilently(mStream);
-        Utils.closeSilently(mWrappedStream);
-        mWrappedStream = null;
-        mStream = null;
-        if (mBitmap != null) {
-            mBitmap.recycle();
-            mBitmap = null;
-        }
-        if (mControl != null) {
-            mControl.recycle();
-            mControl = null;
-        }
-    }
-
-    public void testBasicWrites() throws Exception {
-        assertTrue(mBitmap != null);
-        int width = mBitmap.getWidth();
-        int height = mBitmap.getHeight();
-        mStream = new JPEGOutputStream(mWrappedStream, width,
-                height, 20, JpegConfig.FORMAT_RGBA);
-
-        // Put bitmap pixels into a byte array (format is RGBA).
-        int rowLength = width * StreamUtils.pixelSize(JpegConfig.FORMAT_RGBA);
-        int size = height * rowLength;
-        byte[] byteArray = new byte[size];
-        ByteBuffer buf = ByteBuffer.wrap(byteArray);
-        mBitmap.copyPixelsToBuffer(buf);
-
-        // Write out whole array
-        mStream.write(byteArray, 0, byteArray.length);
-        mStream.close();
-
-        // Get compressed jpeg output
-        byte[] compressed = mWrappedStream.toByteArray();
-
-        // Check jpeg
-        ByteArrayInputStream inStream = new ByteArrayInputStream(compressed);
-        Bitmap test = BitmapFactory.decodeStream(inStream);
-        assertTrue(test != null);
-        assertTrue(test.sameAs(mControl));
-    }
-
-    public void testStreamingWrites() throws Exception {
-        assertTrue(mBitmap != null);
-        int width = mBitmap.getWidth();
-        int height = mBitmap.getHeight();
-        mStream = new JPEGOutputStream(mWrappedStream, width,
-                height, 20, JpegConfig.FORMAT_RGBA);
-
-        // Put bitmap pixels into a byte array (format is RGBA).
-        int rowLength = width * StreamUtils.pixelSize(JpegConfig.FORMAT_RGBA);
-        int size = height * rowLength;
-        byte[] byteArray = new byte[size];
-        ByteBuffer buf = ByteBuffer.wrap(byteArray);
-        mBitmap.copyPixelsToBuffer(buf);
-
-        // Write array in chunks
-        int chunkSize = rowLength / 3;
-        int written = 0;
-        while (written < size) {
-            if (written + chunkSize > size) {
-                chunkSize = size - written;
-            }
-            mStream.write(byteArray, written, chunkSize);
-            written += chunkSize;
-        }
-        mStream.close();
-
-        // Get compressed jpeg output
-        byte[] compressed = mWrappedStream.toByteArray();
-
-        // Check jpeg
-        ByteArrayInputStream inStream = new ByteArrayInputStream(compressed);
-        Bitmap test = BitmapFactory.decodeStream(inStream);
-        assertTrue(test != null);
-        assertTrue(test.sameAs(mControl));
-    }
-
-    // TODO : more tests
-}
diff --git a/tests/src/com/android/gallery3d/stress/CameraLatency.java b/tests/src/com/android/gallery3d/stress/CameraLatency.java
deleted file mode 100755
index 2cdc2f1..0000000
--- a/tests/src/com/android/gallery3d/stress/CameraLatency.java
+++ /dev/null
@@ -1,148 +0,0 @@
-/*
- * Copyright (C) 2009 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.gallery3d.stress;
-
-import com.android.camera.CameraActivity;
-
-import android.app.Instrumentation;
-import android.os.Environment;
-import android.test.ActivityInstrumentationTestCase2;
-import android.test.suitebuilder.annotation.LargeTest;
-import android.util.Log;
-import android.view.KeyEvent;
-
-import java.io.BufferedWriter;
-import java.io.FileWriter;
-
-/**
- * Junit / Instrumentation test case for camera test
- *
- */
-
-public class CameraLatency extends ActivityInstrumentationTestCase2 <CameraActivity> {
-    private String TAG = "CameraLatency";
-    private static final int TOTAL_NUMBER_OF_IMAGECAPTURE = 20;
-    private static final long WAIT_FOR_IMAGE_CAPTURE_TO_BE_TAKEN = 4000;
-    private static final String CAMERA_TEST_OUTPUT_FILE =
-            Environment.getExternalStorageDirectory().toString() + "/mediaStressOut.txt";
-
-    private long mTotalAutoFocusTime;
-    private long mTotalShutterLag;
-    private long mTotalShutterToPictureDisplayedTime;
-    private long mTotalPictureDisplayedToJpegCallbackTime;
-    private long mTotalJpegCallbackFinishTime;
-    private long mAvgAutoFocusTime;
-    private long mAvgShutterLag = mTotalShutterLag;
-    private long mAvgShutterToPictureDisplayedTime;
-    private long mAvgPictureDisplayedToJpegCallbackTime;
-    private long mAvgJpegCallbackFinishTime;
-
-    public CameraLatency() {
-        super(CameraActivity.class);
-    }
-
-    @Override
-    protected void setUp() throws Exception {
-        getActivity();
-        super.setUp();
-    }
-
-    @Override
-    protected void tearDown() throws Exception {
-        super.tearDown();
-    }
-
-    public void testImageCapture() {
-        Log.v(TAG, "start testImageCapture test");
-        Instrumentation inst = getInstrumentation();
-        inst.sendKeyDownUpSync(KeyEvent.KEYCODE_DPAD_DOWN);
-        try {
-            for (int i = 0; i < TOTAL_NUMBER_OF_IMAGECAPTURE; i++) {
-                Thread.sleep(WAIT_FOR_IMAGE_CAPTURE_TO_BE_TAKEN);
-                inst.sendKeyDownUpSync(KeyEvent.KEYCODE_DPAD_CENTER);
-                Thread.sleep(WAIT_FOR_IMAGE_CAPTURE_TO_BE_TAKEN);
-                //skip the first measurement
-                if (i != 0) {
-                    CameraActivity c = getActivity();
-
-                    // if any of the latency var accessor methods return -1 then the
-                    // camera is set to a different module other than PhotoModule so
-                    // skip the shot and try again
-                    if (c.getAutoFocusTime() != -1) {
-                        mTotalAutoFocusTime += c.getAutoFocusTime();
-                        mTotalShutterLag += c.getShutterLag();
-                        mTotalShutterToPictureDisplayedTime +=
-                                c.getShutterToPictureDisplayedTime();
-                        mTotalPictureDisplayedToJpegCallbackTime +=
-                                c.getPictureDisplayedToJpegCallbackTime();
-                        mTotalJpegCallbackFinishTime += c.getJpegCallbackFinishTime();
-                    }
-                    else {
-                        i--;
-                        continue;
-                    }
-                }
-            }
-        } catch (Exception e) {
-            Log.v(TAG, "Got exception", e);
-        }
-        //ToDO: yslau
-        //1) Need to get the baseline from the cupcake so that we can add the
-        //failure condition of the camera latency.
-        //2) Only count those number with succesful capture. Set the timer to invalid
-        //before capture and ignore them if the value is invalid
-        int numberofRun = TOTAL_NUMBER_OF_IMAGECAPTURE - 1;
-        mAvgAutoFocusTime = mTotalAutoFocusTime / numberofRun;
-        mAvgShutterLag = mTotalShutterLag / numberofRun;
-        mAvgShutterToPictureDisplayedTime =
-                mTotalShutterToPictureDisplayedTime / numberofRun;
-        mAvgPictureDisplayedToJpegCallbackTime =
-                mTotalPictureDisplayedToJpegCallbackTime / numberofRun;
-        mAvgJpegCallbackFinishTime =
-                mTotalJpegCallbackFinishTime / numberofRun;
-
-        try {
-            FileWriter fstream = null;
-            fstream = new FileWriter(CAMERA_TEST_OUTPUT_FILE, true);
-            BufferedWriter out = new BufferedWriter(fstream);
-            out.write("Camera Latency : \n");
-            out.write("Number of loop: " + TOTAL_NUMBER_OF_IMAGECAPTURE + "\n");
-            out.write("Avg AutoFocus = " + mAvgAutoFocusTime + "\n");
-            out.write("Avg mShutterLag = " + mAvgShutterLag + "\n");
-            out.write("Avg mShutterToPictureDisplayedTime = "
-                    + mAvgShutterToPictureDisplayedTime + "\n");
-            out.write("Avg mPictureDisplayedToJpegCallbackTime = "
-                    + mAvgPictureDisplayedToJpegCallbackTime + "\n");
-            out.write("Avg mJpegCallbackFinishTime = " +
-                    mAvgJpegCallbackFinishTime + "\n");
-            out.close();
-            fstream.close();
-        } catch (Exception e) {
-            fail("Camera Latency write output to file");
-        }
-        Log.v(TAG, "The Image capture wait time = " +
-            WAIT_FOR_IMAGE_CAPTURE_TO_BE_TAKEN);
-        Log.v(TAG, "Avg AutoFocus = " + mAvgAutoFocusTime);
-        Log.v(TAG, "Avg mShutterLag = " + mAvgShutterLag);
-        Log.v(TAG, "Avg mShutterToPictureDisplayedTime = "
-                + mAvgShutterToPictureDisplayedTime);
-        Log.v(TAG, "Avg mPictureDisplayedToJpegCallbackTime = "
-                + mAvgPictureDisplayedToJpegCallbackTime);
-        Log.v(TAG, "Avg mJpegCallbackFinishTime = " + mAvgJpegCallbackFinishTime);
-    }
-}
-
diff --git a/tests/src/com/android/gallery3d/stress/CameraStartUp.java b/tests/src/com/android/gallery3d/stress/CameraStartUp.java
deleted file mode 100644
index 3ca1632..0000000
--- a/tests/src/com/android/gallery3d/stress/CameraStartUp.java
+++ /dev/null
@@ -1,155 +0,0 @@
-/*
- * Copyright (C) 2009 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.gallery3d.stress;
-
-import com.android.camera.CameraActivity;
-
-import android.app.Activity;
-import android.app.Instrumentation;
-import android.content.Intent;
-import android.os.Environment;
-import android.provider.MediaStore;
-import android.test.InstrumentationTestCase;
-import android.test.suitebuilder.annotation.LargeTest;
-import android.util.Log;
-
-import java.io.FileWriter;
-import java.io.BufferedWriter;
-
-/**
- * Test cases to measure the camera and video recorder startup time.
- */
-public class CameraStartUp extends InstrumentationTestCase {
-
-    private static final int TOTAL_NUMBER_OF_STARTUP = 20;
-
-    private String TAG = "CameraStartUp";
-    private static final String CAMERA_TEST_OUTPUT_FILE =
-            Environment.getExternalStorageDirectory().toString() + "/mediaStressOut.txt";
-    private static int WAIT_TIME_FOR_PREVIEW = 1500; //1.5 second
-
-    private long launchCamera() {
-        long startupTime = 0;
-        try {
-            Intent intent = new Intent(Intent.ACTION_MAIN);
-            intent.setClass(getInstrumentation().getTargetContext(), CameraActivity.class);
-            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
-            long beforeStart = System.currentTimeMillis();
-            Instrumentation inst = getInstrumentation();
-            Activity cameraActivity = inst.startActivitySync(intent);
-            long cameraStarted = System.currentTimeMillis();
-            Thread.sleep(WAIT_TIME_FOR_PREVIEW);
-            cameraActivity.finish();
-            startupTime = cameraStarted - beforeStart;
-            Thread.sleep(1000);
-            Log.v(TAG, "camera startup time: " + startupTime);
-        } catch (Exception e) {
-            Log.v(TAG, "Got exception", e);
-            fail("Fails to get the output file");
-        }
-        return startupTime;
-    }
-
-    private long launchVideo() {
-        long startupTime = 0;
-
-        try {
-            Intent intent = new Intent(MediaStore.INTENT_ACTION_VIDEO_CAMERA);
-            intent.setClass(getInstrumentation().getTargetContext(), CameraActivity.class);
-            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
-            long beforeStart = System.currentTimeMillis();
-            Instrumentation inst = getInstrumentation();
-            Activity recorderActivity = inst.startActivitySync(intent);
-            long cameraStarted = System.currentTimeMillis();
-            recorderActivity.finish();
-            startupTime = cameraStarted - beforeStart;
-            Log.v(TAG, "Video Startup Time = " + startupTime);
-            // wait for 1s to make sure it reach a clean stage
-            Thread.sleep(WAIT_TIME_FOR_PREVIEW);
-            Log.v(TAG, "video startup time: " + startupTime);
-        } catch (Exception e) {
-            Log.v(TAG, "Got exception", e);
-            fail("Fails to launch video output file");
-        }
-        return startupTime;
-    }
-
-    private void writeToOutputFile(long totalStartupTime,
-            String individualStartupTime, boolean firstStartUp, String Type) throws Exception {
-        // TODO (yslau) : Need to integrate the output data with central
-        // dashboard
-        try {
-            FileWriter fstream = null;
-            fstream = new FileWriter(CAMERA_TEST_OUTPUT_FILE, true);
-            BufferedWriter out = new BufferedWriter(fstream);
-            if (firstStartUp) {
-                out.write("First " + Type + " Startup: " + totalStartupTime + "\n");
-            } else {
-                long averageStartupTime = totalStartupTime / (TOTAL_NUMBER_OF_STARTUP -1);
-                out.write(Type + "startup time: " + "\n");
-                out.write("Number of loop: " + (TOTAL_NUMBER_OF_STARTUP -1)  + "\n");
-                out.write(individualStartupTime + "\n\n");
-                out.write(Type + " average startup time: " + averageStartupTime + " ms\n\n");
-            }
-            out.close();
-            fstream.close();
-        } catch (Exception e) {
-            fail("Camera write output to file");
-        }
-    }
-
-    public void testLaunchVideo() throws Exception {
-        String individualStartupTime;
-        individualStartupTime = "Individual Video Startup Time = ";
-        long totalStartupTime = 0;
-        long startupTime = 0;
-        for (int i = 0; i < TOTAL_NUMBER_OF_STARTUP; i++) {
-            if (i == 0) {
-                // Capture the first startup time individually
-                long firstStartUpTime = launchVideo();
-                writeToOutputFile(firstStartUpTime, "na", true, "Video");
-            } else {
-                startupTime = launchVideo();
-                totalStartupTime += startupTime;
-                individualStartupTime += startupTime + " ,";
-            }
-        }
-        Log.v(TAG, "totalStartupTime =" + totalStartupTime);
-        writeToOutputFile(totalStartupTime, individualStartupTime, false, "Video");
-    }
-
-    public void testLaunchCamera() throws Exception {
-        String individualStartupTime;
-        individualStartupTime = "Individual Camera Startup Time = ";
-        long totalStartupTime = 0;
-        long startupTime = 0;
-        for (int i = 0; i < TOTAL_NUMBER_OF_STARTUP; i++) {
-            if (i == 0) {
-                // Capture the first startup time individually
-                long firstStartUpTime = launchCamera();
-                writeToOutputFile(firstStartUpTime, "na", true, "Camera");
-            } else {
-                startupTime = launchCamera();
-                totalStartupTime += startupTime;
-                individualStartupTime += startupTime + " ,";
-            }
-        }
-        Log.v(TAG, "totalStartupTime =" + totalStartupTime);
-        writeToOutputFile(totalStartupTime,
-                individualStartupTime, false, "Camera");
-    }
-}
diff --git a/tests/src/com/android/gallery3d/stress/CameraStressTestRunner.java b/tests/src/com/android/gallery3d/stress/CameraStressTestRunner.java
deleted file mode 100755
index d3fb10d..0000000
--- a/tests/src/com/android/gallery3d/stress/CameraStressTestRunner.java
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Copyright (C) 2010 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.gallery3d.stress;
-
-import android.os.Bundle;
-import android.test.InstrumentationTestRunner;
-import android.test.InstrumentationTestSuite;
-import junit.framework.TestSuite;
-
-public class CameraStressTestRunner extends InstrumentationTestRunner {
-
-    // Default recorder settings
-    public static int mVideoDuration = 20000; // set default to 20 seconds
-    public static int mVideoIterations = 1; // set default to 1 video
-    public static int mImageIterations = 10; // set default to 10 images
-
-    @Override
-    public TestSuite getAllTests() {
-        TestSuite suite = new InstrumentationTestSuite(this);
-        suite.addTestSuite(ImageCapture.class);
-        suite.addTestSuite(VideoCapture.class);
-        return suite;
-    }
-
-    @Override
-    public ClassLoader getLoader() {
-        return CameraStressTestRunner.class.getClassLoader();
-    }
-
-    @Override
-    public void onCreate(Bundle icicle) {
-        super.onCreate(icicle);
-        String video_iterations = (String) icicle.get("video_iterations");
-        String image_iterations = (String) icicle.get("image_iterations");
-        String video_duration = (String) icicle.get("video_duration");
-
-        if ( video_iterations != null ) {
-            mVideoIterations = Integer.parseInt(video_iterations);
-        }
-        if ( image_iterations != null) {
-            mImageIterations = Integer.parseInt(image_iterations);
-        }
-        if ( video_duration != null) {
-            mVideoDuration = Integer.parseInt(video_duration);
-        }
-    }
-}
diff --git a/tests/src/com/android/gallery3d/stress/ImageCapture.java b/tests/src/com/android/gallery3d/stress/ImageCapture.java
deleted file mode 100755
index 5a9ee6a..0000000
--- a/tests/src/com/android/gallery3d/stress/ImageCapture.java
+++ /dev/null
@@ -1,119 +0,0 @@
-/*
- * Copyright (C) 2009 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.gallery3d.stress;
-
-import com.android.camera.CameraActivity;
-import com.android.gallery3d.stress.CameraStressTestRunner;
-
-import android.app.Instrumentation;
-import android.content.Intent;
-import android.test.ActivityInstrumentationTestCase2;
-import android.test.suitebuilder.annotation.LargeTest;
-import android.util.Log;
-import android.view.KeyEvent;
-import android.app.Activity;
-
-/**
- * Junit / Instrumentation test case for camera test
- *
- * Running the test suite:
- *
- * adb shell am instrument \
- *    -e class com.android.camera.stress.ImageCapture \
- *    -w com.google.android.camera.tests/android.test.InstrumentationTestRunner
- *
- */
-
-public class ImageCapture extends ActivityInstrumentationTestCase2 <CameraActivity> {
-    private String TAG = "ImageCapture";
-    private static final long WAIT_FOR_IMAGE_CAPTURE_TO_BE_TAKEN = 1500;   //1.5 sedconds
-    private static final long WAIT_FOR_SWITCH_CAMERA = 3000; //3 seconds
-
-    private TestUtil testUtil = new TestUtil();
-
-    // Private intent extras.
-    private final static String EXTRAS_CAMERA_FACING =
-        "android.intent.extras.CAMERA_FACING";
-
-    public ImageCapture() {
-        super(CameraActivity.class);
-    }
-
-    @Override
-    protected void setUp() throws Exception {
-        testUtil.prepareOutputFile();
-        super.setUp();
-    }
-
-    @Override
-    protected void tearDown() throws Exception {
-        testUtil.closeOutputFile();
-        super.tearDown();
-    }
-
-    public void captureImages(String reportTag, Instrumentation inst) {
-        int total_num_of_images = CameraStressTestRunner.mImageIterations;
-        Log.v(TAG, "no of images = " + total_num_of_images);
-
-        //TODO(yslau): Need to integrate the outoput with the central dashboard,
-        //write to a txt file as a temp solution
-        boolean memoryResult = false;
-        KeyEvent focusEvent = new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_FOCUS);
-
-        try {
-            testUtil.writeReportHeader(reportTag, total_num_of_images);
-            for (int i = 0; i < total_num_of_images; i++) {
-                Thread.sleep(WAIT_FOR_IMAGE_CAPTURE_TO_BE_TAKEN);
-                inst.sendKeySync(focusEvent);
-                inst.sendCharacterSync(KeyEvent.KEYCODE_CAMERA);
-                Thread.sleep(WAIT_FOR_IMAGE_CAPTURE_TO_BE_TAKEN);
-                testUtil.writeResult(i);
-            }
-        } catch (Exception e) {
-            Log.v(TAG, "Got exception: " + e.toString());
-            assertTrue("testImageCapture", false);
-        }
-    }
-
-    public void testBackImageCapture() throws Exception {
-        Instrumentation inst = getInstrumentation();
-        Intent intent = new Intent();
-
-        intent.setClass(getInstrumentation().getTargetContext(), CameraActivity.class);
-        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
-        intent.putExtra(EXTRAS_CAMERA_FACING,
-                android.hardware.Camera.CameraInfo.CAMERA_FACING_BACK);
-        Activity act = inst.startActivitySync(intent);
-        Thread.sleep(WAIT_FOR_SWITCH_CAMERA);
-        captureImages("Back Camera Image Capture\n", inst);
-        act.finish();
-    }
-
-    public void testFrontImageCapture() throws Exception {
-        Instrumentation inst = getInstrumentation();
-        Intent intent = new Intent();
-
-        intent.setClass(getInstrumentation().getTargetContext(), CameraActivity.class);
-        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
-        intent.putExtra(EXTRAS_CAMERA_FACING,
-                android.hardware.Camera.CameraInfo.CAMERA_FACING_FRONT);
-        Activity act = inst.startActivitySync(intent);
-        Thread.sleep(WAIT_FOR_SWITCH_CAMERA);
-        captureImages("Front Camera Image Capture\n", inst);
-        act.finish();
-    }
-}
diff --git a/tests/src/com/android/gallery3d/stress/ShotToShotLatency.java b/tests/src/com/android/gallery3d/stress/ShotToShotLatency.java
deleted file mode 100644
index 0d5749e..0000000
--- a/tests/src/com/android/gallery3d/stress/ShotToShotLatency.java
+++ /dev/null
@@ -1,142 +0,0 @@
-/*
- * 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.gallery3d.stress;
-
-import android.app.Instrumentation;
-import android.os.Environment;
-import android.test.ActivityInstrumentationTestCase2;
-import android.test.suitebuilder.annotation.LargeTest;
-import android.util.Log;
-import android.view.KeyEvent;
-import com.android.camera.CameraActivity;
-import java.io.BufferedWriter;
-import java.io.File;
-import java.io.FilenameFilter;
-import java.io.FileWriter;
-import java.io.IOException;
-import java.util.ArrayList;
-
-/**
- * Junit / Instrumentation test case for measuring camera shot to shot latency
- */
-public class ShotToShotLatency extends ActivityInstrumentationTestCase2<CameraActivity> {
-    private String TAG = "ShotToShotLatency";
-    private static final int TOTAL_NUMBER_OF_SNAPSHOTS = 250;
-    private static final long SNAPSHOT_WAIT = 1000;
-    private static final String CAMERA_TEST_OUTPUT_FILE =
-            Environment.getExternalStorageDirectory().toString() + "/mediaStressOut.txt";
-    private static final String CAMERA_IMAGE_DIRECTORY =
-            Environment.getExternalStorageDirectory().toString() + "/DCIM/Camera/";
-
-    public ShotToShotLatency() {
-        super(CameraActivity.class);
-    }
-
-    @Override
-    protected void setUp() throws Exception {
-        getActivity();
-        super.setUp();
-    }
-
-    @Override
-    protected void tearDown() throws Exception {
-        super.tearDown();
-    }
-
-    private void cleanupLatencyImages() {
-        try {
-            File sdcard = new File(CAMERA_IMAGE_DIRECTORY);
-            File[] pics = null;
-            FilenameFilter filter = new FilenameFilter() {
-                public boolean accept(File dir, String name) {
-                    return name.endsWith(".jpg");
-                }
-            };
-            pics = sdcard.listFiles(filter);
-            for (File f : pics) {
-                f.delete();
-            }
-        } catch (SecurityException e) {
-            Log.e(TAG, "Security manager access violation: " + e.toString());
-        }
-    }
-
-    private void sleep(long time) {
-        try {
-            Thread.sleep(time);
-        } catch (InterruptedException e) {
-            Log.e(TAG, "Sleep InterruptedException " + e.toString());
-        }
-    }
-
-    public void testShotToShotLatency() {
-        long sigmaOfDiffFromMeanSquared = 0;
-        double mean = 0;
-        double standardDeviation = 0;
-        ArrayList<Long> captureTimes = new ArrayList<Long>();
-        ArrayList<Long> latencyTimes = new ArrayList<Long>();
-
-        Log.v(TAG, "start testShotToShotLatency test");
-        Instrumentation inst = getInstrumentation();
-
-        // Generate data points
-        for (int i = 0; i < TOTAL_NUMBER_OF_SNAPSHOTS; i++) {
-            inst.sendKeyDownUpSync(KeyEvent.KEYCODE_DPAD_CENTER);
-            sleep(SNAPSHOT_WAIT);
-            CameraActivity c = getActivity();
-            if (c.getCaptureStartTime() > 0) {
-                captureTimes.add(c.getCaptureStartTime());
-            }
-        }
-
-        // Calculate latencies
-        for (int j = 1; j < captureTimes.size(); j++) {
-            latencyTimes.add(captureTimes.get(j) - captureTimes.get(j - 1));
-        }
-
-        // Crunch numbers
-        for (long dataPoint : latencyTimes) {
-            mean += (double) dataPoint;
-        }
-        mean /= latencyTimes.size();
-
-        for (long dataPoint : latencyTimes) {
-            sigmaOfDiffFromMeanSquared += (dataPoint - mean) * (dataPoint - mean);
-        }
-        standardDeviation = Math.sqrt(sigmaOfDiffFromMeanSquared / latencyTimes.size());
-
-        // Report statistics
-        File outFile = new File(CAMERA_TEST_OUTPUT_FILE);
-        BufferedWriter output = null;
-        try {
-            output = new BufferedWriter(new FileWriter(outFile, true));
-            output.write("Shot to shot latency - mean: " + mean + "\n");
-            output.write("Shot to shot latency - standard deviation: " + standardDeviation + "\n");
-            cleanupLatencyImages();
-        } catch (IOException e) {
-            Log.e(TAG, "testShotToShotLatency IOException writing to log " + e.toString());
-        } finally {
-            try {
-                if (output != null) {
-                    output.close();
-                }
-            } catch (IOException e) {
-                Log.e(TAG, "Error closing file: " + e.toString());
-            }
-        }
-    }
-}
diff --git a/tests/src/com/android/gallery3d/stress/SwitchPreview.java b/tests/src/com/android/gallery3d/stress/SwitchPreview.java
deleted file mode 100755
index 3545f3b..0000000
--- a/tests/src/com/android/gallery3d/stress/SwitchPreview.java
+++ /dev/null
@@ -1,116 +0,0 @@
-/*
- * Copyright (C) 2009 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.gallery3d.stress;
-
-import com.android.camera.CameraActivity;
-
-import android.app.Instrumentation;
-import android.content.Intent;
-import android.provider.MediaStore;
-import android.test.ActivityInstrumentationTestCase2;
-import android.test.suitebuilder.annotation.LargeTest;
-import android.os.Environment;
-import android.util.Log;
-
-import java.io.BufferedWriter;
-import java.io.FileWriter;
-
-/**
- * Junit / Instrumentation test case for camera test
- *
- * Running the test suite:
- *
- * adb shell am instrument \
- *    -e class com.android.camera.stress.SwitchPreview \
- *    -w com.android.camera.tests/com.android.camera.stress.CameraStressTestRunner
- *
- */
-public class SwitchPreview extends ActivityInstrumentationTestCase2 <CameraActivity>{
-    private String TAG = "SwitchPreview";
-    private static final int TOTAL_NUMBER_OF_SWITCHING = 200;
-    private static final long WAIT_FOR_PREVIEW = 4000;
-
-    private static final String CAMERA_TEST_OUTPUT_FILE =
-            Environment.getExternalStorageDirectory().toString() + "/mediaStressOut.txt";
-    private BufferedWriter mOut;
-    private FileWriter mfstream;
-
-    public SwitchPreview() {
-        super(CameraActivity.class);
-    }
-
-    @Override
-    protected void setUp() throws Exception {
-        getActivity();
-        prepareOutputFile();
-        super.setUp();
-    }
-
-    @Override
-    protected void tearDown() throws Exception {
-        getActivity().finish();
-        closeOutputFile();
-        super.tearDown();
-    }
-
-    private void prepareOutputFile(){
-        try{
-            mfstream = new FileWriter(CAMERA_TEST_OUTPUT_FILE, true);
-            mOut = new BufferedWriter(mfstream);
-        } catch (Exception e){
-            assertTrue("Camera Switch Mode", false);
-        }
-    }
-
-    private void closeOutputFile() {
-        try {
-            mOut.write("\n");
-            mOut.close();
-            mfstream.close();
-        } catch (Exception e) {
-            assertTrue("CameraSwitchMode close output", false);
-        }
-    }
-
-    public void testSwitchMode() {
-        //Switching the video and the video recorder mode
-        Instrumentation inst = getInstrumentation();
-        try{
-            mOut.write("Camera Switch Mode:\n");
-            mOut.write("No of loops :" + TOTAL_NUMBER_OF_SWITCHING + "\n");
-            mOut.write("loop: ");
-            for (int i=0; i< TOTAL_NUMBER_OF_SWITCHING; i++) {
-                Thread.sleep(WAIT_FOR_PREVIEW);
-                Intent intent = new Intent(MediaStore.INTENT_ACTION_VIDEO_CAMERA);
-                intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
-                intent.setClass(getInstrumentation().getTargetContext(),
-                        CameraActivity.class);
-                getActivity().startActivity(intent);
-                Thread.sleep(WAIT_FOR_PREVIEW);
-                intent = new Intent();
-                intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
-                intent.setClass(getInstrumentation().getTargetContext(),
-                        CameraActivity.class);
-                getActivity().startActivity(intent);
-                mOut.write(" ," + i);
-                mOut.flush();
-            }
-        } catch (Exception e){
-            Log.v(TAG, "Got exception", e);
-        }
-    }
-}
diff --git a/tests/src/com/android/gallery3d/stress/TestUtil.java b/tests/src/com/android/gallery3d/stress/TestUtil.java
deleted file mode 100644
index 56ab715..0000000
--- a/tests/src/com/android/gallery3d/stress/TestUtil.java
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Copyright (C) 2011 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.gallery3d.stress;
-
-import android.os.Environment;
-import java.io.FileWriter;
-import java.io.BufferedWriter;
-
-
-/**
- * Collection of utility functions used for the test.
- */
-public class TestUtil {
-    public BufferedWriter mOut;
-    public FileWriter mfstream;
-
-    public TestUtil() {
-    }
-
-    public void prepareOutputFile() throws Exception {
-        String camera_test_output_file =
-                Environment.getExternalStorageDirectory().toString() + "/mediaStressOut.txt";
-        mfstream = new FileWriter(camera_test_output_file, true);
-        mOut = new BufferedWriter(mfstream);
-    }
-
-    public void closeOutputFile() throws Exception {
-        mOut.write("\n");
-        mOut.close();
-        mfstream.close();
-    }
-
-    public void writeReportHeader(String reportTag, int iteration) throws Exception {
-        mOut.write(reportTag);
-        mOut.write("No of loops :" + iteration + "\n");
-        mOut.write("loop: ");
-    }
-
-    public void writeResult(int iteration) throws Exception {
-        mOut.write(" ," + iteration);
-        mOut.flush();
-    }
-}
diff --git a/tests/src/com/android/gallery3d/stress/VideoCapture.java b/tests/src/com/android/gallery3d/stress/VideoCapture.java
deleted file mode 100755
index 8211bad..0000000
--- a/tests/src/com/android/gallery3d/stress/VideoCapture.java
+++ /dev/null
@@ -1,112 +0,0 @@
-/*
- * Copyright (C) 2010 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.gallery3d.stress;
-
-import com.android.camera.CameraActivity;
-import com.android.gallery3d.stress.TestUtil;
-
-import android.app.Activity;
-import android.app.Instrumentation;
-import android.content.Intent;
-import android.provider.MediaStore;
-import android.test.ActivityInstrumentationTestCase2;
-import android.test.suitebuilder.annotation.LargeTest;
-import android.view.KeyEvent;
-
-import com.android.gallery3d.stress.CameraStressTestRunner;
-
-/**
- * Junit / Instrumentation test case for camera test
- *
- * Running the test suite:
- *
- * adb shell am instrument \
- *    -e class com.android.camera.stress.VideoCapture \
- *    -w com.google.android.camera.tests/android.test.InstrumentationTestRunner
- *
- */
-
-public class VideoCapture extends ActivityInstrumentationTestCase2 <CameraActivity> {
-    private static final long WAIT_FOR_PREVIEW = 1500; //1.5 seconds
-    private static final long WAIT_FOR_SWITCH_CAMERA = 3000; //2 seconds
-
-    // Private intent extras which control the camera facing.
-    private final static String EXTRAS_CAMERA_FACING =
-        "android.intent.extras.CAMERA_FACING";
-
-    private TestUtil testUtil = new TestUtil();
-
-    public VideoCapture() {
-        super(CameraActivity.class);
-    }
-
-    @Override
-    protected void setUp() throws Exception {
-        testUtil.prepareOutputFile();
-        super.setUp();
-    }
-
-    @Override
-    protected void tearDown() throws Exception {
-        testUtil.closeOutputFile();
-        super.tearDown();
-    }
-
-    public void captureVideos(String reportTag, Instrumentation inst) throws Exception{
-        boolean memoryResult = false;
-        int total_num_of_videos = CameraStressTestRunner.mVideoIterations;
-        int video_duration = CameraStressTestRunner.mVideoDuration;
-        testUtil.writeReportHeader(reportTag, total_num_of_videos);
-
-        for (int i = 0; i < total_num_of_videos; i++) {
-            Thread.sleep(WAIT_FOR_PREVIEW);
-            // record a video
-            inst.sendCharacterSync(KeyEvent.KEYCODE_CAMERA);
-            Thread.sleep(video_duration);
-            inst.sendCharacterSync(KeyEvent.KEYCODE_CAMERA);
-            testUtil.writeResult(i);
-        }
-    }
-
-    public void testBackVideoCapture() throws Exception {
-        Instrumentation inst = getInstrumentation();
-        Intent intent = new Intent(MediaStore.INTENT_ACTION_VIDEO_CAMERA);
-
-        intent.setClass(getInstrumentation().getTargetContext(), CameraActivity.class);
-        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
-        intent.putExtra(EXTRAS_CAMERA_FACING,
-                android.hardware.Camera.CameraInfo.CAMERA_FACING_BACK);
-        Activity act = inst.startActivitySync(intent);
-        Thread.sleep(WAIT_FOR_SWITCH_CAMERA);
-        captureVideos("Back Camera Video Capture\n", inst);
-        act.finish();
-    }
-
-    public void testFrontVideoCapture() throws Exception {
-        Instrumentation inst = getInstrumentation();
-        Intent intent = new Intent(MediaStore.INTENT_ACTION_VIDEO_CAMERA);
-
-        intent.setClass(getInstrumentation().getTargetContext(), CameraActivity.class);
-        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
-        intent.putExtra(EXTRAS_CAMERA_FACING,
-                android.hardware.Camera.CameraInfo.CAMERA_FACING_FRONT);
-        Activity act = inst.startActivitySync(intent);
-        Thread.sleep(WAIT_FOR_SWITCH_CAMERA);
-        captureVideos("Front Camera Video Capture\n", inst);
-        act.finish();
-    }
-}
diff --git a/tests/src/com/android/gallery3d/ui/GLCanvasStub.java b/tests/src/com/android/gallery3d/ui/GLCanvasStub.java
deleted file mode 100644
index 01f0350..0000000
--- a/tests/src/com/android/gallery3d/ui/GLCanvasStub.java
+++ /dev/null
@@ -1,160 +0,0 @@
-/*
- * Copyright (C) 2010 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.gallery3d.ui;
-
-import android.graphics.Bitmap;
-import android.graphics.Rect;
-import android.graphics.RectF;
-
-import com.android.gallery3d.glrenderer.BasicTexture;
-import com.android.gallery3d.glrenderer.GLCanvas;
-import com.android.gallery3d.glrenderer.GLId;
-import com.android.gallery3d.glrenderer.GLPaint;
-import com.android.gallery3d.glrenderer.RawTexture;
-
-import java.nio.ByteBuffer;
-import java.nio.FloatBuffer;
-
-import javax.microedition.khronos.opengles.GL11;
-
-public class GLCanvasStub implements GLCanvas {
-    @Override
-    public void setSize(int width, int height) {}
-    @Override
-    public void clearBuffer() {}
-    @Override
-    public void clearBuffer(float[] argb) {}
-    public void setCurrentAnimationTimeMillis(long time) {}
-    public long currentAnimationTimeMillis() {
-        throw new UnsupportedOperationException();
-    }
-    @Override
-    public void setAlpha(float alpha) {}
-    @Override
-    public float getAlpha() {
-        throw new UnsupportedOperationException();
-    }
-    @Override
-    public void multiplyAlpha(float alpha) {}
-    @Override
-    public void translate(float x, float y, float z) {}
-    @Override
-    public void translate(float x, float y) {}
-    @Override
-    public void scale(float sx, float sy, float sz) {}
-    @Override
-    public void rotate(float angle, float x, float y, float z) {}
-    public boolean clipRect(int left, int top, int right, int bottom) {
-        throw new UnsupportedOperationException();
-    }
-    @Override
-    public void save() {
-        throw new UnsupportedOperationException();
-    }
-    @Override
-    public void save(int saveFlags) {
-        throw new UnsupportedOperationException();
-    }
-    public void setBlendEnabled(boolean enabled) {}
-    @Override
-    public void restore() {}
-    @Override
-    public void drawLine(float x1, float y1, float x2, float y2, GLPaint paint) {}
-    @Override
-    public void drawRect(float x1, float y1, float x2, float y2, GLPaint paint) {}
-    @Override
-    public void fillRect(float x, float y, float width, float height, int color) {}
-    @Override
-    public void drawTexture(
-            BasicTexture texture, int x, int y, int width, int height) {}
-    @Override
-    public void drawMesh(BasicTexture tex, int x, int y, int xyBuffer,
-            int uvBuffer, int indexBuffer, int indexCount) {}
-    public void drawTexture(BasicTexture texture,
-            int x, int y, int width, int height, float alpha) {}
-    @Override
-    public void drawTexture(BasicTexture texture, RectF source, RectF target) {}
-    @Override
-    public void drawTexture(BasicTexture texture, float[] mTextureTransform,
-            int x, int y, int w, int h) {}
-    public void drawMixed(BasicTexture from, BasicTexture to,
-            float ratio, int x, int y, int w, int h) {}
-    @Override
-    public void drawMixed(BasicTexture from, int to,
-            float ratio, int x, int y, int w, int h) {}
-    public void drawMixed(BasicTexture from, BasicTexture to,
-            float ratio, int x, int y, int width, int height, float alpha) {}
-    public BasicTexture copyTexture(int x, int y, int width, int height) {
-        throw new UnsupportedOperationException();
-    }
-    public GL11 getGLInstance() {
-        throw new UnsupportedOperationException();
-    }
-    @Override
-    public boolean unloadTexture(BasicTexture texture) {
-        throw new UnsupportedOperationException();
-    }
-    @Override
-    public void deleteBuffer(int bufferId) {
-        throw new UnsupportedOperationException();
-    }
-    @Override
-    public void deleteRecycledResources() {}
-    @Override
-    public void multiplyMatrix(float[] mMatrix, int offset) {}
-    @Override
-    public void dumpStatisticsAndClear() {}
-    @Override
-    public void beginRenderTarget(RawTexture texture) {}
-    @Override
-    public void endRenderTarget() {}
-    @Override
-    public void drawMixed(BasicTexture from, int toColor,
-            float ratio, RectF src, RectF target) {}
-
-    @Override
-    public void setTextureParameters(BasicTexture texture) {
-    }
-    @Override
-    public void initializeTextureSize(BasicTexture texture, int format, int type) {
-    }
-    @Override
-    public void initializeTexture(BasicTexture texture, Bitmap bitmap) {
-    }
-    @Override
-    public void texSubImage2D(BasicTexture texture, int xOffset, int yOffset, Bitmap bitmap,
-            int format, int type) {
-    }
-    @Override
-    public int uploadBuffer(ByteBuffer buffer) {
-        return 0;
-    }
-    @Override
-    public int uploadBuffer(FloatBuffer buffer) {
-        return 0;
-    }
-    @Override
-    public void recoverFromLightCycle() {
-    }
-    @Override
-    public void getBounds(Rect bounds, int x, int y, int width, int height) {
-    }
-    @Override
-    public GLId getGLId() {
-        return null;
-    }
-}
diff --git a/tests/src/com/android/gallery3d/ui/GLRootMock.java b/tests/src/com/android/gallery3d/ui/GLRootMock.java
deleted file mode 100644
index da78e14..0000000
--- a/tests/src/com/android/gallery3d/ui/GLRootMock.java
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Copyright (C) 2010 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.gallery3d.ui;
-
-import android.content.Context;
-import android.graphics.Matrix;
-import com.android.gallery3d.anim.CanvasAnimation;
-
-public class GLRootMock implements GLRoot {
-    int mRequestRenderCalled;
-    int mRequestLayoutContentPaneCalled;
-
-    public void addOnGLIdleListener(OnGLIdleListener listener) {}
-    public void registerLaunchedAnimation(CanvasAnimation animation) {}
-    public void requestRenderForced() {
-        mRequestRenderCalled++;
-    }
-    public void requestRender() {
-        mRequestRenderCalled++;
-    }
-    public void requestLayoutContentPane() {
-        mRequestLayoutContentPaneCalled++;
-    }
-    public boolean hasStencil() { return true; }
-    public void lockRenderThread() {}
-    public void unlockRenderThread() {}
-    public void setContentPane(GLView content) {}
-    public void setOrientationSource(OrientationSource source) {}
-    public int getDisplayRotation() { return 0; }
-    public int getCompensation() { return 0; }
-    public Matrix getCompensationMatrix() { return null; }
-    public void freeze() {}
-    public void unfreeze() {}
-    public void setLightsOutMode(boolean enabled) {}
-    public Context getContext() { return null; }
-}
diff --git a/tests/src/com/android/gallery3d/ui/GLRootStub.java b/tests/src/com/android/gallery3d/ui/GLRootStub.java
deleted file mode 100644
index 25e7bca..0000000
--- a/tests/src/com/android/gallery3d/ui/GLRootStub.java
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright (C) 2010 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.gallery3d.ui;
-
-import android.content.Context;
-import android.graphics.Matrix;
-import com.android.gallery3d.anim.CanvasAnimation;
-
-public class GLRootStub implements GLRoot {
-    public void addOnGLIdleListener(OnGLIdleListener listener) {}
-    public void registerLaunchedAnimation(CanvasAnimation animation) {}
-    public void requestRenderForced() {}
-    public void requestRender() {}
-    public void requestLayoutContentPane() {}
-    public boolean hasStencil() { return true; }
-    public void lockRenderThread() {}
-    public void unlockRenderThread() {}
-    public void setContentPane(GLView content) {}
-    public void setOrientationSource(OrientationSource source) {}
-    public int getDisplayRotation() { return 0; }
-    public int getCompensation() { return 0; }
-    public Matrix getCompensationMatrix() { return null; }
-    public void freeze() {}
-    public void unfreeze() {}
-    public void setLightsOutMode(boolean enabled) {}
-    public Context getContext() { return null; }
-}
diff --git a/tests/src/com/android/gallery3d/ui/GLViewMock.java b/tests/src/com/android/gallery3d/ui/GLViewMock.java
deleted file mode 100644
index 9b7488f..0000000
--- a/tests/src/com/android/gallery3d/ui/GLViewMock.java
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * Copyright (C) 2010 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.gallery3d.ui;
-
-import com.android.gallery3d.glrenderer.GLCanvas;
-
-class GLViewMock extends GLView {
-    // onAttachToRoot
-    int mOnAttachCalled;
-    GLRoot mRoot;
-    // onDetachFromRoot
-    int mOnDetachCalled;
-    // onVisibilityChanged
-    int mOnVisibilityChangedCalled;
-    // onLayout
-    int mOnLayoutCalled;
-    boolean mOnLayoutChangeSize;
-    // renderBackground
-    int mRenderBackgroundCalled;
-    // onMeasure
-    int mOnMeasureCalled;
-    int mOnMeasureWidthSpec;
-    int mOnMeasureHeightSpec;
-
-    @Override
-    public void onAttachToRoot(GLRoot root) {
-        mRoot = root;
-        mOnAttachCalled++;
-        super.onAttachToRoot(root);
-    }
-
-    @Override
-    public void onDetachFromRoot() {
-        mRoot = null;
-        mOnDetachCalled++;
-        super.onDetachFromRoot();
-    }
-
-    @Override
-    protected void onVisibilityChanged(int visibility) {
-        mOnVisibilityChangedCalled++;
-    }
-
-    @Override
-    protected void onLayout(boolean changeSize, int left, int top,
-            int right, int bottom) {
-        mOnLayoutCalled++;
-        mOnLayoutChangeSize = changeSize;
-        // call children's layout.
-        for (int i = 0, n = getComponentCount(); i < n; ++i) {
-            GLView item = getComponent(i);
-            item.layout(left, top, right, bottom);
-        }
-    }
-
-    @Override
-    protected void onMeasure(int widthSpec, int heightSpec) {
-        mOnMeasureCalled++;
-        mOnMeasureWidthSpec = widthSpec;
-        mOnMeasureHeightSpec = heightSpec;
-        // call children's measure.
-        for (int i = 0, n = getComponentCount(); i < n; ++i) {
-            GLView item = getComponent(i);
-            item.measure(widthSpec, heightSpec);
-        }
-        setMeasuredSize(widthSpec, heightSpec);
-    }
-
-    @Override
-    protected void renderBackground(GLCanvas view) {
-        mRenderBackgroundCalled++;
-    }
-}
diff --git a/tests/src/com/android/gallery3d/ui/GLViewTest.java b/tests/src/com/android/gallery3d/ui/GLViewTest.java
deleted file mode 100644
index b17b254..0000000
--- a/tests/src/com/android/gallery3d/ui/GLViewTest.java
+++ /dev/null
@@ -1,398 +0,0 @@
-/*
- * Copyright (C) 2010 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.gallery3d.ui;
-
-import android.graphics.Rect;
-import android.test.suitebuilder.annotation.SmallTest;
-import android.view.MotionEvent;
-
-import junit.framework.TestCase;
-
-@SmallTest
-public class GLViewTest extends TestCase {
-    @SuppressWarnings("unused")
-    private static final String TAG = "GLViewTest";
-
-    @SmallTest
-    public void testVisibility() {
-        GLViewMock a = new GLViewMock();
-        assertEquals(GLView.VISIBLE, a.getVisibility());
-        assertEquals(0, a.mOnVisibilityChangedCalled);
-        a.setVisibility(GLView.INVISIBLE);
-        assertEquals(GLView.INVISIBLE, a.getVisibility());
-        assertEquals(1, a.mOnVisibilityChangedCalled);
-        a.setVisibility(GLView.VISIBLE);
-        assertEquals(GLView.VISIBLE, a.getVisibility());
-        assertEquals(2, a.mOnVisibilityChangedCalled);
-    }
-
-    @SmallTest
-    public void testComponents() {
-        GLView view = new GLView();
-        assertEquals(0, view.getComponentCount());
-        try {
-            view.getComponent(0);
-            fail();
-        } catch (IndexOutOfBoundsException ex) {
-            // expected
-        }
-
-        GLView x = new GLView();
-        GLView y = new GLView();
-        view.addComponent(x);
-        view.addComponent(y);
-        assertEquals(2, view.getComponentCount());
-        assertSame(x, view.getComponent(0));
-        assertSame(y, view.getComponent(1));
-        view.removeComponent(x);
-        assertSame(y, view.getComponent(0));
-        try {
-            view.getComponent(1);
-            fail();
-        } catch (IndexOutOfBoundsException ex) {
-            // expected
-        }
-        try {
-            view.addComponent(y);
-            fail();
-        } catch (IllegalStateException ex) {
-            // expected
-        }
-        view.addComponent(x);
-        view.removeAllComponents();
-        assertEquals(0, view.getComponentCount());
-    }
-
-    @SmallTest
-    public void testBounds() {
-        GLView view = new GLView();
-
-        assertEquals(0, view.getWidth());
-        assertEquals(0, view.getHeight());
-
-        Rect b = view.bounds();
-        assertEquals(0, b.left);
-        assertEquals(0, b.top);
-        assertEquals(0, b.right);
-        assertEquals(0, b.bottom);
-
-        view.layout(10, 20, 30, 100);
-        assertEquals(20, view.getWidth());
-        assertEquals(80, view.getHeight());
-
-        b = view.bounds();
-        assertEquals(10, b.left);
-        assertEquals(20, b.top);
-        assertEquals(30, b.right);
-        assertEquals(100, b.bottom);
-    }
-
-    @SmallTest
-    public void testParent() {
-        GLView a = new GLView();
-        GLView b = new GLView();
-        assertNull(b.mParent);
-        a.addComponent(b);
-        assertSame(a, b.mParent);
-        a.removeComponent(b);
-        assertNull(b.mParent);
-    }
-
-    @SmallTest
-    public void testRoot() {
-        GLViewMock a = new GLViewMock();
-        GLViewMock b = new GLViewMock();
-        GLRoot r = new GLRootStub();
-        GLRoot r2 = new GLRootStub();
-        a.addComponent(b);
-
-        // Attach to root r
-        assertEquals(0, a.mOnAttachCalled);
-        assertEquals(0, b.mOnAttachCalled);
-        a.attachToRoot(r);
-        assertEquals(1, a.mOnAttachCalled);
-        assertEquals(1, b.mOnAttachCalled);
-        assertSame(r, a.getGLRoot());
-        assertSame(r, b.getGLRoot());
-
-        // Detach from r
-        assertEquals(0, a.mOnDetachCalled);
-        assertEquals(0, b.mOnDetachCalled);
-        a.detachFromRoot();
-        assertEquals(1, a.mOnDetachCalled);
-        assertEquals(1, b.mOnDetachCalled);
-
-        // Attach to another root r2
-        assertEquals(1, a.mOnAttachCalled);
-        assertEquals(1, b.mOnAttachCalled);
-        a.attachToRoot(r2);
-        assertEquals(2, a.mOnAttachCalled);
-        assertEquals(2, b.mOnAttachCalled);
-        assertSame(r2, a.getGLRoot());
-        assertSame(r2, b.getGLRoot());
-
-        // Detach from r2
-        assertEquals(1, a.mOnDetachCalled);
-        assertEquals(1, b.mOnDetachCalled);
-        a.detachFromRoot();
-        assertEquals(2, a.mOnDetachCalled);
-        assertEquals(2, b.mOnDetachCalled);
-    }
-
-    @SmallTest
-    public void testRoot2() {
-        GLView a = new GLViewMock();
-        GLViewMock b = new GLViewMock();
-        GLRoot r = new GLRootStub();
-
-        a.attachToRoot(r);
-
-        assertEquals(0, b.mOnAttachCalled);
-        a.addComponent(b);
-        assertEquals(1, b.mOnAttachCalled);
-
-        assertEquals(0, b.mOnDetachCalled);
-        a.removeComponent(b);
-        assertEquals(1, b.mOnDetachCalled);
-    }
-
-    @SmallTest
-    public void testInvalidate() {
-        GLView a = new GLView();
-        GLRootMock r = new GLRootMock();
-        a.attachToRoot(r);
-        assertEquals(0, r.mRequestRenderCalled);
-        a.invalidate();
-        assertEquals(1, r.mRequestRenderCalled);
-    }
-
-    @SmallTest
-    public void testRequestLayout() {
-        GLView a = new GLView();
-        GLView b = new GLView();
-        GLRootMock r = new GLRootMock();
-        a.attachToRoot(r);
-        a.addComponent(b);
-        assertEquals(0, r.mRequestLayoutContentPaneCalled);
-        b.requestLayout();
-        assertEquals(1, r.mRequestLayoutContentPaneCalled);
-    }
-
-    @SmallTest
-    public void testLayout() {
-        GLViewMock a = new GLViewMock();
-        GLViewMock b = new GLViewMock();
-        GLViewMock c = new GLViewMock();
-        GLRootMock r = new GLRootMock();
-
-        a.attachToRoot(r);
-        a.addComponent(b);
-        a.addComponent(c);
-
-        assertEquals(0, a.mOnLayoutCalled);
-        a.layout(10, 20, 60, 100);
-        assertEquals(1, a.mOnLayoutCalled);
-        assertEquals(1, b.mOnLayoutCalled);
-        assertEquals(1, c.mOnLayoutCalled);
-        assertTrue(a.mOnLayoutChangeSize);
-        assertTrue(b.mOnLayoutChangeSize);
-        assertTrue(c.mOnLayoutChangeSize);
-
-        // same size should not trigger onLayout
-        a.layout(10, 20, 60, 100);
-        assertEquals(1, a.mOnLayoutCalled);
-
-        // unless someone requested it, but only those on the path
-        // to the requester.
-        assertEquals(0, r.mRequestLayoutContentPaneCalled);
-        b.requestLayout();
-        a.layout(10, 20, 60, 100);
-        assertEquals(1, r.mRequestLayoutContentPaneCalled);
-        assertEquals(2, a.mOnLayoutCalled);
-        assertEquals(2, b.mOnLayoutCalled);
-        assertEquals(1, c.mOnLayoutCalled);
-    }
-
-    @SmallTest
-    public void testRender() {
-        GLViewMock a = new GLViewMock();
-        GLViewMock b = new GLViewMock();
-
-        a.addComponent(b);
-        GLCanvasStub canvas = new GLCanvasStub();
-        assertEquals(0, a.mRenderBackgroundCalled);
-        assertEquals(0, b.mRenderBackgroundCalled);
-        a.render(canvas);
-        assertEquals(1, a.mRenderBackgroundCalled);
-        assertEquals(1, b.mRenderBackgroundCalled);
-    }
-
-    @SmallTest
-    public void testMeasure() {
-        GLViewMock a = new GLViewMock();
-        GLViewMock b = new GLViewMock();
-        GLViewMock c = new GLViewMock();
-        GLRootMock r = new GLRootMock();
-
-        a.addComponent(b);
-        a.addComponent(c);
-        a.attachToRoot(r);
-
-        assertEquals(0, a.mOnMeasureCalled);
-        a.measure(100, 200);
-        assertEquals(1, a.mOnMeasureCalled);
-        assertEquals(1, b.mOnMeasureCalled);
-        assertEquals(100, a.mOnMeasureWidthSpec);
-        assertEquals(200, a.mOnMeasureHeightSpec);
-        assertEquals(100, b.mOnMeasureWidthSpec);
-        assertEquals(200, b.mOnMeasureHeightSpec);
-        assertEquals(100, a.getMeasuredWidth());
-        assertEquals(200, b.getMeasuredHeight());
-
-        // same spec should not trigger onMeasure
-        a.measure(100, 200);
-        assertEquals(1, a.mOnMeasureCalled);
-
-        // unless someone requested it, but only those on the path
-        // to the requester.
-        b.requestLayout();
-        a.measure(100, 200);
-        assertEquals(2, a.mOnMeasureCalled);
-        assertEquals(2, b.mOnMeasureCalled);
-        assertEquals(1, c.mOnMeasureCalled);
-    }
-
-    class MyGLView extends GLView {
-        private int mWidth;
-        int mOnTouchCalled;
-        int mOnTouchX;
-        int mOnTouchY;
-        int mOnTouchAction;
-
-        public MyGLView(int width) {
-            mWidth = width;
-        }
-
-        @Override
-        protected void onLayout(boolean changeSize, int left, int top,
-                int right, int bottom) {
-            // layout children from left to right
-            // call children's layout.
-            int x = 0;
-            for (int i = 0, n = getComponentCount(); i < n; ++i) {
-                GLView item = getComponent(i);
-                item.measure(0, 0);
-                int w = item.getMeasuredWidth();
-                int h = item.getMeasuredHeight();
-                item.layout(x, 0, x + w, h);
-                x += w;
-            }
-        }
-
-        @Override
-        protected void onMeasure(int widthSpec, int heightSpec) {
-            setMeasuredSize(mWidth, 100);
-        }
-
-        @Override
-        protected boolean onTouch(MotionEvent event) {
-            mOnTouchCalled++;
-            mOnTouchX = (int) event.getX();
-            mOnTouchY = (int) event.getY();
-            mOnTouchAction = event.getAction();
-            return true;
-        }
-    }
-
-    private MotionEvent NewMotionEvent(int action, int x, int y) {
-        return MotionEvent.obtain(0, 0, action, x, y, 0);
-    }
-
-    @SmallTest
-    public void testTouchEvent() {
-        // We construct a tree with four nodes. Only the x coordinate is used:
-        // A = [0..............................300)
-        // B = [0......100)
-        // C =             [100......200)
-        // D =             [100..150)
-
-        MyGLView a = new MyGLView(300);
-        MyGLView b = new MyGLView(100);
-        MyGLView c = new MyGLView(100);
-        MyGLView d = new MyGLView(50);
-        GLRoot r = new GLRootStub();
-
-        a.addComponent(b);
-        a.addComponent(c);
-        c.addComponent(d);
-        a.attachToRoot(r);
-        a.layout(0, 0, 300, 100);
-
-        int DOWN = MotionEvent.ACTION_DOWN;
-        int UP = MotionEvent.ACTION_UP;
-        int MOVE = MotionEvent.ACTION_MOVE;
-        int CANCEL = MotionEvent.ACTION_CANCEL;
-
-        // simple case
-        assertEquals(0, a.mOnTouchCalled);
-        a.dispatchTouchEvent(NewMotionEvent(DOWN, 250, 0));
-        assertEquals(DOWN, a.mOnTouchAction);
-        a.dispatchTouchEvent(NewMotionEvent(UP, 250, 0));
-        assertEquals(UP, a.mOnTouchAction);
-        assertEquals(2, a.mOnTouchCalled);
-
-        // pass to a child, check the location is offseted.
-        assertEquals(0, c.mOnTouchCalled);
-        a.dispatchTouchEvent(NewMotionEvent(DOWN, 175, 0));
-        a.dispatchTouchEvent(NewMotionEvent(UP, 175, 0));
-        assertEquals(75, c.mOnTouchX);
-        assertEquals(0, c.mOnTouchY);
-        assertEquals(2, c.mOnTouchCalled);
-        assertEquals(2, a.mOnTouchCalled);
-
-        // motion target cancel event
-        assertEquals(0, d.mOnTouchCalled);
-        a.dispatchTouchEvent(NewMotionEvent(DOWN, 125, 0));
-        assertEquals(1, d.mOnTouchCalled);
-        a.dispatchTouchEvent(NewMotionEvent(MOVE, 250, 0));
-        assertEquals(2, d.mOnTouchCalled);
-        a.dispatchTouchEvent(NewMotionEvent(MOVE, 50, 0));
-        assertEquals(3, d.mOnTouchCalled);
-        a.dispatchTouchEvent(NewMotionEvent(DOWN, 175, 0));
-        assertEquals(4, d.mOnTouchCalled);
-        assertEquals(CANCEL, d.mOnTouchAction);
-        assertEquals(3, c.mOnTouchCalled);
-        assertEquals(DOWN, c.mOnTouchAction);
-        a.dispatchTouchEvent(NewMotionEvent(UP, 175, 0));
-
-        // motion target is removed
-        assertEquals(4, d.mOnTouchCalled);
-        a.dispatchTouchEvent(NewMotionEvent(DOWN, 125, 0));
-        assertEquals(5, d.mOnTouchCalled);
-        a.removeComponent(c);
-        assertEquals(6, d.mOnTouchCalled);
-        assertEquals(CANCEL, d.mOnTouchAction);
-
-        // invisible component should not get events
-        assertEquals(2, a.mOnTouchCalled);
-        assertEquals(0, b.mOnTouchCalled);
-        b.setVisibility(GLView.INVISIBLE);
-        a.dispatchTouchEvent(NewMotionEvent(DOWN, 50, 0));
-        assertEquals(3, a.mOnTouchCalled);
-        assertEquals(0, b.mOnTouchCalled);
-    }
-}
diff --git a/tests/src/com/android/gallery3d/ui/PointerInfo.java b/tests/src/com/android/gallery3d/ui/PointerInfo.java
deleted file mode 100644
index 6c78556..0000000
--- a/tests/src/com/android/gallery3d/ui/PointerInfo.java
+++ /dev/null
@@ -1,222 +0,0 @@
-/*
- * Copyright (C) 2010 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.gallery3d.ui;
-
-import java.nio.Buffer;
-import java.nio.ByteBuffer;
-import java.nio.ByteOrder;
-import java.nio.CharBuffer;
-import java.nio.DoubleBuffer;
-import java.nio.FloatBuffer;
-import java.nio.IntBuffer;
-import java.nio.LongBuffer;
-import java.nio.ShortBuffer;
-
-import javax.microedition.khronos.opengles.GL10;
-
-public class PointerInfo {
-
-    /**
-     * The number of coordinates per vertex. 1..4
-     */
-    public int mSize;
-
-    /**
-     * The type of each coordinate.
-     */
-    public int mType;
-
-    /**
-     * The byte offset between consecutive vertices. 0 means mSize *
-     * sizeof(mType)
-     */
-    public int mStride;
-    public Buffer mPointer;
-    public ByteBuffer mTempByteBuffer;
-
-    public PointerInfo(int size, int type, int stride, Buffer pointer) {
-        mSize = size;
-        mType = type;
-        mStride = stride;
-        mPointer = pointer;
-    }
-
-    private int getStride() {
-        return mStride > 0 ? mStride : sizeof(mType) * mSize;
-    }
-
-    public void bindByteBuffer() {
-        mTempByteBuffer = mPointer == null ? null : toByteBuffer(-1, mPointer);
-    }
-
-    public void unbindByteBuffer() {
-        mTempByteBuffer = null;
-    }
-
-    private static int sizeof(int type) {
-        switch (type) {
-        case GL10.GL_UNSIGNED_BYTE:
-            return 1;
-        case GL10.GL_BYTE:
-            return 1;
-        case GL10.GL_SHORT:
-            return 2;
-        case GL10.GL_FIXED:
-            return 4;
-        case GL10.GL_FLOAT:
-            return 4;
-        default:
-            return 0;
-        }
-    }
-
-    private static ByteBuffer toByteBuffer(int byteCount, Buffer input) {
-        ByteBuffer result = null;
-        boolean convertWholeBuffer = (byteCount < 0);
-        if (input instanceof ByteBuffer) {
-            ByteBuffer input2 = (ByteBuffer) input;
-            int position = input2.position();
-            if (convertWholeBuffer) {
-                byteCount = input2.limit() - position;
-            }
-            result = ByteBuffer.allocate(byteCount).order(input2.order());
-            for (int i = 0; i < byteCount; i++) {
-                result.put(input2.get());
-            }
-            input2.position(position);
-        } else if (input instanceof CharBuffer) {
-            CharBuffer input2 = (CharBuffer) input;
-            int position = input2.position();
-            if (convertWholeBuffer) {
-                byteCount = (input2.limit() - position) * 2;
-            }
-            result = ByteBuffer.allocate(byteCount).order(input2.order());
-            CharBuffer result2 = result.asCharBuffer();
-            for (int i = 0; i < byteCount / 2; i++) {
-                result2.put(input2.get());
-            }
-            input2.position(position);
-        } else if (input instanceof ShortBuffer) {
-            ShortBuffer input2 = (ShortBuffer) input;
-            int position = input2.position();
-            if (convertWholeBuffer) {
-                byteCount = (input2.limit() - position)* 2;
-            }
-            result = ByteBuffer.allocate(byteCount).order(input2.order());
-            ShortBuffer result2 = result.asShortBuffer();
-            for (int i = 0; i < byteCount / 2; i++) {
-                result2.put(input2.get());
-            }
-            input2.position(position);
-        } else if (input instanceof IntBuffer) {
-            IntBuffer input2 = (IntBuffer) input;
-            int position = input2.position();
-            if (convertWholeBuffer) {
-                byteCount = (input2.limit() - position) * 4;
-            }
-            result = ByteBuffer.allocate(byteCount).order(input2.order());
-            IntBuffer result2 = result.asIntBuffer();
-            for (int i = 0; i < byteCount / 4; i++) {
-                result2.put(input2.get());
-            }
-            input2.position(position);
-        } else if (input instanceof FloatBuffer) {
-            FloatBuffer input2 = (FloatBuffer) input;
-            int position = input2.position();
-            if (convertWholeBuffer) {
-                byteCount = (input2.limit() - position) * 4;
-            }
-            result = ByteBuffer.allocate(byteCount).order(input2.order());
-            FloatBuffer result2 = result.asFloatBuffer();
-            for (int i = 0; i < byteCount / 4; i++) {
-                result2.put(input2.get());
-            }
-            input2.position(position);
-        } else if (input instanceof DoubleBuffer) {
-            DoubleBuffer input2 = (DoubleBuffer) input;
-            int position = input2.position();
-            if (convertWholeBuffer) {
-                byteCount = (input2.limit() - position) * 8;
-            }
-            result = ByteBuffer.allocate(byteCount).order(input2.order());
-            DoubleBuffer result2 = result.asDoubleBuffer();
-            for (int i = 0; i < byteCount / 8; i++) {
-                result2.put(input2.get());
-            }
-            input2.position(position);
-        } else if (input instanceof LongBuffer) {
-            LongBuffer input2 = (LongBuffer) input;
-            int position = input2.position();
-            if (convertWholeBuffer) {
-                byteCount = (input2.limit() - position) * 8;
-            }
-            result = ByteBuffer.allocate(byteCount).order(input2.order());
-            LongBuffer result2 = result.asLongBuffer();
-            for (int i = 0; i < byteCount / 8; i++) {
-                result2.put(input2.get());
-            }
-            input2.position(position);
-        } else {
-            throw new RuntimeException("Unimplemented Buffer subclass.");
-        }
-        result.rewind();
-        // The OpenGL API will interpret the result in hardware byte order,
-        // so we better do that as well:
-        result.order(ByteOrder.nativeOrder());
-        return result;
-    }
-
-    public void getArrayElement(int index, double[] result) {
-        if (mTempByteBuffer == null) {
-            throw new IllegalArgumentException("undefined pointer");
-        }
-        if (mStride < 0) {
-            throw new IllegalArgumentException("invalid stride");
-        }
-
-        int stride = getStride();
-        ByteBuffer byteBuffer = mTempByteBuffer;
-        int size = mSize;
-        int type = mType;
-        int sizeofType = sizeof(type);
-        int byteOffset = stride * index;
-
-        for (int i = 0; i < size; i++) {
-            switch (type) {
-            case GL10.GL_BYTE:
-            case GL10.GL_UNSIGNED_BYTE:
-                result[i] = byteBuffer.get(byteOffset);
-                break;
-            case GL10.GL_SHORT:
-                ShortBuffer shortBuffer = byteBuffer.asShortBuffer();
-                result[i] = shortBuffer.get(byteOffset / 2);
-                break;
-            case GL10.GL_FIXED:
-                IntBuffer intBuffer = byteBuffer.asIntBuffer();
-                result[i] = intBuffer.get(byteOffset / 4);
-                break;
-            case GL10.GL_FLOAT:
-                FloatBuffer floatBuffer = byteBuffer.asFloatBuffer();
-                result[i] = floatBuffer.get(byteOffset / 4);
-                break;
-            default:
-                throw new UnsupportedOperationException("unknown type");
-            }
-            byteOffset += sizeofType;
-        }
-    }
-}
diff --git a/tests/src/com/android/gallery3d/unittest/CameraUnitTest.java b/tests/src/com/android/gallery3d/unittest/CameraUnitTest.java
deleted file mode 100644
index b8fb05f..0000000
--- a/tests/src/com/android/gallery3d/unittest/CameraUnitTest.java
+++ /dev/null
@@ -1,107 +0,0 @@
-/*
- * Copyright (C) 2010 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.gallery3d.unittest;
-
-import com.android.camera.Util;
-
-import android.graphics.Matrix;
-import android.test.suitebuilder.annotation.SmallTest;
-
-import junit.framework.TestCase;
-
-@SmallTest
-public class CameraUnitTest extends TestCase {
-    public void testRoundOrientation() {
-        int h = Util.ORIENTATION_HYSTERESIS;
-        assertEquals(0, Util.roundOrientation(0, 0));
-        assertEquals(0, Util.roundOrientation(359, 0));
-        assertEquals(0, Util.roundOrientation(0 + 44 + h, 0));
-        assertEquals(90, Util.roundOrientation(0 + 45 + h, 0));
-        assertEquals(0, Util.roundOrientation(360 - 44 - h, 0));
-        assertEquals(270, Util.roundOrientation(360 - 45 - h, 0));
-
-        assertEquals(90, Util.roundOrientation(90, 90));
-        assertEquals(90, Util.roundOrientation(90 + 44 + h, 90));
-        assertEquals(180, Util.roundOrientation(90 + 45 + h, 90));
-        assertEquals(90, Util.roundOrientation(90 - 44 - h, 90));
-        assertEquals(0, Util.roundOrientation(90 - 45 - h, 90));
-
-        assertEquals(180, Util.roundOrientation(180, 180));
-        assertEquals(180, Util.roundOrientation(180 + 44 + h, 180));
-        assertEquals(270, Util.roundOrientation(180 + 45 + h, 180));
-        assertEquals(180, Util.roundOrientation(180 - 44 - h, 180));
-        assertEquals(90, Util.roundOrientation(180 - 45 - h, 180));
-
-        assertEquals(270, Util.roundOrientation(270, 270));
-        assertEquals(270, Util.roundOrientation(270 + 44 + h, 270));
-        assertEquals(0, Util.roundOrientation(270 + 45 + h, 270));
-        assertEquals(270, Util.roundOrientation(270 - 44 - h, 270));
-        assertEquals(180, Util.roundOrientation(270 - 45 - h, 270));
-
-        assertEquals(90, Util.roundOrientation(90, 0));
-        assertEquals(180, Util.roundOrientation(180, 0));
-        assertEquals(270, Util.roundOrientation(270, 0));
-
-        assertEquals(0, Util.roundOrientation(0, 90));
-        assertEquals(180, Util.roundOrientation(180, 90));
-        assertEquals(270, Util.roundOrientation(270, 90));
-
-        assertEquals(0, Util.roundOrientation(0, 180));
-        assertEquals(90, Util.roundOrientation(90, 180));
-        assertEquals(270, Util.roundOrientation(270, 180));
-
-        assertEquals(0, Util.roundOrientation(0, 270));
-        assertEquals(90, Util.roundOrientation(90, 270));
-        assertEquals(180, Util.roundOrientation(180, 270));
-    }
-
-    public void testPrepareMatrix() {
-        Matrix matrix = new Matrix();
-        float[] points;
-        int[] expected;
-
-        Util.prepareMatrix(matrix, false, 0, 800, 480);
-        points = new float[] {-1000, -1000, 0, 0, 1000, 1000, 0, 1000, -750, 250};
-        expected = new int[] {0, 0, 400, 240, 800, 480, 400, 480, 100, 300};
-        matrix.mapPoints(points);
-        assertEquals(expected, points);
-
-        Util.prepareMatrix(matrix, false, 90, 800, 480);
-        points = new float[] {-1000, -1000,   0,   0, 1000, 1000, 0, 1000, -750, 250};
-        expected = new int[] {800, 0, 400, 240, 0, 480, 0, 240, 300, 60};
-        matrix.mapPoints(points);
-        assertEquals(expected, points);
-
-        Util.prepareMatrix(matrix, false, 180, 800, 480);
-        points = new float[] {-1000, -1000, 0, 0, 1000, 1000, 0, 1000, -750, 250};
-        expected = new int[] {800, 480, 400, 240, 0, 0, 400, 0, 700, 180};
-        matrix.mapPoints(points);
-        assertEquals(expected, points);
-
-        Util.prepareMatrix(matrix, true, 180, 800, 480);
-        points = new float[] {-1000, -1000, 0, 0, 1000, 1000, 0, 1000, -750, 250};
-        expected = new int[] {0, 480, 400, 240, 800, 0, 400, 0, 100, 180};
-        matrix.mapPoints(points);
-        assertEquals(expected, points);
-    }
-
-    private void assertEquals(int expected[], float[] actual) {
-        for (int i = 0; i < expected.length; i++) {
-            assertEquals("Array index " + i + " mismatch", expected[i], Math.round(actual[i]));
-        }
-    }
-}
diff --git a/tests/src/com/android/gallery3d/util/IntArrayTest.java b/tests/src/com/android/gallery3d/util/IntArrayTest.java
deleted file mode 100644
index 83e6050..0000000
--- a/tests/src/com/android/gallery3d/util/IntArrayTest.java
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * Copyright (C) 2010 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.gallery3d.util;
-
-import com.android.gallery3d.util.IntArray;
-
-import android.test.suitebuilder.annotation.SmallTest;
-import android.util.Log;
-
-import java.util.Arrays;
-import junit.framework.TestCase;
-
-@SmallTest
-public class IntArrayTest extends TestCase {
-    private static final String TAG = "IntArrayTest";
-
-    public void testIntArray() {
-        IntArray a = new IntArray();
-        assertEquals(0, a.size());
-        assertTrue(Arrays.equals(new int[] {}, a.toArray(null)));
-
-        a.add(0);
-        assertEquals(1, a.size());
-        assertTrue(Arrays.equals(new int[] {0}, a.toArray(null)));
-
-        a.add(1);
-        assertEquals(2, a.size());
-        assertTrue(Arrays.equals(new int[] {0, 1}, a.toArray(null)));
-
-        int[] buf = new int[2];
-        int[] result = a.toArray(buf);
-        assertSame(buf, result);
-
-        IntArray b = new IntArray();
-        for (int i = 0; i < 100; i++) {
-            b.add(i * i);
-        }
-
-        assertEquals(100, b.size());
-        result = b.toArray(buf);
-        assertEquals(100, result.length);
-        for (int i = 0; i < 100; i++) {
-            assertEquals(i * i, result[i]);
-        }
-    }
-}
diff --git a/tests/src/com/android/gallery3d/util/ProfileTest.java b/tests/src/com/android/gallery3d/util/ProfileTest.java
deleted file mode 100644
index 798b905..0000000
--- a/tests/src/com/android/gallery3d/util/ProfileTest.java
+++ /dev/null
@@ -1,179 +0,0 @@
-/*
- * 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.gallery3d.util;
-
-import com.android.gallery3d.util.Profile;
-
-import android.os.Environment;
-import android.test.suitebuilder.annotation.SmallTest;
-import android.util.Log;
-
-import java.io.DataInputStream;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.HashMap;
-import junit.framework.Assert;
-import junit.framework.TestCase;
-
-@SmallTest
-public class ProfileTest extends TestCase {
-    private static final String TAG = "ProfileTest";
-    private static final String TEST_FILE =
-            Environment.getExternalStorageDirectory().getPath() + "/test.dat";
-
-
-    public void testProfile() throws IOException {
-        ProfileData p = new ProfileData();
-        ParsedProfile q;
-        String[] A = {"A"};
-        String[] B = {"B"};
-        String[] AC = {"A", "C"};
-        String[] AD = {"A", "D"};
-
-        // Empty profile
-        p.dumpToFile(TEST_FILE);
-        q = new ParsedProfile(TEST_FILE);
-        assertTrue(q.mEntries.isEmpty());
-        assertTrue(q.mSymbols.isEmpty());
-
-        // Only one sample
-        p.addSample(A);
-        p.dumpToFile(TEST_FILE);
-        q = new ParsedProfile(TEST_FILE);
-        assertEquals(1, q.mEntries.size());
-        assertEquals(1, q.mSymbols.size());
-        assertEquals(1, q.mEntries.get(0).sampleCount);
-
-        // Two samples at the same place
-        p.addSample(A);
-        p.dumpToFile(TEST_FILE);
-        q = new ParsedProfile(TEST_FILE);
-        assertEquals(1, q.mEntries.size());
-        assertEquals(1, q.mSymbols.size());
-        assertEquals(2, q.mEntries.get(0).sampleCount);
-
-        // Two samples at the different places
-        p.reset();
-        p.addSample(A);
-        p.addSample(B);
-        p.dumpToFile(TEST_FILE);
-        q = new ParsedProfile(TEST_FILE);
-        assertEquals(2, q.mEntries.size());
-        assertEquals(2, q.mSymbols.size());
-        assertEquals(1, q.mEntries.get(0).sampleCount);
-        assertEquals(1, q.mEntries.get(1).sampleCount);
-
-        // depth > 1
-        p.reset();
-        p.addSample(AC);
-        p.dumpToFile(TEST_FILE);
-        q = new ParsedProfile(TEST_FILE);
-        assertEquals(1, q.mEntries.size());
-        assertEquals(2, q.mSymbols.size());
-        assertEquals(1, q.mEntries.get(0).sampleCount);
-
-        // two samples (AC and AD)
-        p.addSample(AD);
-        p.dumpToFile(TEST_FILE);
-        q = new ParsedProfile(TEST_FILE);
-        assertEquals(2, q.mEntries.size());
-        assertEquals(3, q.mSymbols.size());  // three symbols: A, C, D
-        assertEquals(1, q.mEntries.get(0).sampleCount);
-        assertEquals(1, q.mEntries.get(0).sampleCount);
-
-        // Remove the test file
-        new File(TEST_FILE).delete();
-    }
-}
-
-class ParsedProfile {
-    public class Entry {
-        int sampleCount;
-        int stackId[];
-    }
-
-    ArrayList<Entry> mEntries = new ArrayList<Entry>();
-    HashMap<Integer, String> mSymbols = new HashMap<Integer, String>();
-    private DataInputStream mIn;
-    private byte[] mScratch = new byte[4];  // scratch buffer for readInt
-
-    public ParsedProfile(String filename) throws IOException {
-        mIn = new DataInputStream(new FileInputStream(filename));
-
-        Entry entry = parseOneEntry();
-        checkIsFirstEntry(entry);
-
-        while (true) {
-            entry = parseOneEntry();
-            if (entry.sampleCount == 0) {
-                checkIsLastEntry(entry);
-                break;
-            }
-            mEntries.add(entry);
-        }
-
-        // Read symbol table
-        while (true) {
-            String line = mIn.readLine();
-            if (line == null) break;
-            String[] fields = line.split(" +");
-            checkIsValidSymbolLine(fields);
-            mSymbols.put(Integer.decode(fields[0]), fields[1]);
-        }
-    }
-
-    private void checkIsFirstEntry(Entry entry) {
-        Assert.assertEquals(0, entry.sampleCount);
-        Assert.assertEquals(3, entry.stackId.length);
-        Assert.assertEquals(1, entry.stackId[0]);
-        Assert.assertTrue(entry.stackId[1] > 0);  // sampling period
-        Assert.assertEquals(0, entry.stackId[2]);  // padding
-    }
-
-    private void checkIsLastEntry(Entry entry) {
-        Assert.assertEquals(0, entry.sampleCount);
-        Assert.assertEquals(1, entry.stackId.length);
-        Assert.assertEquals(0, entry.stackId[0]);
-    }
-
-    private void checkIsValidSymbolLine(String[] fields) {
-        Assert.assertEquals(2, fields.length);
-        Assert.assertTrue(fields[0].startsWith("0x"));
-    }
-
-    private Entry parseOneEntry() throws IOException {
-        int sampleCount = readInt();
-        int depth = readInt();
-        Entry e = new Entry();
-        e.sampleCount = sampleCount;
-        e.stackId = new int[depth];
-        for (int i = 0; i < depth; i++) {
-            e.stackId[i] = readInt();
-        }
-        return e;
-    }
-
-    private int readInt() throws IOException {
-        mIn.read(mScratch, 0, 4);
-        return (mScratch[0] & 0xff) |
-                ((mScratch[1] & 0xff) << 8) |
-                ((mScratch[2] & 0xff) << 16) |
-                ((mScratch[3] & 0xff) << 24);
-    }
-}
diff --git a/tests/src/com/android/photos/data/DataTestRunner.java b/tests/src/com/android/photos/data/DataTestRunner.java
deleted file mode 100644
index 10618d6..0000000
--- a/tests/src/com/android/photos/data/DataTestRunner.java
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Copyright (C) 2013 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.photos.data;
-
-import android.test.InstrumentationTestRunner;
-import android.test.InstrumentationTestSuite;
-
-import com.android.photos.data.TestHelper.TestInitialization;
-
-import junit.framework.TestCase;
-import junit.framework.TestSuite;
-
-public class DataTestRunner extends InstrumentationTestRunner {
-    @Override
-    public TestSuite getAllTests() {
-        TestSuite suite = new InstrumentationTestSuite(this);
-        suite.addTestSuite(PhotoDatabaseTest.class);
-        suite.addTestSuite(PhotoProviderTest.class);
-        TestHelper.addTests(MediaCacheTest.class, suite, new TestInitialization() {
-            @Override
-            public void initialize(TestCase testCase) {
-                MediaCacheTest test = (MediaCacheTest) testCase;
-                test.setLocalContext(getContext());
-            }
-        });
-        return suite;
-    }
-
-    @Override
-    public ClassLoader getLoader() {
-        return DataTestRunner.class.getClassLoader();
-    }
-}
diff --git a/tests/src/com/android/photos/data/MediaCacheTest.java b/tests/src/com/android/photos/data/MediaCacheTest.java
deleted file mode 100644
index 9e71128..0000000
--- a/tests/src/com/android/photos/data/MediaCacheTest.java
+++ /dev/null
@@ -1,388 +0,0 @@
-/*
- * Copyright (C) 2013 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.photos.data;
-
-import android.content.Context;
-import android.content.res.Resources;
-import android.graphics.Bitmap;
-import android.graphics.BitmapFactory;
-import android.net.Uri;
-import android.os.Environment;
-import android.os.SystemClock;
-import android.test.ProviderTestCase2;
-
-import com.android.gallery3d.tests.R;
-import com.android.photos.data.MediaCache.ImageReady;
-import com.android.photos.data.MediaCache.OriginalReady;
-import com.android.photos.data.MediaRetriever.MediaSize;
-import com.android.photos.data.PhotoProvider.Photos;
-
-import java.io.File;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-
-public class MediaCacheTest extends ProviderTestCase2<PhotoProvider> {
-    @SuppressWarnings("unused")
-    private static final String TAG = MediaCacheTest.class.getSimpleName();
-
-    private File mDir;
-    private File mImage;
-    private File mCacheDir;
-    private Resources mResources;
-    private MediaCache mMediaCache;
-    private ReadyCollector mReady;
-
-    public static final long MAX_WAIT = 2000;
-
-    private static class ReadyCollector implements ImageReady, OriginalReady {
-        public File mOriginalFile;
-        public InputStream mInputStream;
-
-        @Override
-        public synchronized void originalReady(File originalFile) {
-            mOriginalFile = originalFile;
-            notifyAll();
-        }
-
-        @Override
-        public synchronized void imageReady(InputStream bitmapInputStream) {
-            mInputStream = bitmapInputStream;
-            notifyAll();
-        }
-
-        public synchronized boolean waitForNotification() {
-            long endWait = SystemClock.uptimeMillis() + MAX_WAIT;
-
-            try {
-                while (mInputStream == null && mOriginalFile == null
-                        && SystemClock.uptimeMillis() < endWait) {
-                    wait(endWait - SystemClock.uptimeMillis());
-                }
-            } catch (InterruptedException e) {
-            }
-            return mInputStream != null || mOriginalFile != null;
-        }
-    }
-
-    private static class DummyMediaRetriever implements MediaRetriever {
-        private boolean mNullUri = false;
-        @Override
-        public File getLocalFile(Uri contentUri) {
-            return null;
-        }
-
-        @Override
-        public MediaSize getFastImageSize(Uri contentUri, MediaSize size) {
-            return null;
-        }
-
-        @Override
-        public byte[] getTemporaryImage(Uri contentUri, MediaSize temporarySize) {
-            return null;
-        }
-
-        @Override
-        public boolean getMedia(Uri contentUri, MediaSize imageSize, File tempFile) {
-            return false;
-        }
-
-        @Override
-        public Uri normalizeUri(Uri contentUri, MediaSize size) {
-            if (mNullUri) {
-                return null;
-            } else {
-                return contentUri;
-            }
-        }
-
-        @Override
-        public MediaSize normalizeMediaSize(Uri contentUri, MediaSize size) {
-            return size;
-        }
-
-        public void setNullUri() {
-            mNullUri = true;
-        }
-    };
-
-    public MediaCacheTest() {
-        super(PhotoProvider.class, PhotoProvider.AUTHORITY);
-    }
-
-    @Override
-    public void setUp() throws Exception {
-        super.setUp();
-
-        mReady = new ReadyCollector();
-        File externalDir = Environment.getExternalStorageDirectory();
-        mDir = new File(externalDir, "test");
-        mDir.mkdirs();
-        mCacheDir = new File(externalDir, "test_cache");
-        mImage = new File(mDir, "original.jpg");
-        MediaCache.initialize(getMockContext());
-        MediaCache.getInstance().setCacheDir(mCacheDir);
-        mMediaCache = MediaCache.getInstance();
-        mMediaCache.addRetriever("file", "", new FileRetriever());
-    }
-
-    @Override
-    public void tearDown() throws Exception {
-        super.tearDown();
-        mMediaCache.clearCacheDir();
-        MediaCache.shutdown();
-        mMediaCache = null;
-        mImage.delete();
-        mDir.delete();
-        mCacheDir.delete();
-    }
-
-    public void setLocalContext(Context context) {
-        mResources = context.getResources();
-    }
-
-    public void testRetrieveOriginal() throws IOException {
-        copyResourceToFile(R.raw.galaxy_nexus, mImage.getPath());
-        Uri uri = Uri.fromFile(mImage);
-        mMediaCache.retrieveOriginal(uri, mReady, null);
-        assertTrue(mReady.waitForNotification());
-        assertNull(mReady.mInputStream);
-        assertEquals(mImage, mReady.mOriginalFile);
-    }
-
-    public void testRetrievePreview() throws IOException {
-        copyResourceToFile(R.raw.galaxy_nexus, mImage.getPath());
-        Uri uri = Uri.fromFile(mImage);
-        mMediaCache.retrievePreview(uri, mReady, null);
-        assertTrue(mReady.waitForNotification());
-        assertNotNull(mReady.mInputStream);
-        assertNull(mReady.mOriginalFile);
-        Bitmap bitmap = BitmapFactory.decodeStream(mReady.mInputStream);
-        mReady.mInputStream.close();
-        assertNotNull(bitmap);
-        Bitmap original = BitmapFactory.decodeFile(mImage.getPath());
-        assertTrue(bitmap.getWidth() < original.getWidth());
-        assertTrue(bitmap.getHeight() < original.getHeight());
-        int maxDimension = Math.max(bitmap.getWidth(), bitmap.getHeight());
-        int targetSize = MediaCacheUtils.getTargetSize(MediaSize.Preview);
-        assertTrue(maxDimension >= targetSize);
-        assertTrue(maxDimension < (targetSize * 2));
-    }
-
-    public void testRetrieveExifThumb() throws IOException {
-        copyResourceToFile(R.raw.galaxy_nexus, mImage.getPath());
-        Uri uri = Uri.fromFile(mImage);
-        ReadyCollector done = new ReadyCollector();
-        mMediaCache.retrieveThumbnail(uri, done, mReady);
-        assertTrue(mReady.waitForNotification());
-        assertNotNull(mReady.mInputStream);
-        assertNull(mReady.mOriginalFile);
-        Bitmap bitmap = BitmapFactory.decodeStream(mReady.mInputStream);
-        mReady.mInputStream.close();
-        assertTrue(done.waitForNotification());
-        assertNotNull(done.mInputStream);
-        done.mInputStream.close();
-        assertNotNull(bitmap);
-        assertEquals(320, bitmap.getWidth());
-        assertEquals(240, bitmap.getHeight());
-    }
-
-    public void testRetrieveThumb() throws IOException {
-        copyResourceToFile(R.raw.galaxy_nexus, mImage.getPath());
-        Uri uri = Uri.fromFile(mImage);
-        long downsampleStart = SystemClock.uptimeMillis();
-        mMediaCache.retrieveThumbnail(uri, mReady, null);
-        assertTrue(mReady.waitForNotification());
-        long downsampleEnd = SystemClock.uptimeMillis();
-        assertNotNull(mReady.mInputStream);
-        assertNull(mReady.mOriginalFile);
-        Bitmap bitmap = BitmapFactory.decodeStream(mReady.mInputStream);
-        mReady.mInputStream.close();
-        assertNotNull(bitmap);
-        Bitmap original = BitmapFactory.decodeFile(mImage.getPath());
-        assertTrue(bitmap.getWidth() < original.getWidth());
-        assertTrue(bitmap.getHeight() < original.getHeight());
-        int maxDimension = Math.max(bitmap.getWidth(), bitmap.getHeight());
-        int targetSize = MediaCacheUtils.getTargetSize(MediaSize.Thumbnail);
-        assertTrue(maxDimension >= targetSize);
-        assertTrue(maxDimension < (targetSize * 2));
-
-        // Retrieve cached thumb.
-        mReady = new ReadyCollector();
-        long start = SystemClock.uptimeMillis();
-        mMediaCache.retrieveThumbnail(uri, mReady, null);
-        assertTrue(mReady.waitForNotification());
-        mReady.mInputStream.close();
-        long end = SystemClock.uptimeMillis();
-        // Already cached. Wait shorter time.
-        assertTrue((end - start) < (downsampleEnd - downsampleStart) / 2);
-    }
-
-    public void testGetVideo() throws IOException {
-        mImage = new File(mDir, "original.mp4");
-        copyResourceToFile(R.raw.android_lawn, mImage.getPath());
-        Uri uri = Uri.fromFile(mImage);
-
-        mMediaCache.retrieveOriginal(uri, mReady, null);
-        assertTrue(mReady.waitForNotification());
-        assertNull(mReady.mInputStream);
-        assertNotNull(mReady.mOriginalFile);
-
-        mReady = new ReadyCollector();
-        mMediaCache.retrievePreview(uri, mReady, null);
-        assertTrue(mReady.waitForNotification());
-        assertNotNull(mReady.mInputStream);
-        assertNull(mReady.mOriginalFile);
-        Bitmap bitmap = BitmapFactory.decodeStream(mReady.mInputStream);
-        mReady.mInputStream.close();
-        int maxDimension = Math.max(bitmap.getWidth(), bitmap.getHeight());
-        int targetSize = MediaCacheUtils.getTargetSize(MediaSize.Preview);
-        assertTrue(maxDimension >= targetSize);
-        assertTrue(maxDimension < (targetSize * 2));
-
-        mReady = new ReadyCollector();
-        mMediaCache.retrieveThumbnail(uri, mReady, null);
-        assertTrue(mReady.waitForNotification());
-        assertNotNull(mReady.mInputStream);
-        assertNull(mReady.mOriginalFile);
-        bitmap = BitmapFactory.decodeStream(mReady.mInputStream);
-        mReady.mInputStream.close();
-        maxDimension = Math.max(bitmap.getWidth(), bitmap.getHeight());
-        targetSize = MediaCacheUtils.getTargetSize(MediaSize.Thumbnail);
-        assertTrue(maxDimension >= targetSize);
-        assertTrue(maxDimension < (targetSize * 2));
-    }
-
-    public void testFastImage() throws IOException {
-        copyResourceToFile(R.raw.galaxy_nexus, mImage.getPath());
-        Uri uri = Uri.fromFile(mImage);
-        mMediaCache.retrieveThumbnail(uri, mReady, null);
-        mReady.waitForNotification();
-        mReady.mInputStream.close();
-
-        mMediaCache.retrieveOriginal(uri, mReady, null);
-        assertTrue(mReady.waitForNotification());
-        assertNotNull(mReady.mInputStream);
-        mReady.mInputStream.close();
-    }
-
-    public void testBadRetriever() {
-        Uri uri = Photos.CONTENT_URI;
-        try {
-            mMediaCache.retrieveOriginal(uri, mReady, null);
-            fail("Expected exception");
-        } catch (IllegalArgumentException e) {
-            // expected
-        }
-    }
-
-    public void testInsertIntoCache() throws IOException {
-        // FileRetriever inserts into the cache opportunistically with Videos
-        mImage = new File(mDir, "original.mp4");
-        copyResourceToFile(R.raw.android_lawn, mImage.getPath());
-        Uri uri = Uri.fromFile(mImage);
-
-        mMediaCache.retrieveThumbnail(uri, mReady, null);
-        assertTrue(mReady.waitForNotification());
-        mReady.mInputStream.close();
-        assertNotNull(mMediaCache.getCachedFile(uri, MediaSize.Preview));
-    }
-
-    public void testBadNormalizedUri() {
-        DummyMediaRetriever retriever = new DummyMediaRetriever();
-        Uri uri = Uri.fromParts("http", "world", "morestuff");
-        mMediaCache.addRetriever(uri.getScheme(), uri.getAuthority(), retriever);
-        retriever.setNullUri();
-        try {
-            mMediaCache.retrieveOriginal(uri, mReady, null);
-            fail("Expected IllegalArgumentException");
-        } catch (IllegalArgumentException e) {
-            // expected
-        }
-    }
-
-    public void testClearOldCache() throws IOException {
-        copyResourceToFile(R.raw.galaxy_nexus, mImage.getPath());
-        Uri uri = Uri.fromFile(mImage);
-        mMediaCache.retrievePreview(uri, mReady, null);
-        assertTrue(mReady.waitForNotification());
-        mReady.mInputStream.close();
-        mMediaCache.setMaxCacheSize(mMediaCache.getCachedFile(uri, MediaSize.Preview).length());
-        assertNotNull(mMediaCache.getCachedFile(uri, MediaSize.Preview));
-
-        mReady = new ReadyCollector();
-        // This should kick the preview image out of the cache.
-        mMediaCache.retrieveThumbnail(uri, mReady, null);
-        assertTrue(mReady.waitForNotification());
-        mReady.mInputStream.close();
-        assertNull(mMediaCache.getCachedFile(uri, MediaSize.Preview));
-        assertNotNull(mMediaCache.getCachedFile(uri, MediaSize.Thumbnail));
-    }
-
-    public void testClearLargeInCache() throws IOException {
-        copyResourceToFile(R.raw.galaxy_nexus, mImage.getPath());
-        Uri imageUri = Uri.fromFile(mImage);
-        mMediaCache.retrieveThumbnail(imageUri, mReady, null);
-        assertTrue(mReady.waitForNotification());
-            mReady.mInputStream.close();
-        assertNotNull(mMediaCache.getCachedFile(imageUri, MediaSize.Thumbnail));
-        long thumbSize = mMediaCache.getCachedFile(imageUri, MediaSize.Thumbnail).length();
-        mMediaCache.setMaxCacheSize(thumbSize * 10);
-
-        for (int i = 0; i < 9; i++) {
-            File tempImage = new File(mDir, "image" + i + ".jpg");
-            mImage.renameTo(tempImage);
-            Uri tempImageUri = Uri.fromFile(tempImage);
-            mReady = new ReadyCollector();
-            mMediaCache.retrieveThumbnail(tempImageUri, mReady, null);
-            assertTrue(mReady.waitForNotification());
-                mReady.mInputStream.close();
-            tempImage.renameTo(mImage);
-        }
-        assertNotNull(mMediaCache.getCachedFile(imageUri, MediaSize.Thumbnail));
-
-        for (int i = 0; i < 9; i++) {
-            File tempImage = new File(mDir, "image" + i + ".jpg");
-            mImage.renameTo(tempImage);
-            Uri tempImageUri = Uri.fromFile(tempImage);
-            mReady = new ReadyCollector();
-            mMediaCache.retrievePreview(tempImageUri, mReady, null);
-            assertTrue(mReady.waitForNotification());
-                mReady.mInputStream.close();
-            tempImage.renameTo(mImage);
-        }
-        assertNotNull(mMediaCache.getCachedFile(imageUri, MediaSize.Thumbnail));
-        Uri oldestUri = Uri.fromFile(new File(mDir, "image0.jpg"));
-        assertNull(mMediaCache.getCachedFile(oldestUri, MediaSize.Thumbnail));
-    }
-
-    private void copyResourceToFile(int resourceId, String path) throws IOException {
-        File outputDir = new File(path).getParentFile();
-        outputDir.mkdirs();
-
-        InputStream in = mResources.openRawResource(resourceId);
-        FileOutputStream out = new FileOutputStream(path);
-        byte[] buffer = new byte[1000];
-        int bytesRead;
-
-        while ((bytesRead = in.read(buffer)) >= 0) {
-            out.write(buffer, 0, bytesRead);
-        }
-
-        in.close();
-        out.close();
-    }
-}
diff --git a/tests/src/com/android/photos/data/PhotoDatabaseTest.java b/tests/src/com/android/photos/data/PhotoDatabaseTest.java
deleted file mode 100644
index e7c1689..0000000
--- a/tests/src/com/android/photos/data/PhotoDatabaseTest.java
+++ /dev/null
@@ -1,229 +0,0 @@
-/*
- * Copyright (C) 2013 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.photos.data;
-
-import android.content.Context;
-import android.database.Cursor;
-import android.database.DatabaseUtils;
-import android.database.sqlite.SQLiteDatabase;
-import android.test.InstrumentationTestCase;
-
-import com.android.photos.data.PhotoProvider.Accounts;
-import com.android.photos.data.PhotoProvider.Albums;
-import com.android.photos.data.PhotoProvider.Metadata;
-import com.android.photos.data.PhotoProvider.Photos;
-
-import java.io.File;
-import java.io.IOException;
-
-public class PhotoDatabaseTest extends InstrumentationTestCase {
-
-    private PhotoDatabase mDBHelper;
-    private static final String DB_NAME = "dummy.db";
-    private static final long PARENT_ID1 = 100;
-    private static final long PARENT_ID2 = 101;
-
-    @Override
-    protected void setUp() throws Exception {
-        super.setUp();
-        Context context = getInstrumentation().getTargetContext();
-        context.deleteDatabase(DB_NAME);
-        mDBHelper = new PhotoDatabase(context, DB_NAME);
-    }
-
-    @Override
-    protected void tearDown() throws Exception {
-        mDBHelper.close();
-        mDBHelper = null;
-        Context context = getInstrumentation().getTargetContext();
-        context.deleteDatabase(DB_NAME);
-        super.tearDown();
-    }
-
-    public void testCreateDatabase() throws IOException {
-        Context context = getInstrumentation().getTargetContext();
-        File dbFile = context.getDatabasePath(DB_NAME);
-        SQLiteDatabase db = getReadableDB();
-        db.beginTransaction();
-        db.endTransaction();
-        assertTrue(dbFile.exists());
-    }
-
-    public void testTables() {
-        validateTable(Metadata.TABLE, PhotoDatabaseUtils.PROJECTION_METADATA);
-        validateTable(Albums.TABLE, PhotoDatabaseUtils.PROJECTION_ALBUMS);
-        validateTable(Photos.TABLE, PhotoDatabaseUtils.PROJECTION_PHOTOS);
-    }
-
-    public void testAlbumsConstraints() {
-        SQLiteDatabase db = getWritableDB();
-        db.beginTransaction();
-        try {
-            long accountId = 100;
-            // Test NOT NULL constraint on name
-            assertFalse(PhotoDatabaseUtils.insertAlbum(db, null, null, Albums.VISIBILITY_PRIVATE,
-                    accountId));
-
-            // test NOT NULL constraint on privacy
-            assertFalse(PhotoDatabaseUtils.insertAlbum(db, null, "hello", null, accountId));
-
-            // test NOT NULL constraint on account_id
-            assertFalse(PhotoDatabaseUtils.insertAlbum(db, null, "hello",
-                    Albums.VISIBILITY_PRIVATE, null));
-
-            // Normal insert
-            assertTrue(PhotoDatabaseUtils.insertAlbum(db, PARENT_ID1, "hello",
-                    Albums.VISIBILITY_PRIVATE, accountId));
-
-            long albumId = PhotoDatabaseUtils.queryAlbumIdFromParentId(db, PARENT_ID1);
-
-            // Assign a valid child
-            assertTrue(PhotoDatabaseUtils.insertAlbum(db, PARENT_ID2, "hello",
-                    Albums.VISIBILITY_PRIVATE, accountId));
-
-            long otherAlbumId = PhotoDatabaseUtils.queryAlbumIdFromParentId(db, PARENT_ID2);
-            assertNotSame(albumId, otherAlbumId);
-
-            // This is a valid child of another album.
-            assertTrue(PhotoDatabaseUtils.insertAlbum(db, otherAlbumId, "hello",
-                    Albums.VISIBILITY_PRIVATE, accountId));
-
-            // This isn't allowed due to uniqueness constraint (parent_id/name)
-            assertFalse(PhotoDatabaseUtils.insertAlbum(db, otherAlbumId, "hello",
-                    Albums.VISIBILITY_PRIVATE, accountId));
-        } finally {
-            db.endTransaction();
-        }
-    }
-
-    public void testPhotosConstraints() {
-        SQLiteDatabase db = getWritableDB();
-        db.beginTransaction();
-        try {
-            int width = 100;
-            int height = 100;
-            long dateTaken = System.currentTimeMillis();
-            String mimeType = "test/test";
-            long accountId = 100;
-
-            // Test NOT NULL mime-type
-            assertFalse(PhotoDatabaseUtils.insertPhoto(db, width, height, dateTaken, null, null,
-                    accountId));
-
-            // Test NOT NULL width
-            assertFalse(PhotoDatabaseUtils.insertPhoto(db, null, height, dateTaken, null, mimeType,
-                    accountId));
-
-            // Test NOT NULL height
-            assertFalse(PhotoDatabaseUtils.insertPhoto(db, width, null, dateTaken, null, mimeType,
-                    accountId));
-
-            // Test NOT NULL dateTaken
-            assertFalse(PhotoDatabaseUtils.insertPhoto(db, width, height, null, null, mimeType,
-                    accountId));
-
-            // Test NOT NULL accountId
-            assertFalse(PhotoDatabaseUtils.insertPhoto(db, width, height, dateTaken, null,
-                    mimeType, null));
-
-            // Test normal insert
-            assertTrue(PhotoDatabaseUtils.insertPhoto(db, width, height, dateTaken, null, mimeType,
-                    accountId));
-        } finally {
-            db.endTransaction();
-        }
-    }
-
-    public void testMetadataConstraints() {
-        SQLiteDatabase db = getWritableDB();
-        db.beginTransaction();
-        try {
-            final String mimeType = "test/test";
-            PhotoDatabaseUtils.insertPhoto(db, 100, 100, 100L, PARENT_ID1, mimeType, 100L);
-            long photoId = PhotoDatabaseUtils.queryPhotoIdFromAlbumId(db, PARENT_ID1);
-
-            // Test NOT NULL PHOTO_ID constraint.
-            assertFalse(PhotoDatabaseUtils.insertMetadata(db, null, "foo", "bar"));
-
-            // Normal insert.
-            assertTrue(PhotoDatabaseUtils.insertMetadata(db, photoId, "foo", "bar"));
-
-            // Test uniqueness constraint.
-            assertFalse(PhotoDatabaseUtils.insertMetadata(db, photoId, "foo", "baz"));
-        } finally {
-            db.endTransaction();
-        }
-    }
-
-    public void testAccountsConstraints() {
-        SQLiteDatabase db = getWritableDB();
-        db.beginTransaction();
-        try {
-            assertFalse(PhotoDatabaseUtils.insertAccount(db, null));
-            assertTrue(PhotoDatabaseUtils.insertAccount(db, "hello"));
-            assertTrue(PhotoDatabaseUtils.insertAccount(db, "hello"));
-        } finally {
-            db.endTransaction();
-        }
-    }
-
-    public void testUpgrade() {
-        SQLiteDatabase db = getWritableDB();
-        db.beginTransaction();
-        try {
-            assertTrue(PhotoDatabaseUtils.insertAccount(db, "Hello"));
-            assertTrue(PhotoDatabaseUtils.insertAlbum(db, PARENT_ID1, "hello",
-                    Albums.VISIBILITY_PRIVATE, 100L));
-            final String mimeType = "test/test";
-            assertTrue(PhotoDatabaseUtils.insertPhoto(db, 100, 100, 100L, PARENT_ID1, mimeType,
-                    100L));
-            // Normal insert.
-            assertTrue(PhotoDatabaseUtils.insertMetadata(db, 100L, "foo", "bar"));
-            db.setTransactionSuccessful();
-        } finally {
-            db.endTransaction();
-        }
-        mDBHelper.close();
-        Context context = getInstrumentation().getTargetContext();
-        mDBHelper = new PhotoDatabase(context, DB_NAME, PhotoDatabase.DB_VERSION + 1);
-        db = getReadableDB();
-        assertEquals(0, DatabaseUtils.queryNumEntries(db, Accounts.TABLE));
-        assertEquals(0, DatabaseUtils.queryNumEntries(db, Photos.TABLE));
-        assertEquals(0, DatabaseUtils.queryNumEntries(db, Albums.TABLE));
-        assertEquals(0, DatabaseUtils.queryNumEntries(db, Metadata.TABLE));
-    }
-
-    private SQLiteDatabase getReadableDB() {
-        return mDBHelper.getReadableDatabase();
-    }
-
-    private SQLiteDatabase getWritableDB() {
-        return mDBHelper.getWritableDatabase();
-    }
-
-    private void validateTable(String table, String[] projection) {
-        SQLiteDatabase db = getReadableDB();
-        Cursor cursor = db.query(table, projection, null, null, null, null, null);
-        assertNotNull(cursor);
-        assertEquals(cursor.getCount(), 0);
-        assertEquals(cursor.getColumnCount(), projection.length);
-        for (int i = 0; i < projection.length; i++) {
-            assertEquals(cursor.getColumnName(i), projection[i]);
-        }
-    }
-
-
-}
diff --git a/tests/src/com/android/photos/data/PhotoDatabaseUtils.java b/tests/src/com/android/photos/data/PhotoDatabaseUtils.java
deleted file mode 100644
index f7a46d4..0000000
--- a/tests/src/com/android/photos/data/PhotoDatabaseUtils.java
+++ /dev/null
@@ -1,135 +0,0 @@
-/*
- * Copyright (C) 2013 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.photos.data;
-
-import android.content.ContentValues;
-import android.database.Cursor;
-import android.database.sqlite.SQLiteDatabase;
-
-import com.android.photos.data.PhotoProvider.Accounts;
-import com.android.photos.data.PhotoProvider.Albums;
-import com.android.photos.data.PhotoProvider.Metadata;
-import com.android.photos.data.PhotoProvider.Photos;
-
-import junit.framework.AssertionFailedError;
-
-public class PhotoDatabaseUtils {
-    public static String[] PROJECTION_ALBUMS = {
-        Albums._ID,
-        Albums.ACCOUNT_ID,
-        Albums.PARENT_ID,
-        Albums.VISIBILITY,
-        Albums.LOCATION_STRING,
-        Albums.TITLE,
-        Albums.SUMMARY,
-        Albums.DATE_PUBLISHED,
-        Albums.DATE_MODIFIED,
-    };
-
-    public static String[] PROJECTION_METADATA = {
-        Metadata.PHOTO_ID,
-        Metadata.KEY,
-        Metadata.VALUE,
-    };
-
-    public static String[] PROJECTION_PHOTOS = {
-        Photos._ID,
-        Photos.ACCOUNT_ID,
-        Photos.WIDTH,
-        Photos.HEIGHT,
-        Photos.DATE_TAKEN,
-        Photos.ALBUM_ID,
-        Photos.MIME_TYPE,
-        Photos.TITLE,
-        Photos.DATE_MODIFIED,
-        Photos.ROTATION,
-    };
-
-    public static String[] PROJECTION_ACCOUNTS = {
-        Accounts._ID,
-        Accounts.ACCOUNT_NAME,
-    };
-
-    private static String SELECTION_ALBUM_PARENT_ID = Albums.PARENT_ID + " = ?";
-    private static String SELECTION_PHOTO_ALBUM_ID = Photos.ALBUM_ID + " = ?";
-    private static String SELECTION_ACCOUNT_ID = Accounts.ACCOUNT_NAME + " = ?";
-
-    public static long queryAlbumIdFromParentId(SQLiteDatabase db, long parentId) {
-        return queryId(db, Albums.TABLE, PROJECTION_ALBUMS, SELECTION_ALBUM_PARENT_ID, parentId);
-    }
-
-    public static long queryPhotoIdFromAlbumId(SQLiteDatabase db, long albumId) {
-        return queryId(db, Photos.TABLE, PROJECTION_PHOTOS, SELECTION_PHOTO_ALBUM_ID, albumId);
-    }
-
-    public static long queryAccountIdFromName(SQLiteDatabase db, String accountName) {
-        return queryId(db, Accounts.TABLE, PROJECTION_ACCOUNTS, SELECTION_ACCOUNT_ID, accountName);
-    }
-
-    public static long queryId(SQLiteDatabase db, String table, String[] projection,
-            String selection, Object parameter) {
-        String paramString = parameter == null ? null : parameter.toString();
-        String[] selectionArgs = {
-            paramString,
-        };
-        Cursor cursor = db.query(table, projection, selection, selectionArgs, null, null, null);
-        try {
-            if (cursor.getCount() != 1 || !cursor.moveToNext()) {
-                throw new AssertionFailedError("Couldn't find item in table");
-            }
-            long id = cursor.getLong(0);
-            return id;
-        } finally {
-            cursor.close();
-        }
-    }
-
-    public static boolean insertPhoto(SQLiteDatabase db, Integer width, Integer height,
-            Long dateTaken, Long albumId, String mimeType, Long accountId) {
-        ContentValues values = new ContentValues();
-        values.put(Photos.WIDTH, width);
-        values.put(Photos.HEIGHT, height);
-        values.put(Photos.DATE_TAKEN, dateTaken);
-        values.put(Photos.ALBUM_ID, albumId);
-        values.put(Photos.MIME_TYPE, mimeType);
-        values.put(Photos.ACCOUNT_ID, accountId);
-        return db.insert(Photos.TABLE, null, values) != -1;
-    }
-
-    public static boolean insertAlbum(SQLiteDatabase db, Long parentId, String title,
-            Integer privacy, Long accountId) {
-        ContentValues values = new ContentValues();
-        values.put(Albums.PARENT_ID, parentId);
-        values.put(Albums.TITLE, title);
-        values.put(Albums.VISIBILITY, privacy);
-        values.put(Albums.ACCOUNT_ID, accountId);
-        return db.insert(Albums.TABLE, null, values) != -1;
-    }
-
-    public static boolean insertMetadata(SQLiteDatabase db, Long photosId, String key, String value) {
-        ContentValues values = new ContentValues();
-        values.put(Metadata.PHOTO_ID, photosId);
-        values.put(Metadata.KEY, key);
-        values.put(Metadata.VALUE, value);
-        return db.insert(Metadata.TABLE, null, values) != -1;
-    }
-
-    public static boolean insertAccount(SQLiteDatabase db, String name) {
-        ContentValues values = new ContentValues();
-        values.put(Accounts.ACCOUNT_NAME, name);
-        return db.insert(Accounts.TABLE, null, values) != -1;
-    }
-}
diff --git a/tests/src/com/android/photos/data/PhotoProviderTest.java b/tests/src/com/android/photos/data/PhotoProviderTest.java
deleted file mode 100644
index 685946e..0000000
--- a/tests/src/com/android/photos/data/PhotoProviderTest.java
+++ /dev/null
@@ -1,391 +0,0 @@
-/*
- * Copyright (C) 2013 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.photos.data;
-
-import android.content.ContentProviderOperation;
-import android.content.ContentResolver;
-import android.content.ContentUris;
-import android.content.ContentValues;
-import android.content.OperationApplicationException;
-import android.database.Cursor;
-import android.database.sqlite.SQLiteDatabase;
-import android.database.sqlite.SQLiteOpenHelper;
-import android.net.Uri;
-import android.os.RemoteException;
-import android.provider.BaseColumns;
-import android.test.ProviderTestCase2;
-
-import com.android.photos.data.PhotoProvider.Accounts;
-import com.android.photos.data.PhotoProvider.Albums;
-import com.android.photos.data.PhotoProvider.Metadata;
-import com.android.photos.data.PhotoProvider.Photos;
-
-import java.util.ArrayList;
-
-public class PhotoProviderTest extends ProviderTestCase2<PhotoProvider> {
-    @SuppressWarnings("unused")
-    private static final String TAG = PhotoProviderTest.class.getSimpleName();
-
-    private static final String MIME_TYPE = "test/test";
-    private static final String ALBUM_TITLE = "My Album";
-    private static final long ALBUM_PARENT_ID = 100;
-    private static final String META_KEY = "mykey";
-    private static final String META_VALUE = "myvalue";
-    private static final String ACCOUNT_NAME = "foo@bar.com";
-
-    private static final Uri NO_TABLE_URI = PhotoProvider.BASE_CONTENT_URI;
-    private static final Uri BAD_TABLE_URI = Uri.withAppendedPath(PhotoProvider.BASE_CONTENT_URI,
-            "bad_table");
-
-    private static final String WHERE_METADATA_PHOTOS_ID = Metadata.PHOTO_ID + " = ?";
-    private static final String WHERE_METADATA = Metadata.PHOTO_ID + " = ? AND " + Metadata.KEY
-            + " = ?";
-
-    private long mAlbumId;
-    private long mPhotoId;
-    private long mMetadataId;
-    private long mAccountId;
-
-    private SQLiteOpenHelper mDBHelper;
-    private ContentResolver mResolver;
-    private NotificationWatcher mNotifications = new NotificationWatcher();
-
-    public PhotoProviderTest() {
-        super(PhotoProvider.class, PhotoProvider.AUTHORITY);
-    }
-
-    @Override
-    protected void setUp() throws Exception {
-        super.setUp();
-        mResolver = getMockContentResolver();
-        PhotoProvider provider = (PhotoProvider) getProvider();
-        provider.setMockNotification(mNotifications);
-        mDBHelper = provider.getDatabaseHelper();
-        SQLiteDatabase db = mDBHelper.getWritableDatabase();
-        db.beginTransaction();
-        try {
-            PhotoDatabaseUtils.insertAccount(db, ACCOUNT_NAME);
-            mAccountId = PhotoDatabaseUtils.queryAccountIdFromName(db, ACCOUNT_NAME);
-            PhotoDatabaseUtils.insertAlbum(db, ALBUM_PARENT_ID, ALBUM_TITLE,
-                    Albums.VISIBILITY_PRIVATE, mAccountId);
-            mAlbumId = PhotoDatabaseUtils.queryAlbumIdFromParentId(db, ALBUM_PARENT_ID);
-            PhotoDatabaseUtils.insertPhoto(db, 100, 100, System.currentTimeMillis(), mAlbumId,
-                    MIME_TYPE, mAccountId);
-            mPhotoId = PhotoDatabaseUtils.queryPhotoIdFromAlbumId(db, mAlbumId);
-            PhotoDatabaseUtils.insertMetadata(db, mPhotoId, META_KEY, META_VALUE);
-            String[] projection = {
-                    BaseColumns._ID,
-            };
-            Cursor cursor = db.query(Metadata.TABLE, projection, null, null, null, null, null);
-            cursor.moveToNext();
-            mMetadataId = cursor.getLong(0);
-            cursor.close();
-            db.setTransactionSuccessful();
-            mNotifications.reset();
-        } finally {
-            db.endTransaction();
-        }
-    }
-
-    @Override
-    protected void tearDown() throws Exception {
-        mDBHelper.close();
-        mDBHelper = null;
-        super.tearDown();
-        getMockContext().deleteDatabase(PhotoProvider.DB_NAME);
-    }
-
-    public void testDelete() {
-        try {
-            mResolver.delete(NO_TABLE_URI, null, null);
-            fail("Exeption should be thrown when no table given");
-        } catch (Exception e) {
-            // expected exception
-        }
-        try {
-            mResolver.delete(BAD_TABLE_URI, null, null);
-            fail("Exeption should be thrown when deleting from a table that doesn't exist");
-        } catch (Exception e) {
-            // expected exception
-        }
-
-        String[] selectionArgs = {
-            String.valueOf(mPhotoId)
-        };
-        // Delete some metadata
-        assertEquals(1,
-                mResolver.delete(Metadata.CONTENT_URI, WHERE_METADATA_PHOTOS_ID, selectionArgs));
-        Uri photoUri = ContentUris.withAppendedId(Photos.CONTENT_URI, mPhotoId);
-        assertEquals(1, mResolver.delete(photoUri, null, null));
-        Uri albumUri = ContentUris.withAppendedId(Albums.CONTENT_URI, mAlbumId);
-        assertEquals(1, mResolver.delete(albumUri, null, null));
-        // now delete something that isn't there
-        assertEquals(0, mResolver.delete(photoUri, null, null));
-    }
-
-    public void testDeleteMetadataId() {
-        Uri metadataUri = ContentUris.withAppendedId(Metadata.CONTENT_URI, mMetadataId);
-        assertEquals(1, mResolver.delete(metadataUri, null, null));
-        Cursor cursor = mResolver.query(Metadata.CONTENT_URI, null, null, null, null);
-        assertEquals(0, cursor.getCount());
-        cursor.close();
-    }
-
-    // Delete the album and ensure that the photos referring to the album are
-    // deleted.
-    public void testDeleteAlbumCascade() {
-        Uri albumUri = ContentUris.withAppendedId(Albums.CONTENT_URI, mAlbumId);
-        mResolver.delete(albumUri, null, null);
-        assertTrue(mNotifications.isNotified(Photos.CONTENT_URI));
-        assertTrue(mNotifications.isNotified(Metadata.CONTENT_URI));
-        assertTrue(mNotifications.isNotified(albumUri));
-        assertEquals(3, mNotifications.notificationCount());
-        Cursor cursor = mResolver.query(Photos.CONTENT_URI, PhotoDatabaseUtils.PROJECTION_PHOTOS,
-                null, null, null);
-        assertEquals(0, cursor.getCount());
-        cursor.close();
-    }
-
-    // Delete all albums and ensure that photos in any album are deleted.
-    public void testDeleteAlbumCascade2() {
-        mResolver.delete(Albums.CONTENT_URI, null, null);
-        assertTrue(mNotifications.isNotified(Photos.CONTENT_URI));
-        assertTrue(mNotifications.isNotified(Metadata.CONTENT_URI));
-        assertTrue(mNotifications.isNotified(Albums.CONTENT_URI));
-        assertEquals(3, mNotifications.notificationCount());
-        Cursor cursor = mResolver.query(Photos.CONTENT_URI, PhotoDatabaseUtils.PROJECTION_PHOTOS,
-                null, null, null);
-        assertEquals(0, cursor.getCount());
-        cursor.close();
-    }
-
-    // Delete a photo and ensure that the metadata for that photo are deleted.
-    public void testDeletePhotoCascade() {
-        Uri photoUri = ContentUris.withAppendedId(Photos.CONTENT_URI, mPhotoId);
-        mResolver.delete(photoUri, null, null);
-        assertTrue(mNotifications.isNotified(photoUri));
-        assertTrue(mNotifications.isNotified(Metadata.CONTENT_URI));
-        assertEquals(2, mNotifications.notificationCount());
-        Cursor cursor = mResolver.query(Metadata.CONTENT_URI,
-                PhotoDatabaseUtils.PROJECTION_METADATA, null, null, null);
-        assertEquals(0, cursor.getCount());
-        cursor.close();
-    }
-
-    public void testDeleteAccountCascade() {
-        Uri accountUri = ContentUris.withAppendedId(Accounts.CONTENT_URI, mAccountId);
-        SQLiteDatabase db = mDBHelper.getWritableDatabase();
-        db.beginTransaction();
-        PhotoDatabaseUtils.insertPhoto(db, 100, 100, System.currentTimeMillis(), null,
-                "image/jpeg", mAccountId);
-        PhotoDatabaseUtils.insertPhoto(db, 100, 100, System.currentTimeMillis(), null,
-                "image/jpeg", 0L);
-        PhotoDatabaseUtils.insertAlbum(db, null, "title", Albums.VISIBILITY_PRIVATE, 10630L);
-        db.setTransactionSuccessful();
-        db.endTransaction();
-        // ensure all pictures are there:
-        Cursor cursor = mResolver.query(Photos.CONTENT_URI, null, null, null, null);
-        assertEquals(3, cursor.getCount());
-        cursor.close();
-        // delete the account
-        assertEquals(1, mResolver.delete(accountUri, null, null));
-        // now ensure that all associated photos were deleted
-        cursor = mResolver.query(Photos.CONTENT_URI, null, null, null, null);
-        assertEquals(1, cursor.getCount());
-        cursor.close();
-        // now ensure all associated albums were deleted.
-        cursor = mResolver.query(Albums.CONTENT_URI, null, null, null, null);
-        assertEquals(1, cursor.getCount());
-        cursor.close();
-    }
-
-    public void testGetType() {
-        // We don't return types for albums
-        assertNull(mResolver.getType(Albums.CONTENT_URI));
-
-        Uri noImage = ContentUris.withAppendedId(Photos.CONTENT_URI, mPhotoId + 1);
-        assertNull(mResolver.getType(noImage));
-
-        Uri image = ContentUris.withAppendedId(Photos.CONTENT_URI, mPhotoId);
-        assertEquals(MIME_TYPE, mResolver.getType(image));
-    }
-
-    public void testInsert() {
-        ContentValues values = new ContentValues();
-        values.put(Albums.TITLE, "add me");
-        values.put(Albums.VISIBILITY, Albums.VISIBILITY_PRIVATE);
-        values.put(Albums.ACCOUNT_ID, 100L);
-        values.put(Albums.DATE_MODIFIED, 100L);
-        values.put(Albums.DATE_PUBLISHED, 100L);
-        values.put(Albums.LOCATION_STRING, "Home");
-        values.put(Albums.TITLE, "hello world");
-        values.putNull(Albums.PARENT_ID);
-        values.put(Albums.SUMMARY, "Nothing much to say about this");
-        Uri insertedUri = mResolver.insert(Albums.CONTENT_URI, values);
-        assertNotNull(insertedUri);
-        Cursor cursor = mResolver.query(insertedUri, PhotoDatabaseUtils.PROJECTION_ALBUMS, null,
-                null, null);
-        assertNotNull(cursor);
-        assertEquals(1, cursor.getCount());
-        cursor.close();
-    }
-
-    public void testUpdate() {
-        ContentValues values = new ContentValues();
-        // Normal update -- use an album.
-        values.put(Albums.TITLE, "foo");
-        Uri albumUri = ContentUris.withAppendedId(Albums.CONTENT_URI, mAlbumId);
-        assertEquals(1, mResolver.update(albumUri, values, null, null));
-        String[] projection = {
-            Albums.TITLE,
-        };
-        Cursor cursor = mResolver.query(albumUri, projection, null, null, null);
-        assertEquals(1, cursor.getCount());
-        assertTrue(cursor.moveToNext());
-        assertEquals("foo", cursor.getString(0));
-        cursor.close();
-
-        // Update a row that doesn't exist.
-        Uri noAlbumUri = ContentUris.withAppendedId(Albums.CONTENT_URI, mAlbumId + 1);
-        values.put(Albums.TITLE, "bar");
-        assertEquals(0, mResolver.update(noAlbumUri, values, null, null));
-
-        // Update a metadata value that exists.
-        ContentValues metadata = new ContentValues();
-        metadata.put(Metadata.PHOTO_ID, mPhotoId);
-        metadata.put(Metadata.KEY, META_KEY);
-        metadata.put(Metadata.VALUE, "new value");
-        assertEquals(1, mResolver.update(Metadata.CONTENT_URI, metadata, null, null));
-
-        projection = new String[] {
-            Metadata.VALUE,
-        };
-
-        String[] selectionArgs = {
-                String.valueOf(mPhotoId), META_KEY,
-        };
-
-        cursor = mResolver.query(Metadata.CONTENT_URI, projection, WHERE_METADATA, selectionArgs,
-                null);
-        assertEquals(1, cursor.getCount());
-        assertTrue(cursor.moveToNext());
-        assertEquals("new value", cursor.getString(0));
-        cursor.close();
-
-        // Update a metadata value that doesn't exist.
-        metadata.put(Metadata.KEY, "other stuff");
-        assertEquals(1, mResolver.update(Metadata.CONTENT_URI, metadata, null, null));
-
-        selectionArgs[1] = "other stuff";
-        cursor = mResolver.query(Metadata.CONTENT_URI, projection, WHERE_METADATA, selectionArgs,
-                null);
-        assertEquals(1, cursor.getCount());
-        assertTrue(cursor.moveToNext());
-        assertEquals("new value", cursor.getString(0));
-        cursor.close();
-
-        // Remove a metadata value using update.
-        metadata.putNull(Metadata.VALUE);
-        assertEquals(1, mResolver.update(Metadata.CONTENT_URI, metadata, null, null));
-        cursor = mResolver.query(Metadata.CONTENT_URI, projection, WHERE_METADATA, selectionArgs,
-                null);
-        assertEquals(0, cursor.getCount());
-        cursor.close();
-    }
-
-    public void testQuery() {
-        // Query a photo that exists.
-        Cursor cursor = mResolver.query(Photos.CONTENT_URI, PhotoDatabaseUtils.PROJECTION_PHOTOS,
-                null, null, null);
-        assertNotNull(cursor);
-        assertEquals(1, cursor.getCount());
-        assertTrue(cursor.moveToNext());
-        assertEquals(mPhotoId, cursor.getLong(0));
-        cursor.close();
-
-        // Query a photo that doesn't exist.
-        Uri noPhotoUri = ContentUris.withAppendedId(Photos.CONTENT_URI, mPhotoId + 1);
-        cursor = mResolver.query(noPhotoUri, PhotoDatabaseUtils.PROJECTION_PHOTOS, null, null,
-                null);
-        assertNotNull(cursor);
-        assertEquals(0, cursor.getCount());
-        cursor.close();
-
-        // Query a photo that exists using selection arguments.
-        String[] selectionArgs = {
-            String.valueOf(mPhotoId),
-        };
-
-        cursor = mResolver.query(Photos.CONTENT_URI, PhotoDatabaseUtils.PROJECTION_PHOTOS,
-                Photos._ID + " = ?", selectionArgs, null);
-        assertNotNull(cursor);
-        assertEquals(1, cursor.getCount());
-        assertTrue(cursor.moveToNext());
-        assertEquals(mPhotoId, cursor.getLong(0));
-        cursor.close();
-    }
-
-    public void testUpdatePhotoNotification() {
-        Uri photoUri = ContentUris.withAppendedId(Photos.CONTENT_URI, mPhotoId);
-        ContentValues values = new ContentValues();
-        values.put(Photos.MIME_TYPE, "not-a/mime-type");
-        mResolver.update(photoUri, values, null, null);
-        assertTrue(mNotifications.isNotified(photoUri));
-    }
-
-    public void testUpdateMetadataNotification() {
-        ContentValues values = new ContentValues();
-        values.put(Metadata.PHOTO_ID, mPhotoId);
-        values.put(Metadata.KEY, META_KEY);
-        values.put(Metadata.VALUE, "hello world");
-        mResolver.update(Metadata.CONTENT_URI, values, null, null);
-        assertTrue(mNotifications.isNotified(Metadata.CONTENT_URI));
-    }
-
-    public void testBatchTransaction() throws RemoteException, OperationApplicationException {
-        ArrayList<ContentProviderOperation> operations = new ArrayList<ContentProviderOperation>();
-        ContentProviderOperation.Builder insert = ContentProviderOperation
-                .newInsert(Photos.CONTENT_URI);
-        insert.withValue(Photos.WIDTH, 200L);
-        insert.withValue(Photos.HEIGHT, 100L);
-        insert.withValue(Photos.DATE_TAKEN, System.currentTimeMillis());
-        insert.withValue(Photos.ALBUM_ID, 1000L);
-        insert.withValue(Photos.MIME_TYPE, "image/jpg");
-        insert.withValue(Photos.ACCOUNT_ID, 1L);
-        operations.add(insert.build());
-        ContentProviderOperation.Builder update = ContentProviderOperation.newUpdate(Photos.CONTENT_URI);
-        update.withValue(Photos.DATE_MODIFIED, System.currentTimeMillis());
-        String[] whereArgs = {
-            "100",
-        };
-        String where = Photos.WIDTH + " = ?";
-        update.withSelection(where, whereArgs);
-        operations.add(update.build());
-        ContentProviderOperation.Builder delete = ContentProviderOperation
-                .newDelete(Photos.CONTENT_URI);
-        delete.withSelection(where, whereArgs);
-        operations.add(delete.build());
-        mResolver.applyBatch(PhotoProvider.AUTHORITY, operations);
-        assertEquals(3, mNotifications.notificationCount());
-        SQLiteDatabase db = mDBHelper.getReadableDatabase();
-        long id = PhotoDatabaseUtils.queryPhotoIdFromAlbumId(db, 1000L);
-        Uri uri = ContentUris.withAppendedId(Photos.CONTENT_URI, id);
-        assertTrue(mNotifications.isNotified(uri));
-        assertTrue(mNotifications.isNotified(Metadata.CONTENT_URI));
-        assertTrue(mNotifications.isNotified(Photos.CONTENT_URI));
-    }
-
-}
diff --git a/tests/src/com/android/photos/data/TestHelper.java b/tests/src/com/android/photos/data/TestHelper.java
deleted file mode 100644
index 338e160..0000000
--- a/tests/src/com/android/photos/data/TestHelper.java
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Copyright (C) 2013 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.photos.data;
-
-import android.util.Log;
-
-import junit.framework.TestCase;
-import junit.framework.TestSuite;
-
-import java.lang.reflect.Method;
-
-public class TestHelper {
-    private static String TAG = TestHelper.class.getSimpleName();
-
-    public interface TestInitialization {
-        void initialize(TestCase testCase);
-    }
-
-    public static void addTests(Class<? extends TestCase> testClass, TestSuite suite,
-            TestInitialization initialization) {
-        for (Method method : testClass.getDeclaredMethods()) {
-            if (method.getName().startsWith("test") && method.getParameterTypes().length == 0) {
-                TestCase test;
-                try {
-                    test = testClass.newInstance();
-                    test.setName(method.getName());
-                    initialization.initialize(test);
-                    suite.addTest(test);
-                } catch (IllegalArgumentException e) {
-                    Log.e(TAG, "Failed to create test case", e);
-                } catch (InstantiationException e) {
-                    Log.e(TAG, "Failed to create test case", e);
-                } catch (IllegalAccessException e) {
-                    Log.e(TAG, "Failed to create test case", e);
-                }
-            }
-        }
-    }
-
-}