OSDN Git Service

Update the Music app to use the remote control focus API.
[android-x86/packages-apps-Music.git] / src / com / android / music / MediaPlaybackService.java
index 23ca124..2413092 100644 (file)
 package com.android.music;
 
 import android.app.Notification;
-import android.app.NotificationManager;
 import android.app.PendingIntent;
 import android.app.Service;
 import android.appwidget.AppWidgetManager;
+import android.content.ComponentName;
 import android.content.ContentResolver;
 import android.content.ContentUris;
 import android.content.ContentValues;
@@ -33,11 +33,9 @@ import android.content.SharedPreferences.Editor;
 import android.database.Cursor;
 import android.database.sqlite.SQLiteException;
 import android.media.AudioManager;
-import android.media.MediaFile;
+import android.media.AudioManager.OnAudioFocusChangeListener;
 import android.media.MediaPlayer;
 import android.net.Uri;
-import android.os.Environment;
-import android.os.FileUtils;
 import android.os.Handler;
 import android.os.IBinder;
 import android.os.Message;
@@ -51,7 +49,9 @@ import android.util.Log;
 import android.widget.RemoteViews;
 import android.widget.Toast;
 
+import java.io.FileDescriptor;
 import java.io.IOException;
+import java.io.PrintWriter;
 import java.lang.ref.WeakReference;
 import java.util.Random;
 import java.util.Vector;
