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 5444ee9..2413092 100644 (file)
@@ -20,6 +20,7 @@ import android.app.Notification;
 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;
@@ -32,6 +33,7 @@ import android.content.SharedPreferences.Editor;
 import android.database.Cursor;
 import android.database.sqlite.SQLiteException;
 import android.media.AudioManager;
+import android.media.AudioManager.OnAudioFocusChangeListener;
 import android.media.MediaPlayer;
 import android.net.Uri;
 import android.os.Handler;
@@ -47,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;
@@ -136,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.
@@ -181,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()) {
@@ -234,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)) {
@@ -258,12 +267,49 @@ 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 = MusicUtils.getCardId(this);
@@ -305,6 +351,9 @@ public class MediaPlaybackService extends Service {
         // 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);
@@ -568,6 +617,7 @@ public class MediaPlaybackService extends Service {
         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);
@@ -1032,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();
@@ -1725,6 +1780,7 @@ public class MediaPlaybackService extends Service {
         }
 
         public void start() {
+            MusicUtils.debugLog(new Exception("MultiPlayer.start called"));
             mMediaPlayer.start();
         }
 
@@ -1916,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);
 }