am 2f9a1ce2: When checking the current playback position against the length of the file, make sure the length is valid. Otherwise we can end up endlessly (recursively) calling next(), and run out of stack.

Merge commit '2f9a1ce2f3b0ae72d698c240ce8448bc7cfe3a77'

* commit '2f9a1ce2f3b0ae72d698c240ce8448bc7cfe3a77':
  When checking the current playback position against the length
diff --git a/res/values/colors.xml b/res/values/colors.xml
index 9a7806a..07a5839 100644
--- a/res/values/colors.xml
+++ b/res/values/colors.xml
@@ -16,6 +16,5 @@
 
 <resources>
     <color name="appwidget_text">#ff000000</color>
-    <color name="appwidget_shadow">#ffffffff</color>
 </resources>
 
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
deleted file mode 100644
index 539b64f..0000000
--- a/res/values/dimens.xml
+++ /dev/null
@@ -1,20 +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.
--->
-
-<resources>
-    <!-- Size of widget album art cutout -->
-    <dimen name="appwidget_cutout">198dip</dimen>
-</resources>
diff --git a/src/com/android/music/MediaPlaybackActivity.java b/src/com/android/music/MediaPlaybackActivity.java
index 8f47a40..3c9dc1a 100644
--- a/src/com/android/music/MediaPlaybackActivity.java
+++ b/src/com/android/music/MediaPlaybackActivity.java
@@ -1220,13 +1220,16 @@
                 return;
             }
             
