Merge "Fix issue with adding widget with config activity to empty screen (issue 11381059)" into jb-ub-now-jetsonic
diff --git a/res/layout-land/all_apps_cling.xml b/res/layout-land/all_apps_cling.xml
deleted file mode 100644
index 820f00a..0000000
--- a/res/layout-land/all_apps_cling.xml
+++ /dev/null
@@ -1,48 +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.
--->
-<com.android.launcher3.Cling
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:launcher="http://schemas.android.com/apk/res-auto/com.android.launcher3"
-    launcher:drawIdentifier="all_apps_landscape">
-    <FrameLayout
-        android:layout_width="match_parent"
-        android:layout_height="match_parent"
-        android:layout_marginStart="40dp"
-        android:layout_marginTop="40dp">
-        <LinearLayout
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:orientation="vertical">
-            <TextView
-                style="@style/ClingTitleText"
-                android:id="@+id/all_apps_cling_title"
-                android:text="@string/all_apps_cling_title" />
-            <TextView
-                style="@style/ClingText"
-                android:id="@+id/all_apps_cling_add_item"
-                android:layout_width="match_parent"
-                android:layout_height="wrap_content"
-                android:text="@string/all_apps_cling_add_item" />
-        </LinearLayout>
-    </FrameLayout>
-    <Button
-        style="@style/ClingButton"
-        android:id="@+id/cling_dismiss"
-        android:layout_marginBottom="15dp"
-        android:layout_marginEnd="10dp"
-        android:layout_gravity="bottom|end"
-        android:onClick="dismissAllAppsCling" />
-</com.android.launcher3.Cling>
diff --git a/res/layout-port/all_apps_cling.xml b/res/layout-port/all_apps_cling.xml
deleted file mode 100644
index 62284ec..0000000
--- a/res/layout-port/all_apps_cling.xml
+++ /dev/null
@@ -1,48 +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.
--->
-<com.android.launcher3.Cling
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:launcher="http://schemas.android.com/apk/res-auto/com.android.launcher3"
-    launcher:drawIdentifier="all_apps_portrait">
-    <FrameLayout
-        android:layout_width="match_parent"
-        android:layout_height="match_parent"
-        android:layout_marginStart="20dp"
-        android:layout_marginTop="20dp">
-        <LinearLayout
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:orientation="vertical">
-            <TextView
-                style="@style/ClingTitleText"
-                android:id="@+id/all_apps_cling_title"
-                android:text="@string/all_apps_cling_title" />
-            <TextView
-                style="@style/ClingText"
-                android:id="@+id/all_apps_cling_add_item"
-                android:layout_width="285dp"
-                android:layout_height="wrap_content"
-                android:text="@string/all_apps_cling_add_item" />
-        </LinearLayout>
-    </FrameLayout>
-    <Button
-        style="@style/ClingButton"
-        android:id="@+id/cling_dismiss"
-        android:layout_marginBottom="15dp"
-        android:layout_marginEnd="10dp"
-        android:layout_gravity="bottom|end"
-        android:onClick="dismissAllAppsCling" />
-</com.android.launcher3.Cling>
diff --git a/res/layout-sw600dp-port/all_apps_cling.xml b/res/layout-sw600dp-port/all_apps_cling.xml
deleted file mode 100644
index cf65e41..0000000
--- a/res/layout-sw600dp-port/all_apps_cling.xml
+++ /dev/null
@@ -1,50 +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.
--->
-<com.android.launcher3.Cling
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:launcher="http://schemas.android.com/apk/res-auto/com.android.launcher3"
-    launcher:drawIdentifier="all_apps_portrait">
-    <FrameLayout
-        android:layout_width="match_parent"
-        android:layout_height="match_parent"
-        android:layout_marginStart="20dp"
-        android:layout_marginTop="20dp">
-        <LinearLayout
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:orientation="vertical">
-            <TextView
-                style="@style/ClingTitleText"
-                android:id="@+id/all_apps_cling_title"
-                android:text="@string/all_apps_cling_title" />
-            <TextView
-                style="@style/ClingText"
-                android:id="@+id/all_apps_cling_add_item"
-                android:layout_width="match_parent"
-                android:layout_height="wrap_content"
-                android:text="@string/all_apps_cling_add_item" />
-        </LinearLayout>
-    </FrameLayout>
-    <Button
-        style="@style/ClingButton"
-        android:id="@+id/cling_dismiss"
-        android:minWidth="168dp"
-        android:textSize="24sp"
-        android:layout_marginTop="235dp"
-        android:layout_marginEnd="36dp"
-        android:layout_gravity="top|end"
-        android:onClick="dismissAllAppsCling" />
-</com.android.launcher3.Cling>
diff --git a/res/layout-sw720dp/all_apps_cling.xml b/res/layout-sw720dp/all_apps_cling.xml
deleted file mode 100644
index 824d84f..0000000
--- a/res/layout-sw720dp/all_apps_cling.xml
+++ /dev/null
@@ -1,46 +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.
--->
-<com.android.launcher3.Cling
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:launcher="http://schemas.android.com/apk/res-auto/com.android.launcher3"
-    launcher:drawIdentifier="all_apps_large">
-    <FrameLayout
-        android:layout_width="match_parent"
-        android:layout_height="match_parent"
-        android:layout_marginStart="@dimen/cling_text_block_offset_x"
-        android:layout_marginTop="@dimen/cling_text_block_offset_y">
-        <LinearLayout
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:orientation="vertical">
-            <TextView
-                style="@style/ClingTitleText"
-                android:id="@+id/all_apps_cling_title"
-                android:text="@string/all_apps_cling_title" />
-            <TextView
-                style="@style/ClingText"
-                android:id="@+id/all_apps_cling_add_item"
-                android:layout_width="match_parent"
-                android:layout_height="wrap_content"
-                android:text="@string/all_apps_cling_add_item" />
-            <Button
-                style="@style/ClingButton"
-                android:id="@+id/cling_dismiss"
-                android:layout_marginTop="15dp"
-                android:onClick="dismissAllAppsCling" />
-        </LinearLayout>
-    </FrameLayout>
-</com.android.launcher3.Cling>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 1997c8b..30f4d8f 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -238,7 +238,7 @@
     <string name="apps_customize_widgets_scroll_format">Widgets page %1$d of %2$d</string>
 
     <!-- Clings -->
