TransportMediator: handle playback position.

Update interaction with media controller to report playback
position and handle requests to set the position.  Also
update api to use longs for position everywhere.

Change-Id: Ia960cc0443b07b70503d2e08d4943fd5102b809d
diff --git a/v4/java/android/support/v4/media/TransportController.java b/v4/java/android/support/v4/media/TransportController.java
index fdbb3f8..b92a4a1 100644
--- a/v4/java/android/support/v4/media/TransportController.java
+++ b/v4/java/android/support/v4/media/TransportController.java
@@ -52,18 +52,18 @@
     /**
      * Retrieve the total duration of the media stream, in milliseconds.
      */
-    public abstract int getDuration();
+    public abstract long getDuration();
 
     /**
      * Retrieve the current playback location in the media stream, in milliseconds.
      */
-    public abstract int getCurrentPosition();
+    public abstract long getCurrentPosition();
 
     /**
      * Move to a new location in the media stream.
      * @param pos Position to move to, in milliseconds.
      */
-    public abstract void seekTo(int pos);
+    public abstract void seekTo(long pos);
 
     /**
      * Return whether the player is currently playing its stream.
diff --git a/v4/java/android/support/v4/media/TransportMediator.java b/v4/java/android/support/v4/media/TransportMediator.java
index 8ea16a9..93706b9 100644
--- a/v4/java/android/support/v4/media/TransportMediator.java
+++ b/v4/java/android/support/v4/media/TransportMediator.java
@@ -51,11 +51,11 @@
     final AudioManager mAudioManager;
     final View mView;
     final Object mDispatcherState;
-    final TransportControllerJellybeanMR2 mController;
+    final TransportMediatorJellybeanMR2 mController;
     final ArrayList<TransportStateListener> mListeners
             = new ArrayList<TransportStateListener>();
-    final TransportControllerJellybeanMR2.TransportCallback mTransportKeyCallback
-            = new TransportControllerJellybeanMR2.TransportCallback() {
+    final TransportMediatorCallback mTransportKeyCallback
+            = new TransportMediatorCallback() {
         @Override
         public void handleKey(KeyEvent key) {
             key.dispatch(mKeyEventCallback);
@@ -64,6 +64,16 @@
         public void handleAudioFocusChange(int focusChange) {
             mCallbacks.onAudioFocusChange(focusChange);
         }
+
+        @Override
+        public long getPlaybackPosition() {
+            return mCallbacks.onGetCurrentPosition();
+        }
+
+        @Override
+        public void playbackPositionUpdate(long newPositionMs) {
+            mCallbacks.onSeekTo(newPositionMs);
+        }
     };
 
     /** Synonym for {@link KeyEvent#KEYCODE_MEDIA_PLAY KeyEvent.KEYCODE_MEDIA_PLAY} */