-            if (mService.getAudioId() < 0 && path.toLowerCase().startsWith("http://")) {
+            int songid = mService.getAudioId(); 
+            if (songid < 0 && path.toLowerCase().startsWith("http://")) {
+                // Once we can get album art and meta data from MediaPlayer, we
+                // can show that info again when streaming.
                 ((View) mArtistName.getParent()).setVisibility(View.INVISIBLE);
                 ((View) mAlbumName.getParent()).setVisibility(View.INVISIBLE);
                 mAlbum.setVisibility(View.GONE);
                 mTrackName.setText(path);
                 mAlbumArtHandler.removeMessages(GET_ALBUM_ART);
-                mAlbumArtHandler.obtainMessage(GET_ALBUM_ART, -1, 0).sendToTarget();
+                mAlbumArtHandler.obtainMessage(GET_ALBUM_ART, -1, -1).sendToTarget();
             } else {
                 ((View) mArtistName.getParent()).setVisibility(View.VISIBLE);
                 ((View) mAlbumName.getParent()).setVisibility(View.VISIBLE);
@@ -1244,7 +1247,7 @@
                 mAlbumName.setText(albumName);
                 mTrackName.setText(mService.getTrackName());
                 mAlbumArtHandler.removeMessages(GET_ALBUM_ART);
-                mAlbumArtHandler.obtainMessage(GET_ALBUM_ART, albumid, 0).sendToTarget();
+                mAlbumArtHandler.obtainMessage(GET_ALBUM_ART, albumid, songid).sendToTarget();
                 mAlbum.setVisibility(View.VISIBLE);
             }
             mDuration = mService.duration();
@@ -1263,14 +1266,15 @@
         public void handleMessage(Message msg)
         {
             int albumid = msg.arg1;
+            int songid = msg.arg2;
             if (msg.what == GET_ALBUM_ART && (mAlbumId != albumid || albumid < 0)) {
                 // while decoding the new image, show the default album art
                 Message numsg = mHandler.obtainMessage(ALBUM_ART_DECODED, null);
                 mHandler.removeMessages(ALBUM_ART_DECODED);
                 mHandler.sendMessageDelayed(numsg, 300);
-                Bitmap bm = MusicUtils.getArtwork(MediaPlaybackActivity.this, albumid);
+                Bitmap bm = MusicUtils.getArtwork(MediaPlaybackActivity.this, songid, albumid);
                 if (bm == null) {
-                    bm = MusicUtils.getArtwork(MediaPlaybackActivity.this, -1);
+                    bm = MusicUtils.getArtwork(MediaPlaybackActivity.this, songid, -1);
                     albumid = -1;
                 }
                 if (bm != null) {
diff --git a/src/com/android/music/MusicUtils.java b/src/com/android/music/MusicUtils.java
index ea20794..f46334a 100644
--- a/src/com/android/music/MusicUtils.java
+++ b/src/com/android/music/MusicUtils.java
@@ -16,21 +16,7 @@
 
 package com.android.music;
 
-import java.io.File;
-import java.io.FileDescriptor;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.util.Arrays;
-import java.util.Formatter;
-import java.util.HashMap;
-import java.util.Locale;
-
 import android.app.Activity;
-import android.app.ExpandableListActivity;
 import android.content.ComponentName;
 import android.content.ContentResolver;
 import android.content.ContentUris;
@@ -49,12 +35,10 @@
 import android.graphics.PixelFormat;
 import android.graphics.drawable.BitmapDrawable;
 import android.graphics.drawable.Drawable;
-import android.media.MediaFile;
-import android.media.MediaScanner;
 import android.net.Uri;
-import android.os.RemoteException;
 import android.os.Environment;
 import android.os.ParcelFileDescriptor;
+import android.os.RemoteException;
 import android.provider.MediaStore;
 import android.provider.Settings;
 import android.util.Log;
@@ -64,6 +48,16 @@
 import android.widget.TextView;
 import android.widget.Toast;
 
+import java.io.File;
+import java.io.FileDescriptor;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Arrays;
+import java.util.Formatter;
+import java.util.HashMap;
+import java.util.Locale;
+
 public class MusicUtils {
 
     private static final String TAG = "MusicUtils";
@@ -740,7 +734,6 @@
     }
     
     private static int sArtId = -2;
-    private static byte [] mCachedArt;
     private static Bitmap mCachedBit = null;
     private static final BitmapFactory.Options sBitmapOptionsCache = new BitmapFactory.Options();
     private static final BitmapFactory.Options sBitmapOptions = new BitmapFactory.Options();
@@ -865,27 +858,18 @@
     /** Get album art for specified album. You should not pass in the album id
      * for the "unknown" album here (use -1 instead)
      */
-    public static Bitmap getArtwork(Context context, int album_id) {
-        return getArtwork(context, album_id, true);
-    }
-    
-    /** Get album art for specified album. You should not pass in the album id
-     * for the "unknown" album here (use -1 instead)
-     */
-    public static Bitmap getArtwork(Context context, int album_id, boolean allowDefault) {
+    public static Bitmap getArtwork(Context context, int song_id, int album_id) {
 
         if (album_id < 0) {
             // This is something that is not in the database, so get the album art directly
             // from the file.
-            Bitmap bm = getArtworkFromFile(context, null, -1);
-            if (bm != null) {
-                return bm;
+            if (song_id >= 0) {
+                Bitmap bm = getArtworkFromFile(context, song_id, -1);
+                if (bm != null) {
+                    return bm;
+                }
             }
-            if (allowDefault) {
-                return getDefaultArtwork(context);
-            } else {
-                return null;
-            }
+            return getDefaultArtwork(context);
         }
 
         ContentResolver res = context.getContentResolver();
@@ -898,61 +882,16 @@
             } catch (FileNotFoundException ex) {
                 // The album art thumbnail does not actually exist. Maybe the user deleted it, or
                 // maybe it never existed to begin with.
-                Bitmap bm = getArtworkFromFile(context, null, album_id);
+                Bitmap bm = getArtworkFromFile(context, song_id, album_id);
                 if (bm != null) {
                     if (bm.getConfig() == null) {
                         bm = bm.copy(Bitmap.Config.RGB_565, false);
                         if (bm == null) {
-                            if (allowDefault) {
-                                return getDefaultArtwork(context);
-                            } else {
-                                return null;
-                            }
+                            return getDefaultArtwork(context);
                         }
                     }
-                    // Put the newly found artwork in the database.
-                    // Note that this shouldn't be done for the "unknown" album,
-                    // but if this method is called correctly, that won't happen.
-                    
-                    // first write it somewhere
-                    String file = Environment.getExternalStorageDirectory()
-                        + "/albumthumbs/" + String.valueOf(System.currentTimeMillis());
-                    if (ensureFileExists(file)) {
-                        try {
-                            OutputStream outstream = new FileOutputStream(file);
-                            boolean success = bm.compress(Bitmap.CompressFormat.JPEG, 75, outstream);
-                            outstream.close();
-                            if (success) {
-                                ContentValues values = new ContentValues();
-                                values.put("album_id", album_id);
-                                values.put("_data", file);
-                                Uri newuri = res.insert(sArtworkUri, values);
-                                if (newuri == null) {
-                                    // Failed to insert in to the database. The most likely
-                                    // cause of this is that the item already existed in the
-                                    // database, and the most likely cause of that is that
-                                    // the album was scanned before, but the user deleted the
-                                    // album art from the sd card.
-                                    // We can ignore that case here, since the media provider
-                                    // will regenerate the album art for those entries when
-                                    // it detects this.
-                                    success = false;
-                                }
-                            }
-                            if (!success) {
-                                File f = new File(file);
-                                f.delete();
-                            }
-                        } catch (FileNotFoundException e) {
-                            Log.e(TAG, "error creating file", e);
-                        } catch (IOException e) {
-                            Log.e(TAG, "error creating file", e);
-                        }
-                    }
-                } else if (allowDefault) {
-                    bm = getDefaultArtwork(context);
                 } else {
-                    bm = null;
+                    bm = getDefaultArtwork(context);
                 }
                 return bm;
             } finally {
@@ -967,168 +906,39 @@
         
         return null;
     }
-
-    // copied from MediaProvider
-    private static boolean ensureFileExists(String path) {
-        File file = new File(path);
-        if (file.exists()) {
-            return true;
-        } else {
-            // we will not attempt to create the first directory in the path
-            // (for example, do not create /sdcard if the SD card is not mounted)
-            int secondSlash = path.indexOf('/', 1);
-            if (secondSlash < 1) return false;
-            String directoryPath = path.substring(0, secondSlash);
-            File directory = new File(directoryPath);
-            if (!directory.exists())
-                return false;
-            file.getParentFile().mkdirs();
-            try {
-                return file.createNewFile();
-            } catch(IOException ioe) {
-                Log.d(TAG, "File creation failed for " + path);
-            }
-            return false;
-        }
-    }
     
     // get album art for specified file
     private static final String sExternalMediaUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI.toString();
-    private static Bitmap getArtworkFromFile(Context context, Uri uri, int albumid) {
+    private static Bitmap getArtworkFromFile(Context context, int songid, int albumid) {
         Bitmap bm = null;
         byte [] art = null;
         String path = null;
 
-        if (sArtId == albumid) {
-            //Log.i("@@@@@@ ", "reusing cached data", new Exception());
-            if (mCachedBit != null) {
-                return mCachedBit;
-            }
-            art = mCachedArt;
-        } else {
-            // try reading embedded artwork
-            if (uri == null) {
-                try {
-                    int curalbum = sService.getAlbumId();
-                    if (curalbum == albumid || albumid < 0) {
-                        path = sService.getPath();
-                        if (path != null) {
-                            uri = Uri.parse(path);
-                        }
-                    }
-                } catch (RemoteException ex) {
-                    return null;
-                } catch (NullPointerException ex) {
-                    return null;
-                }
-            }
-            if (uri == null) {
-                if (albumid >= 0) {
-                    Cursor c = query(context,MediaStore.Audio.Media.EXTERNAL_CONTENT_URI,
-                            new String[] { MediaStore.Audio.Media._ID, MediaStore.Audio.Media.ALBUM },
-                            MediaStore.Audio.Media.ALBUM_ID + "=?", new String [] {String.valueOf(albumid)},
-                            null);
-                    if (c != null) {
-                        if (c.moveToFirst()) {
-                            int trackid = c.getInt(0);
-                            uri = ContentUris.withAppendedId(
-                                    MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, trackid);
-                            if (MediaFile.UNKNOWN_STRING.equals(c.getString(1))) {
-                                albumid = -1;
-                            }
-                        }
-                        c.close();
-                    }
-                }
-            }
-            if (uri != null) {
-                MediaScanner scanner = new MediaScanner(context);
-                ParcelFileDescriptor pfd = null;
-                try {
-                    pfd = context.getContentResolver().openFileDescriptor(uri, "r");
-                    if (pfd != null) {
-                        FileDescriptor fd = pfd.getFileDescriptor();
-                        art = scanner.extractAlbumArt(fd);
-                    }
-                } catch (IOException ex) {
-                } catch (SecurityException ex) {
-                } finally {
-                    try {
-                        if (pfd != null) {
-                            pfd.close();
-                        }
-                    } catch (IOException ex) {
-                    }
-                }
-            }
+        if (albumid < 0 && songid < 0) {
+            throw new IllegalArgumentException("Must specify an album or a song id");
         }
-        // if no embedded art exists, look for AlbumArt.jpg in same directory as the media file
-        if (art == null && path != null) {
-            if (path.startsWith(sExternalMediaUri)) {
-                // get the real path
-                Cursor c = query(context,Uri.parse(path),
-                        new String[] { MediaStore.Audio.Media.DATA},
-                        null, null, null);
-                if (c != null) {
-                    c.moveToFirst();
-                    if (!c.isAfterLast()) {
-                        path = c.getString(0);
-                    }
-                    c.close();
+
+        try {
+            if (albumid < 0) {
+                Uri uri = Uri.parse("content://media/external/audio/media/" + songid + "/albumart");
+                ParcelFileDescriptor pfd = context.getContentResolver().openFileDescriptor(uri, "r");
+                if (pfd != null) {
+                    FileDescriptor fd = pfd.getFileDescriptor();
+                    bm = BitmapFactory.decodeFileDescriptor(fd);
+                }
+            } else {
+                Uri uri = ContentUris.withAppendedId(sArtworkUri, albumid);
+                ParcelFileDescriptor pfd = context.getContentResolver().openFileDescriptor(uri, "r");
+                if (pfd != null) {
+                    FileDescriptor fd = pfd.getFileDescriptor();
+                    bm = BitmapFactory.decodeFileDescriptor(fd);
                 }
             }
-            int lastSlash = path.lastIndexOf('/');
-            if (lastSlash > 0) {
-                String artPath = path.substring(0, lastSlash + 1) + "AlbumArt.jpg";
-                File file = new File(artPath);
-                if (file.exists()) {
-                    art = new byte[(int)file.length()];
-                    FileInputStream stream = null;
-                    try {
-                        stream = new FileInputStream(file);
-                        stream.read(art);
-                    } catch (IOException ex) {
-                        art = null;
-                    } finally {
-                        try {
-                            if (stream != null) {
-                                stream.close();
-                            }
-                        } catch (IOException ex) {
-                        }
-                    }
-                } else {
-                    // TODO: try getting album art from the web
-                }
-            }
+        } catch (FileNotFoundException ex) {
+            //
         }
-        
-        if (art != null) {
-            try {
-                // get the size of the bitmap
-                BitmapFactory.Options opts = new BitmapFactory.Options();
-                opts.inJustDecodeBounds = true;
-                opts.inSampleSize = 1;
-                BitmapFactory.decodeByteArray(art, 0, art.length, opts);
-                
-                // request a reasonably sized output image
-                // TODO: don't hardcode the size
-                while (opts.outHeight > 320 || opts.outWidth > 320) {
-                    opts.outHeight /= 2;
-                    opts.outWidth /= 2;
-                    opts.inSampleSize *= 2;
-                }
-                
-                // get the image for real now
-                opts.inJustDecodeBounds = false;
-                bm = BitmapFactory.decodeByteArray(art, 0, art.length, opts);
-                if (albumid != -1) {
-                    sArtId = albumid;
-                }
-                mCachedArt = art;
-                mCachedBit = bm;
-            } catch (Exception e) {
-            }
+        if (bm != null) {
+            mCachedBit = bm;
         }
         return bm;
     }