Do not merge.
Fix audio focus issue some more. We now start playing immediately when
regaining focus, and set all the associated state variables accordingly,
so that very rapid focus loss/gain changes can be handled correctly.
b/3209106

Change-Id: I89cb08511728d6e5adecb8b90323c6a22259d590
diff --git a/src/com/android/music/MediaPlaybackService.java b/src/com/android/music/MediaPlaybackService.java
index 8411fc0..9b1fd58 100644
--- a/src/com/android/music/MediaPlaybackService.java
+++ b/src/com/android/music/MediaPlaybackService.java
@@ -98,6 +98,7 @@
     private static final int RELEASE_WAKELOCK = 2;
     private static final int SERVER_DIED = 3;
     private static final int FADEIN = 4;
+    private static final int FOCUSCHANGE = 5;
     private static final int MAX_HISTORY_SIZE = 100;
     
     private MultiPlayer mPlayer;
@@ -150,10 +151,6 @@
     // interval after which we stop the service when idle
     private static final int IDLE_DELAY = 60000;
     
-    private void startAndFadeIn() {
-        mMediaplayerHandler.sendEmptyMessageDelayed(FADEIN, 10);
-    }
-    
     private Handler mMediaplayerHandler = new Handler() {
         float mCurrentVolume = 1.0f;
         @Override
@@ -161,20 +158,13 @@
             MusicUtils.debugLog("mMediaplayerHandler.handleMessage " + msg.what);
             switch (msg.what) {
                 case FADEIN:
-                    if (!isPlaying()) {
-                        mCurrentVolume = 0f;
-                        mPlayer.setVolume(mCurrentVolume);
-                        play();
+                    mCurrentVolume += 0.01f;
+                    if (mCurrentVolume < 1.0f) {
                         mMediaplayerHandler.sendEmptyMessageDelayed(FADEIN, 10);
                     } else {
-                        mCurrentVolume += 0.01f;
-                        if (mCurrentVolume < 1.0f) {
-                            mMediaplayerHandler.sendEmptyMessageDelayed(FADEIN, 10);
-                        } else {
-                            mCurrentVolume = 1.0f;
-                        }
-                        mPlayer.setVolume(mCurrentVolume);
+                        mCurrentVolume = 1.0f;
                     }
+                    mPlayer.setVolume(mCurrentVolume);
                     break;
                 case SERVER_DIED:
                     if (mIsSupposedToBePlaying) {
@@ -198,6 +188,41 @@
                 case RELEASE_WAKELOCK:
                     mWakeLock.release();
                     break;
+
+                case FOCUSCHANGE:
+                    // This code is here so we can better synchronize it with the code that
+                    // handles fade-in
+                    // AudioFocus is a new feature: focus updates are made verbose on purpose
+                    switch (msg.arg1) {
+                        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;
+                                mCurrentVolume = 0f;
+                                mPlayer.setVolume(mCurrentVolume);
+                                play(); // also queues a fade-in
+                            }
+                            break;
+                        default:
+                            Log.e(LOGTAG, "Unknown audio focus change code");
+                    }
+                    break;
+
                 default:
                     break;
             }
@@ -239,33 +264,7 @@
 
     private OnAudioFocusChangeListener mAudioFocusListener = new OnAudioFocusChangeListener() {
         public void onAudioFocusChange(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;
-                        startAndFadeIn();
-                    }
-                    break;
-                default:
-                    Log.e(LOGTAG, "Unknown audio focus change code");
-            }
+            mMediaplayerHandler.obtainMessage(FOCUSCHANGE, focusChange, 0).sendToTarget();
         }
     };
 
@@ -1047,6 +1046,9 @@
             }
 
             mPlayer.start();
+            // make sure we fade in, in case a previous fadein was stopped because
+            // of another focus loss
+            mMediaplayerHandler.sendEmptyMessage(FADEIN);
 
             RemoteViews views = new RemoteViews(getPackageName(), R.layout.statusbar);
             views.setImageViewResource(R.id.icon, R.drawable.stat_notify_musicplayer);
@@ -1122,8 +1124,8 @@
      */
     public void pause() {
         synchronized(this) {
+            mMediaplayerHandler.removeMessages(FADEIN);
             if (isPlaying()) {
-                mMediaplayerHandler.removeMessages(FADEIN);
                 mPlayer.pause();
                 gotoIdleState();
                 mIsSupposedToBePlaying = false;