am d10dda27: Fix the layout of title in Gallery-Picker.

Merge commit 'd10dda271e22fd312381eb3437b0541525498452' into eclair-mr2

* commit 'd10dda271e22fd312381eb3437b0541525498452':
  Fix the layout of title in Gallery-Picker.
diff --git a/res/layout/camera.xml b/res/layout/camera.xml
index 8984a0c..b9530e6 100644
--- a/res/layout/camera.xml
+++ b/res/layout/camera.xml
@@ -80,7 +80,7 @@
                         android:layout_width="wrap_content"
                         android:layout_height="wrap_content"
                         android:id="@+id/flash_icon"
-                        camera:modes="@array/pref_camera_flashmode_entryvalues"
+                        camera:modes="@array/flash_modes"
                         camera:icons="@array/flash_icons"
                         android:visibility="visible"/>
             </com.android.camera.EvenlySpacedLayout>
diff --git a/res/values/arrays.xml b/res/values/arrays.xml
index b6cb407..026ed71 100644
--- a/res/values/arrays.xml
+++ b/res/values/arrays.xml
@@ -134,9 +134,17 @@
         <item>@string/pref_camera_recordlocation_entry_on</item>
     </array>
 
+    <string-array name="flash_modes" translatable="false">
+        <item>auto</item>
+        <item>on</item>
+        <item>off</item>
+        <item>no_flash</item>
+    </string-array>
+
     <array name="flash_icons">
         <item>@drawable/ic_viewfinder_flash_auto</item>
         <item>@drawable/ic_viewfinder_flash_on</item>
+        <item>@drawable/ic_viewfinder_flash_off</item>
         <item>@drawable/ic_viewfinder_empty</item>
     </array>
 
diff --git a/src/com/android/camera/BitmapManager.java b/src/com/android/camera/BitmapManager.java
index 36c7ec1..3ae6b93 100644
--- a/src/com/android/camera/BitmapManager.java
+++ b/src/com/android/camera/BitmapManager.java
@@ -16,8 +16,11 @@
 
 package com.android.camera;
 
+import android.content.ContentResolver;
 import android.graphics.Bitmap;
 import android.graphics.BitmapFactory;
+import android.provider.MediaStore.Images;
+import android.provider.MediaStore.Video;
 import android.util.Log;
 
 import java.io.FileDescriptor;