-    <!-- The title text for the workspace cling [CHAR_LIMIT=60] -->
+    <!-- The title text for the workspace cling [CHAR_LIMIT=30] -->
     <string name="first_run_cling_title">Welcome!</string>
     <!-- The description of how to use the workspace [CHAR_LIMIT=60] -->
     <string name="first_run_cling_description">Make yourself at home.</string>
@@ -248,17 +248,13 @@
     <string name="first_run_cling_search_bar_hint"></string>
     <!-- The description of how to use the workspace [CHAR_LIMIT=60] -->
     <string name="first_run_cling_create_screens_hint">Create more screens for apps and folders</string>
-    <!-- The title text for the workspace cling [CHAR_LIMIT=60] -->
+    <!-- The title text for the workspace cling [CHAR_LIMIT=30] -->
     <string name="workspace_cling_title">Organize your space</string>
-    <!-- The description of how to use the workspace [CHAR_LIMIT=160] -->
+    <!-- The description of how to use the workspace [CHAR_LIMIT=70] -->
     <string name="workspace_cling_move_item">Touch &amp; hold background to manage wallpaper, widgets and settings.</string>
-    <!-- The title text for the All Apps cling [CHAR_LIMIT=60] -->
-    <string name="all_apps_cling_title">Choose some apps</string>
-    <!-- The description of how to pick up and add an item to the workspace [CHAR_LIMIT=160] -->
-    <string name="all_apps_cling_add_item">To add an app to your Home screen, touch &amp; hold it.</string>
-    <!-- The title text for the Folder cling [CHAR_LIMIT=60] -->
+    <!-- The title text for the Folder cling [CHAR_LIMIT=30] -->
     <string name="folder_cling_title">Here\'s a folder</string>
-    <!-- The description of how to create a folder [CHAR_LIMIT=160] -->
+    <!-- The description of how to create a folder [CHAR_LIMIT=70] -->
     <string name="folder_cling_create_folder">To create one like this, touch &amp; hold an app, then move it over another.</string>
     <!-- The text on the button to dismiss a cling [CHAR_LIMIT=30] -->
     <string name="cling_dismiss">OK</string>