@@ -101,16 +101,16 @@ public class MediaPlaybackService extends Service {
     private static final int RELEASE_WAKELOCK = 2;
     private static final int SERVER_DIED = 3;
     private static final int FADEIN = 4;
-    private static final int MAX_HISTORY_SIZE = 10;
+    private static final int MAX_HISTORY_SIZE = 100;
     
     private MultiPlayer mPlayer;
     private String mFileToPlay;
     private int mShuffleMode = SHUFFLE_NONE;
     private int mRepeatMode = REPEAT_NONE;
     private int mMediaMountedCount = 0;
-    private int [] mAutoShuffleList = null;
+    private long [] mAutoShuffleList = null;
     private boolean mOneShot;
-    private int [] mPlayList = null;
+    private long [] mPlayList = null;
     private int mPlayListLen = 0;
     private Vector<Integer> mHistory = new Vector<Integer>(MAX_HISTORY_SIZE);
     private Cursor mCursor;
@@ -140,7 +140,10 @@ public class MediaPlaybackService extends Service {
     private boolean mResumeAfterCall = false;
     private boolean mIsSupposedToBePlaying = false;
     private boolean mQuietMode = false;
-    
+    private AudioManager mAudioManager;
+    // used to track what type of audio focus loss caused the playback to pause
+    private boolean mPausedByTransientLossOfFocus = false;
+
     private SharedPreferences mPreferences;
     // We use this to distinguish between different cards when saving/restoring playlists.
     // This will have to change if we want to support multiple simultaneous cards.
@@ -185,6 +188,7 @@ public class MediaPlaybackService extends Service {
         float mCurrentVolume = 1.0f;
         @Override
         public void handleMessage(Message msg) {
+            MusicUtils.debugLog("mMediaplayerHandler.handleMessage " + msg.what);
             switch (msg.what) {
                 case FADEIN:
                     if (!isPlaying()) {
@@ -238,6 +242,7 @@ public class MediaPlaybackService extends Service {
         public void onReceive(Context context, Intent intent) {
             String action = intent.getAction();
             String cmd = intent.getStringExtra("command");
+            MusicUtils.debugLog("mIntentReceiver.onReceive " + action + " / " + cmd);
             if (CMDNEXT.equals(cmd) || NEXT_ACTION.equals(action)) {
                 next(true);
             } else if (CMDPREVIOUS.equals(cmd) || PREVIOUS_ACTION.equals(action)) {
@@ -262,15 +267,52 @@ public class MediaPlaybackService extends Service {
         }
     };
 
+    private OnAudioFocusChangeListener mAudioFocusListener = new OnAudioFocusChangeListener() {
+        public void onAudioFocusChanged(int focusChange) {
+            // AudioFocus is a new feature: focus updates are made verbose on purpose
+            switch (focusChange) {
+                case AudioManager.AUDIOFOCUS_LOSS:
+                    Log.v(LOGTAG, "AudioFocus: received AUDIOFOCUS_LOSS");
+                    if(isPlaying()) {
+                        mPausedByTransientLossOfFocus = false;
+                        pause();
+                    }
+                    break;
+                case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT:
+                case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK:
+                    Log.v(LOGTAG, "AudioFocus: received AUDIOFOCUS_LOSS_TRANSIENT");
+                    if(isPlaying()) {
+                        mPausedByTransientLossOfFocus = true;
+                        pause();
+                    }
+                    break;
+                case AudioManager.AUDIOFOCUS_GAIN:
+                    Log.v(LOGTAG, "AudioFocus: received AUDIOFOCUS_GAIN");
+                    if(!isPlaying() && mPausedByTransientLossOfFocus) {
+                        mPausedByTransientLossOfFocus = false;
+                        play();
+                    }
+                    break;
+                default:
+                    Log.e(LOGTAG, "Unknown audio focus change code");
+            }
+        }
+    };
+
     public MediaPlaybackService() {
     }
 
     @Override
     public void onCreate() {
         super.onCreate();
+
+        mAudioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
+        mAudioManager.registerAudioFocusListener(mAudioFocusListener);
+        mAudioManager.registerMediaButtonEventReceiver(new ComponentName(getPackageName(),
+                MediaButtonIntentReceiver.class.getName()));
         
         mPreferences = getSharedPreferences("Music", MODE_WORLD_READABLE | MODE_WORLD_WRITEABLE);
-        mCardId = FileUtils.getFatVolumeId(Environment.getExternalStorageDirectory().getPath());
+        mCardId = MusicUtils.getCardId(this);
         
         registerExternalStorageListener();
 
@@ -278,10 +320,6 @@ public class MediaPlaybackService extends Service {
         mPlayer = new MultiPlayer();
         mPlayer.setHandler(mMediaplayerHandler);
 
-        // Clear leftover notification in case this service previously got killed while playing
-        NotificationManager nm = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
-        nm.cancel(PLAYBACKSERVICE_STATUS);
-        
         reloadQueue();
         
         IntentFilter commandFilter = new IntentFilter();
@@ -308,11 +346,14 @@ public class MediaPlaybackService extends Service {
     public void onDestroy() {
         // Check that we're not being destroyed while something is still playing.
         if (isPlaying()) {
-            Log.e("MediaPlaybackService", "Service being destroyed while still playing.");
+            Log.e(LOGTAG, "Service being destroyed while still playing.");
         }
         // release all MediaPlayer resources, including the native player and wakelocks
         mPlayer.release();
         mPlayer = null;
+
+        mAudioManager.abandonAudioFocus(mAudioFocusListener);
+        mAudioManager.unregisterAudioFocusListener(mAudioFocusListener);
         
         // make sure there aren't any other messages coming
         mDelayedStopHandler.removeCallbacksAndMessages(null);
@@ -359,12 +400,12 @@ public class MediaPlaybackService extends Service {
             // on the phone)
             int len = mPlayListLen;
             for (int i = 0; i < len; i++) {
-                int n = mPlayList[i];
+                long n = mPlayList[i];
                 if (n == 0) {
                     q.append("0;");
                 } else {
                     while (n != 0) {
-                        int digit = n & 0xf;
+                        int digit = (int)(n & 0xf);
                         n >>= 4;
                         q.append(hexdigits[digit]);
                     }
@@ -374,6 +415,25 @@ public class MediaPlaybackService extends Service {
             //Log.i("@@@@ service", "created queue string in " + (System.currentTimeMillis() - start) + " ms");
             ed.putString("queue", q.toString());
             ed.putInt("cardid", mCardId);
+            if (mShuffleMode != SHUFFLE_NONE) {
+                // In shuffle mode we need to save the history too
+                len = mHistory.size();
+                q.setLength(0);
+                for (int i = 0; i < len; i++) {
+                    int n = mHistory.get(i);
+                    if (n == 0) {
+                        q.append("0;");
+                    } else {
+                        while (n != 0) {
+                            int digit = (n & 0xf);
+                            n >>= 4;
+                            q.append(hexdigits[digit]);
+                        }
+                        q.append(";");
+                    }
+                }
+                ed.putString("history", q.toString());
+            }
         }
         ed.putInt("curpos", mPlayPos);
         if (mPlayer.isInitialized()) {
@@ -442,18 +502,18 @@ public class MediaPlaybackService extends Service {
             // To deal with this, try querying for the current file, and if
             // that fails, wait a while and try again. If that too fails,
             // assume there is a problem and don't restore the state.
-            Cursor c = MusicUtils.query(this,
+            Cursor crsr = MusicUtils.query(this,
                         MediaStore.Audio.Media.EXTERNAL_CONTENT_URI,
                         new String [] {"_id"}, "_id=" + mPlayList[mPlayPos] , null, null);
-            if (c == null || c.getCount() == 0) {
+            if (crsr == null || crsr.getCount() == 0) {
                 // wait a bit and try again
                 SystemClock.sleep(3000);
-                c = getContentResolver().query(
+                crsr = getContentResolver().query(
                         MediaStore.Audio.Media.EXTERNAL_CONTENT_URI,
                         mCursorCols, "_id=" + mPlayList[mPlayPos] , null, null);
             }
-            if (c != null) {
-                c.close();
+            if (crsr != null) {
+                crsr.close();
             }
 
             // Make sure we don't auto-skip to the next song, since that
@@ -478,6 +538,9 @@ public class MediaPlaybackService extends Service {
             
             long seekpos = mPreferences.getLong("seekpos", 0);
             seek(seekpos >= 0 && seekpos < duration() ? seekpos : 0);
+            Log.d(LOGTAG, "restored queue, currently at position "
+                    + position() + "/" + duration()
+                    + " (requested " + seekpos + ")");
             
             int repmode = mPreferences.getInt("repeatmode", REPEAT_NONE);
             if (repmode != REPEAT_ALL && repmode != REPEAT_CURRENT) {
@@ -489,6 +552,41 @@ public class MediaPlaybackService extends Service {
             if (shufmode != SHUFFLE_AUTO && shufmode != SHUFFLE_NORMAL) {
                 shufmode = SHUFFLE_NONE;
             }
+            if (shufmode != SHUFFLE_NONE) {
+                // in shuffle mode we need to restore the history too
+                q = mPreferences.getString("history", "");
+                qlen = q != null ? q.length() : 0;
+                if (qlen > 1) {
+                    plen = 0;
+                    n = 0;
+                    shift = 0;
+                    mHistory.clear();
+                    for (int i = 0; i < qlen; i++) {
+                        char c = q.charAt(i);
+                        if (c == ';') {
+                            if (n >= mPlayListLen) {
+                                // bogus history data
+                                mHistory.clear();
+                                break;
+                            }
+                            mHistory.add(n);
+                            n = 0;
+                            shift = 0;
+                        } else {
+                            if (c >= '0' && c <= '9') {
+                                n += ((c - '0') << shift);
+                            } else if (c >= 'a' && c <= 'f') {
+                                n += ((10 + c - 'a') << shift);
+                            } else {
+                                // bogus history data
+                                mHistory.clear();
+                                break;
+                            }
+                            shift += 4;
+                        }
+                    }
+                }
+            }
             if (shufmode == SHUFFLE_AUTO) {
                 if (! makeAutoShuffleList()) {
                     shufmode = SHUFFLE_NONE;
@@ -512,28 +610,36 @@ public class MediaPlaybackService extends Service {
     }
 
     @Override
-    public void onStart(Intent intent, int startId) {
+    public int onStartCommand(Intent intent, int flags, int startId) {
         mServiceStartId = startId;
         mDelayedStopHandler.removeCallbacksAndMessages(null);
-        
-        String action = intent.getAction();
-        String cmd = intent.getStringExtra("command");
-        
-        if (CMDNEXT.equals(cmd) || NEXT_ACTION.equals(action)) {
-            next(true);
-        } else if (CMDPREVIOUS.equals(cmd) || PREVIOUS_ACTION.equals(action)) {
-            prev();
-        } else if (CMDTOGGLEPAUSE.equals(cmd) || TOGGLEPAUSE_ACTION.equals(action)) {
-            if (isPlaying()) {
+
+        if (intent != null) {
+            String action = intent.getAction();
+            String cmd = intent.getStringExtra("command");
+            MusicUtils.debugLog("onStartCommand " + action + " / " + cmd);
+
+            if (CMDNEXT.equals(cmd) || NEXT_ACTION.equals(action)) {
+                next(true);
+            } else if (CMDPREVIOUS.equals(cmd) || PREVIOUS_ACTION.equals(action)) {
+                if (position() < 2000) {
+                    prev();
+                } else {
+                    seek(0);
+                    play();
+                }
+            } else if (CMDTOGGLEPAUSE.equals(cmd) || TOGGLEPAUSE_ACTION.equals(action)) {
+                if (isPlaying()) {
+                    pause();
+                } else {
+                    play();
+                }
+            } else if (CMDPAUSE.equals(cmd) || PAUSE_ACTION.equals(action)) {
                 pause();
-            } else {
-                play();
+            } else if (CMDSTOP.equals(cmd)) {
+                pause();
+                seek(0);
             }
-        } else if (CMDPAUSE.equals(cmd) || PAUSE_ACTION.equals(action)) {
-            pause();
-        } else if (CMDSTOP.equals(cmd)) {
-            pause();
-            seek(0);
         }
         
         // make sure the service will shut down on its own if it was
@@ -541,6 +647,7 @@ public class MediaPlaybackService extends Service {
         mDelayedStopHandler.removeCallbacksAndMessages(null);
         Message msg = mDelayedStopHandler.obtainMessage();
         mDelayedStopHandler.sendMessageDelayed(msg, IDLE_DELAY);
+        return START_STICKY;
     }
     
     @Override
@@ -617,7 +724,7 @@ public class MediaPlaybackService extends Service {
                         closeExternalStorageFiles(intent.getData().getPath());
                     } else if (action.equals(Intent.ACTION_MEDIA_MOUNTED)) {
                         mMediaMountedCount++;
-                        mCardId = FileUtils.getFatVolumeId(intent.getData().getPath());
+                        mCardId = MusicUtils.getCardId(MediaPlaybackService.this);
                         reloadQueue();
                         notifyChange(QUEUE_CHANGED);
                         notifyChange(META_CHANGED);
@@ -654,7 +761,7 @@ public class MediaPlaybackService extends Service {
     private void notifyChange(String what) {
         
         Intent i = new Intent(what);
-        i.putExtra("id", Integer.valueOf(getAudioId()));
+        i.putExtra("id", Long.valueOf(getAudioId()));
         i.putExtra("artist", getArtistName());
         i.putExtra("album",getAlbumName());
         i.putExtra("track", getTrackName());
@@ -675,7 +782,7 @@ public class MediaPlaybackService extends Service {
             // reallocate at 2x requested size so we don't
             // need to grow and copy the array for every
             // insert
-            int [] newlist = new int[size * 2];
+            long [] newlist = new long[size * 2];
             int len = mPlayList != null ? mPlayList.length : mPlayListLen;
             for (int i = 0; i < len; i++) {
                 newlist[i] = mPlayList[i];
@@ -687,7 +794,7 @@ public class MediaPlaybackService extends Service {
     }
     
     // insert the list of songs at the specified position in the playlist
-    private void addToPlayList(int [] list, int position) {
+    private void addToPlayList(long [] list, int position) {
         int addlen = list.length;
         if (position < 0) { // overwrite
             mPlayListLen = 0;
@@ -720,7 +827,7 @@ public class MediaPlaybackService extends Service {
      * @param list The list of tracks to append.
      * @param action NOW, NEXT or LAST
      */
-    public void enqueue(int [] list, int action) {
+    public void enqueue(long [] list, int action) {
         synchronized(this) {
             if (action == NEXT && mPlayPos + 1 < mPlayListLen) {
                 addToPlayList(list, mPlayPos + 1);
@@ -753,12 +860,12 @@ public class MediaPlaybackService extends Service {
      * specified position is 0.
      * @param list The new list of tracks.
      */
-    public void open(int [] list, int position) {
+    public void open(long [] list, int position) {
         synchronized (this) {
             if (mShuffleMode == SHUFFLE_AUTO) {
                 mShuffleMode = SHUFFLE_NORMAL;
             }
-            int oldId = getAudioId();
+            long oldId = getAudioId();
             int listlength = list.length;
             boolean newlist = true;
             if (mPlayListLen == listlength) {
@@ -805,7 +912,7 @@ public class MediaPlaybackService extends Service {
                 index2 = mPlayListLen - 1;
             }
             if (index1 < index2) {
-                int tmp = mPlayList[index1];
+                long tmp = mPlayList[index1];
                 for (int i = index1; i < index2; i++) {
                     mPlayList[i] = mPlayList[i+1];
                 }
@@ -816,7 +923,7 @@ public class MediaPlaybackService extends Service {
                         mPlayPos--;
                 }
             } else if (index2 < index1) {
-                int tmp = mPlayList[index1];
+                long tmp = mPlayList[index1];
                 for (int i = index1; i > index2; i--) {
                     mPlayList[i] = mPlayList[i-1];
                 }
@@ -835,10 +942,10 @@ public class MediaPlaybackService extends Service {
      * Returns the current play list
      * @return An array of integers containing the IDs of the tracks in the play list
      */
-    public int [] getQueue() {
+    public long [] getQueue() {
         synchronized (this) {
             int len = mPlayListLen;
-            int [] list = new int[len];
+            long [] list = new long[len];
             for (int i = 0; i < len; i++) {
                 list[i] = mPlayList[i];
             }
@@ -941,7 +1048,7 @@ public class MediaPlaybackService extends Service {
                             mCursor.moveToNext();
                             ensurePlayListCapacity(1);
                             mPlayListLen = 1;
-                            mPlayList[0] = mCursor.getInt(IDCOLIDX);
+                            mPlayList[0] = mCursor.getLong(IDCOLIDX);
                             mPlayPos = 0;
                         }
                     }
@@ -963,6 +1070,7 @@ public class MediaPlaybackService extends Service {
                     if (!mQuietMode) {
                         Toast.makeText(this, R.string.playback_failed, Toast.LENGTH_SHORT).show();
                     }
+                    Log.d(LOGTAG, "Failed to open file for playback");
                 }
             } else {
                 mOpenFailedCounter = 0;
@@ -974,6 +1082,11 @@ public class MediaPlaybackService extends Service {
      * Starts playback of a previously opened file.
      */
     public void play() {
+        mAudioManager.requestAudioFocus(mAudioFocusListener, AudioManager.STREAM_MUSIC,
+                AudioManager.AUDIOFOCUS_GAIN);
+        mAudioManager.registerMediaButtonEventReceiver(new ComponentName(this.getPackageName(),
+                MediaButtonIntentReceiver.class.getName()));
+
         if (mPlayer.isInitialized()) {
             // if we are at the end of the song, go to the next song first
             long duration = mPlayer.duration();
@@ -983,11 +1096,7 @@ public class MediaPlaybackService extends Service {
             }
 
             mPlayer.start();
-            setForeground(true);
 
-            NotificationManager nm = (NotificationManager)
-            getSystemService(Context.NOTIFICATION_SERVICE);
-    
             RemoteViews views = new RemoteViews(getPackageName(), R.layout.statusbar);
             views.setImageViewResource(R.id.icon, R.drawable.stat_notify_musicplayer);
             if (getAudioId() < 0) {
@@ -997,11 +1106,11 @@ public class MediaPlaybackService extends Service {
             } else {
                 String artist = getArtistName();
                 views.setTextViewText(R.id.trackname, getTrackName());
-                if (artist == null || artist.equals(MediaFile.UNKNOWN_STRING)) {
+                if (artist == null || artist.equals(MediaStore.UNKNOWN_STRING)) {
                     artist = getString(R.string.unknown_artist_name);
                 }
                 String album = getAlbumName();
-                if (album == null || album.equals(MediaFile.UNKNOWN_STRING)) {
+                if (album == null || album.equals(MediaStore.UNKNOWN_STRING)) {
                     album = getString(R.string.unknown_album_name);
                 }
                 
@@ -1015,12 +1124,14 @@ public class MediaPlaybackService extends Service {
             status.flags |= Notification.FLAG_ONGOING_EVENT;
             status.icon = R.drawable.stat_notify_musicplayer;
             status.contentIntent = PendingIntent.getActivity(this, 0,
-                    new Intent("com.android.music.PLAYBACK_VIEWER"), 0);
-            nm.notify(PLAYBACKSERVICE_STATUS, status);
+                    new Intent("com.android.music.PLAYBACK_VIEWER")
+                    .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK), 0);
+            startForeground(PLAYBACKSERVICE_STATUS, status);
             if (!mIsSupposedToBePlaying) {
+                mIsSupposedToBePlaying = true;
                 notifyChange(PLAYSTATE_CHANGED);
             }
-            mIsSupposedToBePlaying = true;
+
         } else if (mPlayListLen <= 0) {
             // This is mostly so that if you press 'play' on a bluetooth headset
             // without every having played anything before, it will still play
@@ -1040,8 +1151,9 @@ public class MediaPlaybackService extends Service {
         }
         if (remove_status_icon) {
             gotoIdleState();
+        } else {
+            stopForeground(false);
         }
-        setForeground(false);
         if (remove_status_icon) {
             mIsSupposedToBePlaying = false;
         }
@@ -1062,7 +1174,6 @@ public class MediaPlaybackService extends Service {
             if (isPlaying()) {
                 mPlayer.pause();
                 gotoIdleState();
-                setForeground(false);
                 mIsSupposedToBePlaying = false;
                 notifyChange(PLAYSTATE_CHANGED);
                 saveBookmarkIfNeeded();
@@ -1145,6 +1256,7 @@ public class MediaPlaybackService extends Service {
             }
 
             if (mPlayListLen <= 0) {
+                Log.d(LOGTAG, "No play queue");
                 return;
             }
 
@@ -1191,6 +1303,10 @@ public class MediaPlaybackService extends Service {
                     } else {
                         // all done
                         gotoIdleState();
+                        if (mIsSupposedToBePlaying) {
+                            mIsSupposedToBePlaying = false;
+                            notifyChange(PLAYSTATE_CHANGED);
+                        }
                         return;
                     }
                 }
@@ -1233,12 +1349,10 @@ public class MediaPlaybackService extends Service {
     }
     
     private void gotoIdleState() {
-        NotificationManager nm =
-            (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
-        nm.cancel(PLAYBACKSERVICE_STATUS);
         mDelayedStopHandler.removeCallbacksAndMessages(null);
         Message msg = mDelayedStopHandler.obtainMessage();
         mDelayedStopHandler.sendMessageDelayed(msg, IDLE_DELAY);
+        stopForeground(true);
     }
     
     private void saveBookmarkIfNeeded() {
@@ -1283,7 +1397,7 @@ public class MediaPlaybackService extends Service {
         for (int i = 0; i < to_add; i++) {
             // pick something at random from the list
             int idx = mRand.nextInt(mAutoShuffleList.length);
-            Integer which = mAutoShuffleList[idx];
+            long which = mAutoShuffleList[idx];
             ensurePlayListCapacity(mPlayListLen + 1);
             mPlayList[mPlayListLen++] = which;
             notify = true;
@@ -1320,10 +1434,10 @@ public class MediaPlaybackService extends Service {
                 return false;
             }
             int len = c.getCount();
-            int[] list = new int[len];
+            long [] list = new long[len];
             for (int i = 0; i < len; i++) {
                 c.moveToNext();
-                list[i] = c.getInt(0);
+                list[i] = c.getLong(0);
             }
             mAutoShuffleList = list;
             return true;
@@ -1397,7 +1511,7 @@ public class MediaPlaybackService extends Service {
      * @param id The id to be removed
      * @return how many instances of the track were removed
      */
-    public int removeTrack(int id) {
+    public int removeTrack(long id) {
         int numremoved = 0;
         synchronized (this) {
             for (int i = 0; i < mPlayListLen; i++) {
@@ -1466,7 +1580,7 @@ public class MediaPlaybackService extends Service {
      * Returns the rowid of the currently playing file, or -1 if
      * no file is currently playing.
      */
-    public int getAudioId() {
+    public long getAudioId() {
         synchronized (this) {
             if (mPlayPos >= 0 && mPlayer.isInitialized()) {
                 return mPlayList[mPlayPos];
@@ -1496,6 +1610,9 @@ public class MediaPlaybackService extends Service {
             openCurrent();
             play();
             notifyChange(META_CHANGED);
+            if (mShuffleMode == SHUFFLE_AUTO) {
+                doAutoShuffleUpdate();
+            }
         }
     }
 
@@ -1508,12 +1625,12 @@ public class MediaPlaybackService extends Service {
         }
     }
     
-    public int getArtistId() {
+    public long getArtistId() {
         synchronized (this) {
             if (mCursor == null) {
                 return -1;
             }
-            return mCursor.getInt(mCursor.getColumnIndexOrThrow(MediaStore.Audio.Media.ARTIST_ID));
+            return mCursor.getLong(mCursor.getColumnIndexOrThrow(MediaStore.Audio.Media.ARTIST_ID));
         }
     }
 
@@ -1526,12 +1643,12 @@ public class MediaPlaybackService extends Service {
         }
     }
 
-    public int getAlbumId() {
+    public long getAlbumId() {
         synchronized (this) {
             if (mCursor == null) {
                 return -1;
             }
-            return mCursor.getInt(mCursor.getColumnIndexOrThrow(MediaStore.Audio.Media.ALBUM_ID));
+            return mCursor.getLong(mCursor.getColumnIndexOrThrow(MediaStore.Audio.Media.ALBUM_ID));
         }
     }
 
@@ -1663,6 +1780,7 @@ public class MediaPlaybackService extends Service {
         }
 
         public void start() {
+            MusicUtils.debugLog(new Exception("MultiPlayer.start called"));
             mMediaPlayer.start();
         }
 
@@ -1720,6 +1838,7 @@ public class MediaPlaybackService extends Service {
                     mHandler.sendMessageDelayed(mHandler.obtainMessage(SERVER_DIED), 2000);
                     return true;
                 default:
+                    Log.d("MultiPlayer", "Error: " + what + "," + extra);
                     break;
                 }
                 return false;
@@ -1764,7 +1883,7 @@ public class MediaPlaybackService extends Service {
         {
             mService.get().open(path, oneShot);
         }
-        public void open(int [] list, int position) {
+        public void open(long [] list, int position) {
             mService.get().open(list, position);
         }
         public int getQueuePosition() {
@@ -1797,19 +1916,19 @@ public class MediaPlaybackService extends Service {
         public String getAlbumName() {
             return mService.get().getAlbumName();
         }
-        public int getAlbumId() {
+        public long getAlbumId() {
             return mService.get().getAlbumId();
         }
         public String getArtistName() {
             return mService.get().getArtistName();
         }
-        public int getArtistId() {
+        public long getArtistId() {
             return mService.get().getArtistId();
         }
-        public void enqueue(int [] list , int action) {
+        public void enqueue(long [] list , int action) {
             mService.get().enqueue(list, action);
         }
-        public int [] getQueue() {
+        public long [] getQueue() {
             return mService.get().getQueue();
         }
         public void moveQueueItem(int from, int to) {
@@ -1818,7 +1937,7 @@ public class MediaPlaybackService extends Service {
         public String getPath() {
             return mService.get().getPath();
         }
-        public int getAudioId() {
+        public long getAudioId() {
             return mService.get().getAudioId();
         }
         public long position() {
@@ -1839,7 +1958,7 @@ public class MediaPlaybackService extends Service {
         public int removeTracks(int first, int last) {
             return mService.get().removeTracks(first, last);
         }
-        public int removeTrack(int id) {
+        public int removeTrack(long id) {
             return mService.get().removeTrack(id);
         }
         public void setRepeatMode(int repeatmode) {
@@ -1853,6 +1972,20 @@ public class MediaPlaybackService extends Service {
         }
 
     }
-    
+
+    @Override
+    protected void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
+        writer.println("" + mPlayListLen + " items in queue, currently at index " + mPlayPos);
+        writer.println("Currently loaded:");
+        writer.println(getArtistName());
+        writer.println(getAlbumName());
+        writer.println(getTrackName());
+        writer.println(getPath());
+        writer.println("playing: " + mIsSupposedToBePlaying);
+        writer.println("actual: " + mPlayer.mMediaPlayer.isPlaying());
+        writer.println("shuffle mode: " + mShuffleMode);
+        MusicUtils.debugDump(writer);
+    }
+
     private final IBinder mBinder = new ServiceStub(this);
 }