title: OutOfMemoryError although vm has enough free memory
body: <p>I am getting this weird OutOfMemoryError that occurs although the dalvikvm reports enough heap space. Logs:</p>
  
  <pre><code>12-09 14:16:05.527: D/dalvikvm(10040): GC_FOR_ALLOC freed 551K, 21% free 38000K/47687K, paused 173ms, total 173ms
  12-09 14:16:05.527: I/dalvikvm-heap(10040): Grow heap (frag case) to 38.369MB for 858416-byte allocation
  12-09 14:16:05.699: D/dalvikvm(10040): GC_FOR_ALLOC freed 6K, 21% free 38832K/48583K, paused 169ms, total 169ms
  12-09 14:16:05.894: D/dalvikvm(10040): GC_FOR_ALLOC freed 103K, 20% free 38929K/48583K, paused 169ms, total 169ms
  12-09 14:16:05.894: I/dalvikvm-heap(10040): Forcing collection of SoftReferences for 858416-byte allocation
  12-09 14:16:06.074: D/dalvikvm(10040): GC_BEFORE_OOM freed 6K, 20% free 38922K/48583K, paused 182ms, total 182ms
  12-09 14:16:06.074: E/dalvikvm-heap(10040): Out of memory on a 858416-byte allocation.
  12-09 14:16:06.074: I/dalvikvm(10040): "AsyncTask #2" prio=5 tid=17 RUNNABLE
  12-09 14:16:06.074: I/dalvikvm(10040):   | group="main" sCount=0 dsCount=0 obj=0x42013580 self=0x5f2a48d8
  12-09 14:16:06.074: I/dalvikvm(10040):   | sysTid=10101 nice=10 sched=0/0 cgrp=apps/bg_non_interactive handle=1591062136
  12-09 14:16:06.074: I/dalvikvm(10040):   | schedstat=( 7305663992 4216491759 5326 ) utm=697 stm=32 core=1
  12-09 14:16:06.074: I/dalvikvm(10040):   at android.graphics.BitmapFactory.nativeDecodeStream(Native Method)
  12-09 14:16:06.074: I/dalvikvm(10040):   at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:619)
  12-09 14:16:06.074: I/dalvikvm(10040):   at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:691)
  </code></pre>
  
  <p>As you can see right before the outofmemory occurs the dalvikvm reports about 10mb free memory after gc. The allocation is for a 800k bitmap. I doubt that there is a race condition between gc and bitmap decoding here, because the reported free memory of dalvik didn't drop below 8mb free memory in all log statements of the last 20-30 seconds before the crash.</p>
  
  <p>The problem occurs on a Samsung Galaxy Tab 2 10.1 running Android 4.1.2.
  I'm using a modified version of the ImageFetcher classes from the Google I/O app (2012), so I'm already doing stuff like inJustDecodeBounds when loading images to optimize sampleSize option.</p>
  
  <p>As per documentation in <a href="https://developer.android.com/training/displaying-bitmaps/manage-memory.html">Managing Bitmap Memory</a> Android allocates Bitmap pixel data in the dalvik heap (since Android 3.0), so <strong>why does decoding the bitmap cause an outofmemory with 10mb free memory</strong>?</p>
  
  <p>Has anyone seen this before or may have an idea what's happening?</p>
  
  <p>EDIT:
  Per request <a href="https://code.google.com/p/iosched/source/browse/android/src/com/google/android/apps/iosched/util/ImageFetcher.java?name=2012">here</a> is the image loading code from the Google I/O app 2012. 
  In my app I am just calling</p>
  
  <pre><code>mImageFetcher.loadImage(myUrl, myImageView);
  </code></pre>
  
  <p>EDIT2:
  The relevant image decoding methods extracted from above link to make clear that I am already using sample size optimizations:</p>
  
  <pre><code>public static Bitmap decodeSampledBitmapFromDescriptor(
          FileDescriptor fileDescriptor, int reqWidth, int reqHeight) {
  
      // First decode with inJustDecodeBounds=true to check dimensions
      final BitmapFactory.Options options = new BitmapFactory.Options();
      options.inJustDecodeBounds = true;
      BitmapFactory.decodeFileDescriptor(fileDescriptor, null, options);
  
      // Calculate inSampleSize
      options.inSampleSize = calculateInSampleSize(options, reqWidth,
              reqHeight);
  
      // Decode bitmap with inSampleSize set
      options.inJustDecodeBounds = false;
      return BitmapFactory
              .decodeFileDescriptor(fileDescriptor, null, options);
  }
  
  public static int calculateInSampleSize(BitmapFactory.Options options,
          int reqWidth, int reqHeight) {
      // Raw height and width of image
      final int height = options.outHeight;
      final int width = options.outWidth;
      int inSampleSize = 1;
  
      if (height &gt; reqHeight || width &gt; reqWidth) {
          // Calculate ratios of height and width to requested height and
          // width
          final int heightRatio = Math.round((float) height
                  / (float) reqHeight);
          final int widthRatio = Math.round((float) width / (float) reqWidth);
  
          // Choose the smallest ratio as inSampleSize value, this will
          // guarantee
          // a final image with both dimensions larger than or equal to the
          // requested height and width.
          inSampleSize = heightRatio &lt; widthRatio ? heightRatio : widthRatio;
  
          // This offers some additional logic in case the image has a strange
          // aspect ratio. For example, a panorama may have a much larger
          // width than height. In these cases the total pixels might still
          // end up being too large to fit comfortably in memory, so we should
          // be more aggressive with sample down the image (=larger
          // inSampleSize).
  
          final float totalPixels = width * height;
  
          // Anything more than 2x the requested pixels we'll sample down
          // further.
          final float totalReqPixelsCap = reqWidth * reqHeight * 2;
  
          while (totalPixels / (inSampleSize * inSampleSize) &gt; totalReqPixelsCap) {
              inSampleSize++;
          }
      }
      return inSampleSize;
  }
  </code></pre>