diff --git a/src/com/android/launcher3/WallpaperCropActivity.java b/src/com/android/launcher3/WallpaperCropActivity.java
index 491316d..276aba3 100644
--- a/src/com/android/launcher3/WallpaperCropActivity.java
+++ b/src/com/android/launcher3/WallpaperCropActivity.java
@@ -247,19 +247,19 @@
     private static int getRotationFromExifHelper(
             String path, Resources res, int resId, Context context, Uri uri) {
         ExifInterface ei = new ExifInterface();
+        InputStream is = null;
+        BufferedInputStream bis = null;
         try {
             if (path != null) {
                 ei.readExif(path);
             } else if (uri != null) {
-                InputStream is = context.getContentResolver().openInputStream(uri);
-                BufferedInputStream bis = new BufferedInputStream(is);
+                is = context.getContentResolver().openInputStream(uri);
+                bis = new BufferedInputStream(is);
                 ei.readExif(bis);
-                bis.close();
             } else {
-                InputStream is = res.openRawResource(resId);
-                BufferedInputStream bis = new BufferedInputStream(is);
+                is = res.openRawResource(resId);
+                bis = new BufferedInputStream(is);
                 ei.readExif(bis);
-                bis.close();
             }
             Integer ori = ei.getTagIntValue(ExifInterface.TAG_ORIENTATION);
             if (ori != null) {
@@ -267,6 +267,9 @@
             }
         } catch (IOException e) {
             Log.w(LOGTAG, "Getting exif data failed", e);
+        } finally {
+            Utils.closeSilently(bis);
+            Utils.closeSilently(is);
         }
         return 0;
     }
@@ -326,40 +329,15 @@
         // Get the crop
         boolean ltr = mCropView.getLayoutDirection() == View.LAYOUT_DIRECTION_LTR;
 
-        Point minDims = new Point();
-        Point maxDims = new Point();
+
         Display d = getWindowManager().getDefaultDisplay();
-        d.getCurrentSizeRange(minDims, maxDims);
 
         Point displaySize = new Point();
         d.getSize(displaySize);
-
-        int maxDim = Math.max(maxDims.x, maxDims.y);
-        final int minDim = Math.min(minDims.x, minDims.y);
-        int defaultWallpaperWidth;
-        if (isScreenLarge(getResources())) {
-            defaultWallpaperWidth = (int) (maxDim *
-                    wallpaperTravelToScreenWidthRatio(maxDim, minDim));
-        } else {
-            defaultWallpaperWidth = Math.max((int)
-                    (minDim * WALLPAPER_SCREENS_SPAN), maxDim);
-        }
-
         boolean isPortrait = displaySize.x < displaySize.y;
-        int portraitHeight;
-        if (isPortrait) {
-            portraitHeight = mCropView.getHeight();
-        } else {
-            // TODO: how to actually get the proper portrait height?
-            // This is not quite right:
-            portraitHeight = Math.max(maxDims.x, maxDims.y);
-        }
-        if (android.os.Build.VERSION.SDK_INT >=
-                android.os.Build.VERSION_CODES.JELLY_BEAN_MR1) {
-            Point realSize = new Point();
-            d.getRealSize(realSize);
-            portraitHeight = Math.max(realSize.x, realSize.y);
-        }
+
+        Point defaultWallpaperSize = getDefaultWallpaperSize(getResources(),
+                getWindowManager());
         // Get the crop
         RectF cropRect = mCropView.getCrop();
         int cropRotation = mCropView.getImageRotation();
@@ -378,7 +356,7 @@
         // (or all the way to the left, in RTL)
         float extraSpace = ltr ? rotatedInSize[0] - cropRect.right : cropRect.left;
         // Cap the amount of extra width