@@ -153,7 +163,7 @@
         mView = activity != null ? activity.getWindow().getDecorView() : view;
         mDispatcherState = KeyEventCompat.getKeyDispatcherState(mView);
         if (Build.VERSION.SDK_INT >= 18 || Build.VERSION.CODENAME.equals("JellyBeanMR2")) {
-            mController = new TransportControllerJellybeanMR2(mContext, mAudioManager,
+            mController = new TransportMediatorJellybeanMR2(mContext, mAudioManager,
                     mView, mTransportKeyCallback);
         } else {
             mController = null;
@@ -168,6 +178,13 @@
      * {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR2}.  You should always check for
      * null here and not do anything with the RemoteControlClient if none is given; this
      * way you don't need to worry about the current platform API version.
+     *
+     * <p>Note that this class takes possession of the
+     * {@link android.media.RemoteControlClient.OnGetPlaybackPositionListener} and
+     * {@link android.media.RemoteControlClient.OnPlaybackPositionUpdateListener} callbacks;
+     * you will interact with these through
+     * {@link TransportPerformer#onGetCurrentPosition() TransportPerformer.onGetCurrentPosition} and
+     * {@link TransportPerformer#onSeekTo TransportPerformer.onSeekTo}, respectively.</p>
      */
     public Object getRemoteControlClient() {
         return mController != null ? mController.getRemoteControlClient() : null;
@@ -221,6 +238,7 @@
     private void pushControllerState() {
         if (mController != null) {
             mController.refreshState(mCallbacks.onIsPlaying(),
+                    mCallbacks.onGetCurrentPosition(),
                     mCallbacks.onGetTransportControlFlags());
         }
     }
@@ -274,17 +292,17 @@
     }
 
     @Override
-    public int getDuration() {
+    public long getDuration() {
         return mCallbacks.onGetDuration();
     }
 
     @Override
-    public int getCurrentPosition() {
+    public long getCurrentPosition() {
         return mCallbacks.onGetCurrentPosition();
     }
 
     @Override
-    public void seekTo(int pos) {
+    public void seekTo(long pos) {
         mCallbacks.onSeekTo(pos);
     }
 
diff --git a/v4/java/android/support/v4/media/TransportPerformer.java b/v4/java/android/support/v4/media/TransportPerformer.java
index 98bbbaa..2d3afc9 100644
--- a/v4/java/android/support/v4/media/TransportPerformer.java
+++ b/v4/java/android/support/v4/media/TransportPerformer.java
@@ -48,18 +48,18 @@
     /**
      * Request to return the duration of the current media, in milliseconds.
      */
-    public abstract int onGetDuration();
+    public abstract long onGetDuration();
 
     /**
      * Request to return the current playback position, in milliseconds.
      */
-    public abstract int onGetCurrentPosition();
+    public abstract long onGetCurrentPosition();
 
     /**
      * Request to move the current playback position.
      * @param pos New position to move to, in milliseconds.
      */
-    public abstract void onSeekTo(int pos);
+    public abstract void onSeekTo(long pos);
 
     /**
      * Request to find out whether the player is currently playing its media.
diff --git a/v4/jellybean-mr2/android/support/v4/media/TransportMediatorCallback.java b/v4/jellybean-mr2/android/support/v4/media/TransportMediatorCallback.java
new file mode 100644
index 0000000..aaed620
--- /dev/null
+++ b/v4/jellybean-mr2/android/support/v4/media/TransportMediatorCallback.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2013 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.
+ */
+
+package android.support.v4.media;
+
+import android.view.KeyEvent;
+
+public interface TransportMediatorCallback {
+    public void handleKey(KeyEvent key);
+    public void handleAudioFocusChange(int focusChange);
+    public long getPlaybackPosition();
+    public void playbackPositionUpdate(long newPositionMs);
+}
diff --git a/v4/jellybean-mr2/android/support/v4/media/TransportControllerJellybeanMR2.java b/v4/jellybean-mr2/android/support/v4/media/TransportMediatorJellybeanMR2.java
similarity index 87%
rename from v4/jellybean-mr2/android/support/v4/media/TransportControllerJellybeanMR2.java
rename to v4/jellybean-mr2/android/support/v4/media/TransportMediatorJellybeanMR2.java
index fa63005..89bed33 100644
--- a/v4/jellybean-mr2/android/support/v4/media/TransportControllerJellybeanMR2.java
+++ b/v4/jellybean-mr2/android/support/v4/media/TransportMediatorJellybeanMR2.java
@@ -23,19 +23,18 @@
 import android.content.IntentFilter;
 import android.media.AudioManager;
 import android.media.RemoteControlClient;
-import android.os.SystemClock;
 import android.util.Log;
-import android.view.InputDevice;
-import android.view.KeyCharacterMap;
 import android.view.KeyEvent;
 import android.view.View;
 import android.view.ViewTreeObserver;
 
-public class TransportControllerJellybeanMR2 {
+public class TransportMediatorJellybeanMR2
+        implements RemoteControlClient.OnGetPlaybackPositionListener,
+        RemoteControlClient.OnPlaybackPositionUpdateListener {
     final Context mContext;
     final AudioManager mAudioManager;
     final View mTargetView;
-    final TransportCallback mTransportCallback;
+    final TransportMediatorCallback mTransportCallback;
     final String mReceiverAction;
     final IntentFilter mReceiverFilter;
     final Intent mIntent;
@@ -83,13 +82,8 @@
     int mPlayState = 0;
     boolean mAudioFocused;
 
-    public interface TransportCallback {
-        public void handleKey(KeyEvent key);
-        public void handleAudioFocusChange(int focusChange);
-    }
-
-    public TransportControllerJellybeanMR2(Context context, AudioManager audioManager,
-            View view, TransportCallback transportCallback) {
+    public TransportMediatorJellybeanMR2(Context context, AudioManager audioManager,
+            View view, TransportMediatorCallback transportCallback) {
         mContext = context;
         mAudioManager = audioManager;
         mTargetView = view;
@@ -118,6 +112,8 @@
         mPendingIntent = PendingIntent.getBroadcast(mContext, 0, mIntent,
                 PendingIntent.FLAG_CANCEL_CURRENT);
         mRemoteControl = new RemoteControlClient(mPendingIntent);
+        mRemoteControl.setOnGetPlaybackPositionListener(this);
+        mRemoteControl.setPlaybackPositionUpdateListener(this);
     }
 
     void gainFocus() {
@@ -149,10 +145,20 @@
         }
     }
 
-    public void refreshState(boolean playing, int transportControls) {
+    @Override
+    public long onGetPlaybackPosition() {
+        return mTransportCallback.getPlaybackPosition();
+    }
+
+    @Override
+    public void onPlaybackPositionUpdate(long newPositionMs) {
+        mTransportCallback.playbackPositionUpdate(newPositionMs);
+    }
+
+    public void refreshState(boolean playing, long position, int transportControls) {
         if (mRemoteControl != null) {
             mRemoteControl.setPlaybackState(playing ? RemoteControlClient.PLAYSTATE_PLAYING
-                    : RemoteControlClient.PLAYSTATE_STOPPED);
+                    : RemoteControlClient.PLAYSTATE_STOPPED, position, playing ? 1 : 0);
             mRemoteControl.setTransportControlFlags(transportControls);
         }
     }