@@ -38,7 +41,7 @@
     private static class ThreadStatus {
         public State mState = State.ALLOW;
         public BitmapFactory.Options mOptions;
-
+        public boolean mThumbRequesting;
         @Override
         public String toString() {
             String s;
@@ -107,7 +110,7 @@
         getOrCreateThreadStatus(t).mState = State.ALLOW;
     }
 
-    public synchronized void cancelThreadDecoding(Thread t) {
+    public synchronized void cancelThreadDecoding(Thread t, ContentResolver cr) {
         ThreadStatus status = getOrCreateThreadStatus(t);
         status.mState = State.CANCEL;
         if (status.mOptions != null) {
@@ -116,6 +119,49 @@
 
         // Wake up threads in waiting list
         notifyAll();
+
+        // Since our cancel request can arrive MediaProvider earlier than getThumbnail request,
+        // we use mThumbRequesting flag to make sure our request does cancel the request.
+        try {
+            synchronized (status) {
+                while (status.mThumbRequesting) {
+                    Images.Thumbnails.cancelThumbnailRequest(cr, -1, t.getId());
+                    Video.Thumbnails.cancelThumbnailRequest(cr, -1, t.getId());
+                    status.wait(200);
+                }
+            }
+        } catch (InterruptedException ex) {
+            // ignore it.
+        }
+    }
+
+    public Bitmap getThumbnail(ContentResolver cr, long origId, int kind,
+            BitmapFactory.Options options, boolean isVideo) {
+        Thread t = Thread.currentThread();
+        ThreadStatus status = getOrCreateThreadStatus(t);
+
+        if (!canThreadDecoding(t)) {
+            Log.d(TAG, "Thread " + t + " is not allowed to decode.");
+            return null;
+        }
+
+        try {
+            synchronized (status) {
+                status.mThumbRequesting = true;
+            }
+            if (isVideo) {
+                return Video.Thumbnails.getThumbnail(cr, origId, t.getId(),
+                        kind, null);
+            } else {
+                return Images.Thumbnails.getThumbnail(cr, origId, t.getId(),
+                        kind, null);
+            }
+        } finally {
+            synchronized (status) {
+                status.mThumbRequesting = false;
+                status.notifyAll();
+            }
+        }
     }
 
     public static synchronized BitmapManager instance() {
diff --git a/src/com/android/camera/Camera.java b/src/com/android/camera/Camera.java
index 33dfa08..45a2f9b 100644
--- a/src/com/android/camera/Camera.java
+++ b/src/com/android/camera/Camera.java
@@ -89,6 +89,9 @@
 
     private static final String TAG = "camera";
 
+    // This value must be as same as the item value of the string array
+    // "flash_mode" in file "res/values/arrays.xml".
+    private static final String NO_FLASH_MODE = "no_flash";
     private static final int CROP_MSG = 1;
     private static final int FIRST_TIME_INIT = 2;
     private static final int RESTART_PREVIEW = 3;
@@ -1776,7 +1779,7 @@
             } else {
                 flashMode = mParameters.getFlashMode();
                 if (flashMode == null) {
-                    flashMode = Parameters.FLASH_MODE_OFF;
+                    flashMode = NO_FLASH_MODE;
                 }
             }
 
diff --git a/src/com/android/camera/GalleryPicker.java b/src/com/android/camera/GalleryPicker.java
index 39d1d1e..29a06a6 100644
--- a/src/com/android/camera/GalleryPicker.java
+++ b/src/com/android/camera/GalleryPicker.java
@@ -310,8 +310,7 @@
 
     private void abortWorker() {
         if (mWorkerThread != null) {
-            BitmapManager.instance().cancelThreadDecoding(mWorkerThread);
-            MediaStore.Images.Thumbnails.cancelThumbnailRequest(getContentResolver(), -1);
+            BitmapManager.instance().cancelThreadDecoding(mWorkerThread, getContentResolver());
             mAbort = true;
             try {
                 mWorkerThread.join();
@@ -331,7 +330,6 @@
 
     // This is run in the worker thread.
     private void workerRun() {
-
         // We collect items from checkImageList() and checkBucketIds() and
         // put them in allItems. Later we give allItems to checkThumbBitmap()
         // and generated thumbnail bitmaps for each item. We do this instead of
diff --git a/src/com/android/camera/ImageGallery.java b/src/com/android/camera/ImageGallery.java
index 680d186..cfdc634 100644
--- a/src/com/android/camera/ImageGallery.java
+++ b/src/com/android/camera/ImageGallery.java
@@ -939,6 +939,7 @@
     }
 
     private void onShareMultipleClicked() {
+        if (mMultiSelected == null) return;
         if (mMultiSelected.size() > 1) {
             Intent intent = new Intent();
             intent.setAction(Intent.ACTION_SEND_MULTIPLE);
diff --git a/src/com/android/camera/ImageGetter.java b/src/com/android/camera/ImageGetter.java
index 08c9370..72228da 100644
--- a/src/com/android/camera/ImageGetter.java
+++ b/src/com/android/camera/ImageGetter.java
@@ -234,8 +234,7 @@
     public synchronized void cancelCurrent() {
         Util.Assert(mGetterThread != null);
         mCancel = true;
-        BitmapManager.instance().cancelThreadDecoding(mGetterThread);
-        MediaStore.Images.Thumbnails.cancelThumbnailRequest(mCr, -1);
+        BitmapManager.instance().cancelThreadDecoding(mGetterThread, mCr);
     }
 
     // Cancels current loading (with waiting).
diff --git a/src/com/android/camera/ImageLoader.java b/src/com/android/camera/ImageLoader.java
index c4d211f..a394508 100644
--- a/src/com/android/camera/ImageLoader.java
+++ b/src/com/android/camera/ImageLoader.java
@@ -163,8 +163,7 @@
         if (mDecodeThread != null) {
             try {
                 Thread t = mDecodeThread;
-                BitmapManager.instance().cancelThreadDecoding(t);
-                MediaStore.Images.Thumbnails.cancelThumbnailRequest(mCr, -1);
+                BitmapManager.instance().cancelThreadDecoding(t, mCr);
                 t.join();
                 mDecodeThread = null;
             } catch (InterruptedException ex) {
diff --git a/src/com/android/camera/VideoCamera.java b/src/com/android/camera/VideoCamera.java
index afd4cdd..4f22804 100644
--- a/src/com/android/camera/VideoCamera.java
+++ b/src/com/android/camera/VideoCamera.java
@@ -389,6 +389,7 @@
             }
             case R.id.review_thumbnail: {
                 stopVideoRecordingAndShowReview();
+                initializeRecorder();
                 break;
             }
         }
@@ -1382,13 +1383,6 @@
             mRecordingTimeView.setTextColor(color);
         }
 
-        // Work around a limitation of the T-Mobile G1: The T-Mobile
-        // hardware blitter can't pixel-accurately scale and clip at the
-        // same time, and the SurfaceFlinger doesn't attempt to work around
-        // this limitation. In order to avoid visual corruption we must
-        // manually refresh the entire surface view when changing any
-        // overlapping view's contents.
-        mVideoPreview.invalidate();
         mHandler.sendEmptyMessageDelayed(
                 UPDATE_RECORD_TIME, next_update_delay);
     }
diff --git a/src/com/android/camera/ViewImage.java b/src/com/android/camera/ViewImage.java
index 3ee3029..ea14117 100644
--- a/src/com/android/camera/ViewImage.java
+++ b/src/com/android/camera/ViewImage.java
@@ -895,6 +895,7 @@
     private Uri getCurrentUri() {
         if (mAllImages.getCount() == 0) return null;
         IImage image = mAllImages.getImageAt(mCurrentPosition);
+        if (image == null) return null;
         return image.fullSizeImageUri();
     }
 
diff --git a/src/com/android/camera/gallery/BaseImage.java b/src/com/android/camera/gallery/BaseImage.java
index 6607b08..6e2f8f1 100644
--- a/src/com/android/camera/gallery/BaseImage.java
+++ b/src/com/android/camera/gallery/BaseImage.java
@@ -181,8 +181,8 @@
         Bitmap b = null;
         try {
             long id = mId;
-            b = Images.Thumbnails.getThumbnail(mContentResolver, id,
-                    Images.Thumbnails.MICRO_KIND, null);
+            b = BitmapManager.instance().getThumbnail(mContentResolver, id,
+                    Images.Thumbnails.MICRO_KIND, null, false);
         } catch (Throwable ex) {
             Log.e(TAG, "miniThumbBitmap got exception", ex);
             return null;
diff --git a/src/com/android/camera/gallery/Image.java b/src/com/android/camera/gallery/Image.java
index 6190706..78ec382 100644
--- a/src/com/android/camera/gallery/Image.java
+++ b/src/com/android/camera/gallery/Image.java
@@ -16,6 +16,7 @@
 
 package com.android.camera.gallery;
 
+import com.android.camera.BitmapManager;
 import com.android.camera.Util;
 
 import android.content.ContentResolver;
@@ -152,8 +153,8 @@
         BitmapFactory.Options options = new BitmapFactory.Options();
         options.inDither = false;
         options.inPreferredConfig = Bitmap.Config.ARGB_8888;
-        bitmap = Images.Thumbnails.getThumbnail(
-                    mContentResolver, mId, Images.Thumbnails.MINI_KIND, options);
+        bitmap = BitmapManager.instance().getThumbnail(mContentResolver, mId,
+                Images.Thumbnails.MINI_KIND, options, false);
 
         if (bitmap != null && rotateAsNeeded) {
             bitmap = Util.rotate(bitmap, getDegreesRotated());
diff --git a/src/com/android/camera/gallery/VideoObject.java b/src/com/android/camera/gallery/VideoObject.java
index 8e3b60e..589e42f 100644
--- a/src/com/android/camera/gallery/VideoObject.java
+++ b/src/com/android/camera/gallery/VideoObject.java
@@ -16,10 +16,13 @@
 
 package com.android.camera.gallery;
 
+import com.android.camera.BitmapManager;
+
 import android.content.ContentResolver;
 import android.graphics.Bitmap;
 import android.media.ThumbnailUtil;
 import android.net.Uri;
+import android.provider.MediaStore.Images;
 import android.provider.MediaStore.Video;
 import android.util.Log;
 
@@ -110,8 +113,8 @@
     public Bitmap miniThumbBitmap() {
         try {
             long id = mId;
-            return Video.Thumbnails.getThumbnail(mContentResolver, id,
-                    Video.Thumbnails.MICRO_KIND, null);
+            return BitmapManager.instance().getThumbnail(mContentResolver,
+                    id, Images.Thumbnails.MICRO_KIND, null, true);
         } catch (Throwable ex) {
             Log.e(TAG, "miniThumbBitmap got exception", ex);
             return null;
diff --git a/tests/src/com/android/camera/BitmapManagerUnitTests.java b/tests/src/com/android/camera/BitmapManagerUnitTests.java
index fc1ade1..7878b74 100644
--- a/tests/src/com/android/camera/BitmapManagerUnitTests.java
+++ b/tests/src/com/android/camera/BitmapManagerUnitTests.java
@@ -75,7 +75,7 @@
         assertTrue(mBitmapManager.canThreadDecoding(t));
 
         // Disallow thread t to decode.
-        mBitmapManager.cancelThreadDecoding(t);
+        mBitmapManager.cancelThreadDecoding(t, mContext.getContentResolver());
         assertFalse(mBitmapManager.canThreadDecoding(t));
 
         // Allow thread t to decode again.
@@ -96,7 +96,7 @@
 
     public void testCancelDecoding() {
         DecodeThread t = new DecodeThread();
-        mBitmapManager.cancelThreadDecoding(t);
+        mBitmapManager.cancelThreadDecoding(t, mContext.getContentResolver());
         try {
             t.start();
             t.join();
@@ -108,7 +108,7 @@
 
     public void testAllowDecoding() {
         DecodeThread t = new DecodeThread();
-        mBitmapManager.cancelThreadDecoding(t);
+        mBitmapManager.cancelThreadDecoding(t, mContext.getContentResolver());
         mBitmapManager.allowThreadDecoding(t);
         try {
             t.start();
@@ -123,7 +123,7 @@
         DecodeThread t1 = new DecodeThread();
         DecodeThread t2 = new DecodeThread();
         mBitmapManager.allowThreadDecoding(t1);
-        mBitmapManager.cancelThreadDecoding(t2);
+        mBitmapManager.cancelThreadDecoding(t2, mContext.getContentResolver());
         t1.start();
         t2.start();