-        float maxExtraSpace = defaultWallpaperWidth / cropScale - cropRect.width();
+        float maxExtraSpace = defaultWallpaperSize.x / cropScale - cropRect.width();
         extraSpace = Math.min(extraSpace, maxExtraSpace);
 
         if (ltr) {
@@ -389,10 +367,10 @@
 
         // ADJUST CROP HEIGHT
         if (isPortrait) {
-            cropRect.bottom = cropRect.top + portraitHeight / cropScale;
+            cropRect.bottom = cropRect.top + defaultWallpaperSize.y / cropScale;
         } else { // LANDSCAPE
             float extraPortraitHeight =
-                    portraitHeight / cropScale - cropRect.height();
+                    defaultWallpaperSize.y / cropScale - cropRect.height();
             float expandHeight =
                     Math.min(Math.min(rotatedInSize[1] - cropRect.bottom, cropRect.top),
                             extraPortraitHeight / 2);
@@ -606,13 +584,13 @@
                 }
 
                 // See how much we're reducing the size of the image
-                int scaleDownSampleSize = Math.min(roundedTrueCrop.width() / mOutWidth,
-                        roundedTrueCrop.height() / mOutHeight);
-
+                int scaleDownSampleSize = Math.max(1, Math.min(roundedTrueCrop.width() / mOutWidth,
+                        roundedTrueCrop.height() / mOutHeight));
                 // Attempt to open a region decoder
                 BitmapRegionDecoder decoder = null;
+                InputStream is = null;
                 try {
-                    InputStream is = regenerateInputStream();
+                    is = regenerateInputStream();
                     if (is == null) {
                         Log.w(LOGTAG, "cannot get input stream for uri=" + mInUri.toString());
                         failure = true;
@@ -622,6 +600,9 @@
                     Utils.closeSilently(is);
                 } catch (IOException e) {
                     Log.w(LOGTAG, "cannot open region decoder for file: " + mInUri.toString(), e);
+                } finally {
+                   Utils.closeSilently(is);
+                   is = null;
                 }
 
                 Bitmap crop = null;
@@ -637,7 +618,7 @@
 
                 if (crop == null) {
                     // BitmapRegionDecoder has failed, try to crop in-memory
-                    InputStream is = regenerateInputStream();
+                    is = regenerateInputStream();
                     Bitmap fullSize = null;
                     if (is != null) {
                         BitmapFactory.Options options = new BitmapFactory.Options();
@@ -757,7 +738,7 @@
 
     protected void updateWallpaperDimensions(int width, int height) {
         String spKey = getSharedPreferencesKey();
-        SharedPreferences sp = getSharedPreferences(spKey, Context.MODE_PRIVATE);
+        SharedPreferences sp = getSharedPreferences(spKey, Context.MODE_MULTI_PROCESS);
         SharedPreferences.Editor editor = sp.edit();
         if (width != 0 && height != 0) {
             editor.putInt(WALLPAPER_WIDTH_KEY, width);
diff --git a/src/com/android/launcher3/Workspace.java b/src/com/android/launcher3/Workspace.java
index 5bd0bc6..8c2c89d 100644
--- a/src/com/android/launcher3/Workspace.java
+++ b/src/com/android/launcher3/Workspace.java
@@ -1190,7 +1190,7 @@
 
     protected void setWallpaperDimension() {
         String spKey = WallpaperCropActivity.getSharedPreferencesKey();
-        SharedPreferences sp = mLauncher.getSharedPreferences(spKey, Context.MODE_PRIVATE);
+        SharedPreferences sp = mLauncher.getSharedPreferences(spKey, Context.MODE_MULTI_PROCESS);
         WallpaperPickerActivity.suggestWallpaperDimension(mLauncher.getResources(),
                 sp, mLauncher.getWindowManager(), mWallpaperManager);
     }
diff --git a/src/com/android/photos/BitmapRegionTileSource.java b/src/com/android/photos/BitmapRegionTileSource.java
index b85caaa..2f203af 100644
--- a/src/com/android/photos/BitmapRegionTileSource.java
+++ b/src/com/android/photos/BitmapRegionTileSource.java
@@ -24,6 +24,9 @@
 import android.graphics.BitmapFactory;
 import android.graphics.BitmapRegionDecoder;
 import android.graphics.Canvas;
+import android.graphics.Matrix;
+import android.graphics.Paint;
+import android.graphics.PorterDuff;
 import android.graphics.Rect;
 import android.net.Uri;
 import android.os.Build;
@@ -42,6 +45,103 @@
 import java.io.IOException;
 import java.io.InputStream;
 
+interface SimpleBitmapRegionDecoder {
+    int getWidth();
+    int getHeight();
+    Bitmap decodeRegion(Rect wantRegion, BitmapFactory.Options options);
+}
+
+class SimpleBitmapRegionDecoderWrapper implements SimpleBitmapRegionDecoder {
+    BitmapRegionDecoder mDecoder;
+    private SimpleBitmapRegionDecoderWrapper(BitmapRegionDecoder decoder) {
+        mDecoder = decoder;
+    }
+    public static SimpleBitmapRegionDecoderWrapper newInstance(
+            String pathName, boolean isShareable) {
+        try {
+            BitmapRegionDecoder d = BitmapRegionDecoder.newInstance(pathName, isShareable);
+            if (d != null) {
+                return new SimpleBitmapRegionDecoderWrapper(d);
+            }
+        } catch (IOException e) {
+            Log.w("BitmapRegionTileSource", "getting decoder failed for path " + pathName, e);
+            return null;
+        }
+        return null;
+    }
+    public static SimpleBitmapRegionDecoderWrapper newInstance(
+            InputStream is, boolean isShareable) {
+        try {
+            BitmapRegionDecoder d = BitmapRegionDecoder.newInstance(is, isShareable);
+            if (d != null) {
+                return new SimpleBitmapRegionDecoderWrapper(d);
+            }
+        } catch (IOException e) {
+            Log.w("BitmapRegionTileSource", "getting decoder failed", e);
+            return null;
+        }
+        return null;
+    }
+    public int getWidth() {
+        return mDecoder.getWidth();
+    }
+    public int getHeight() {
+        return mDecoder.getHeight();
+    }
+    public Bitmap decodeRegion(Rect wantRegion, BitmapFactory.Options options) {
+        return mDecoder.decodeRegion(wantRegion, options);
+    }
+}
+
+class DumbBitmapRegionDecoder implements SimpleBitmapRegionDecoder {
+    //byte[] mStreamCopy;
+    Bitmap mBuffer;
+    Canvas mTempCanvas;
+    Paint mTempPaint;
+    private DumbBitmapRegionDecoder(Bitmap b) {
+        mBuffer = b;
+    }
+    public static DumbBitmapRegionDecoder newInstance(String pathName) {
+        Bitmap b = BitmapFactory.decodeFile(pathName);
+        if (b != null) {
+            return new DumbBitmapRegionDecoder(b);
+        }
+        return null;
+    }
+    public static DumbBitmapRegionDecoder newInstance(InputStream is) {
+        Bitmap b = BitmapFactory.decodeStream(is);
+        if (b != null) {
+            return new DumbBitmapRegionDecoder(b);
+        }
+        return null;
+    }
+    public int getWidth() {
+        return mBuffer.getWidth();
+    }
+    public int getHeight() {
+        return mBuffer.getHeight();
+    }
+    public Bitmap decodeRegion(Rect wantRegion, BitmapFactory.Options options) {
+        if (mTempCanvas == null) {
+            mTempCanvas = new Canvas();
+            mTempPaint = new Paint();
+            mTempPaint.setFilterBitmap(true);
+        }
+        int sampleSize = Math.max(options.inSampleSize, 1);
+        Bitmap newBitmap = Bitmap.createBitmap(
+                wantRegion.width() / sampleSize,
+                wantRegion.height() / sampleSize,
+                Bitmap.Config.ARGB_8888);
+        mTempCanvas.setBitmap(newBitmap);
+        mTempCanvas.save();
+        mTempCanvas.scale(1f / sampleSize, 1f / sampleSize);
+        mTempCanvas.drawBitmap(mBuffer, -wantRegion.left, -wantRegion.top, mTempPaint);
+        mTempCanvas.restore();
+        mTempCanvas.setBitmap(null);
+        return newBitmap;
+    }
+}
+
 /**
  * A {@link com.android.photos.views.TiledImageRenderer.TileSource} using
  * {@link BitmapRegionDecoder} to wrap a local file
@@ -59,7 +159,7 @@
     public static final int MAX_PREVIEW_SIZE = GL_SIZE_LIMIT / 2;
 
     public static abstract class BitmapSource {
-        private BitmapRegionDecoder mDecoder;
+        private SimpleBitmapRegionDecoder mDecoder;
         private Bitmap mPreview;
         private int mPreviewSize;
         private int mRotation;
@@ -103,7 +203,7 @@
             return mState;
         }
 
-        public BitmapRegionDecoder getBitmapRegionDecoder() {
+        public SimpleBitmapRegionDecoder getBitmapRegionDecoder() {
             return mDecoder;
         }
 
@@ -120,7 +220,7 @@
         }
 
         public abstract boolean readExif(ExifInterface ei);
-        public abstract BitmapRegionDecoder loadBitmapRegionDecoder();
+        public abstract SimpleBitmapRegionDecoder loadBitmapRegionDecoder();
         public abstract Bitmap loadPreviewBitmap(BitmapFactory.Options options);
     }
 
@@ -131,13 +231,13 @@
             mPath = path;
         }
         @Override
-        public BitmapRegionDecoder loadBitmapRegionDecoder() {
-            try {
-                return BitmapRegionDecoder.newInstance(mPath, true);
-            } catch (IOException e) {
-                Log.w("BitmapRegionTileSource", "getting decoder failed", e);
-                return null;
+        public SimpleBitmapRegionDecoder loadBitmapRegionDecoder() {
+            SimpleBitmapRegionDecoder d;
+            d = SimpleBitmapRegionDecoderWrapper.newInstance(mPath, true);
+            if (d == null) {
+                d = DumbBitmapRegionDecoder.newInstance(mPath);
             }
+            return d;
         }
         @Override
         public Bitmap loadPreviewBitmap(BitmapFactory.Options options) {
@@ -168,11 +268,17 @@
             return new BufferedInputStream(is);
         }
         @Override
-        public BitmapRegionDecoder loadBitmapRegionDecoder() {
+        public SimpleBitmapRegionDecoder loadBitmapRegionDecoder() {
             try {
                 InputStream is = regenerateInputStream();
-                BitmapRegionDecoder regionDecoder = BitmapRegionDecoder.newInstance(is, false);
+                SimpleBitmapRegionDecoder regionDecoder =
+                        SimpleBitmapRegionDecoderWrapper.newInstance(is, false);
                 Utils.closeSilently(is);
+                if (regionDecoder == null) {
+                    is = regenerateInputStream();
+                    regionDecoder = DumbBitmapRegionDecoder.newInstance(is);
+                    Utils.closeSilently(is);
+                }
                 return regionDecoder;
             } catch (FileNotFoundException e) {
                 Log.e("BitmapRegionTileSource", "Failed to load URI " + mUri, e);
@@ -196,8 +302,9 @@
         }
         @Override
         public boolean readExif(ExifInterface ei) {
+            InputStream is = null;
             try {
-                InputStream is = regenerateInputStream();
+                is = regenerateInputStream();
                 ei.readExif(is);
                 Utils.closeSilently(is);
                 return true;
@@ -207,6 +314,8 @@
             } catch (IOException e) {
                 Log.e("BitmapRegionTileSource", "Failed to load URI " + mUri, e);
                 return false;
+            } finally {
+                Utils.closeSilently(is);
             }
         }
     }
@@ -224,16 +333,17 @@
             return new BufferedInputStream(is);
         }
         @Override
-        public BitmapRegionDecoder loadBitmapRegionDecoder() {
-            try {
-                InputStream is = regenerateInputStream();
-                BitmapRegionDecoder regionDecoder = BitmapRegionDecoder.newInstance(is, true);
+        public SimpleBitmapRegionDecoder loadBitmapRegionDecoder() {
+            InputStream is = regenerateInputStream();
+            SimpleBitmapRegionDecoder regionDecoder =
+                    SimpleBitmapRegionDecoderWrapper.newInstance(is, false);
+            Utils.closeSilently(is);
+            if (regionDecoder == null) {
+                is = regenerateInputStream();
+                regionDecoder = DumbBitmapRegionDecoder.newInstance(is);
                 Utils.closeSilently(is);
-                return regionDecoder;
-            } catch (IOException e) {
-                Log.e("BitmapRegionTileSource", "Error reading resource", e);
-                return null;
             }
+            return regionDecoder;
         }
         @Override
         public Bitmap loadPreviewBitmap(BitmapFactory.Options options) {
@@ -253,7 +363,7 @@
         }
     }
 
-    BitmapRegionDecoder mDecoder;
+    SimpleBitmapRegionDecoder mDecoder;
     int mWidth;
     int mHeight;
     int mTileSize;