Merge changes I51f2e466,I5b67cb3e into lmp-dev
* changes: Make PlaybackState immutable with a builder Add API to set a default session in Activity
This commit is contained in:
@@ -3309,6 +3309,7 @@ package android.app {
|
||||
method public android.view.LayoutInflater getLayoutInflater();
|
||||
method public android.app.LoaderManager getLoaderManager();
|
||||
method public java.lang.String getLocalClassName();
|
||||
method public final android.media.session.MediaController getMediaController();
|
||||
method public android.view.MenuInflater getMenuInflater();
|
||||
method public final android.app.Activity getParent();
|
||||
method public android.content.Intent getParentActivityIntent();
|
||||
@@ -3432,6 +3433,7 @@ package android.app {
|
||||
method public void setFinishOnTouchOutside(boolean);
|
||||
method public void setImmersive(boolean);
|
||||
method public void setIntent(android.content.Intent);
|
||||
method public final void setMediaController(android.media.session.MediaController);
|
||||
method public boolean setMediaPlaying(boolean);
|
||||
method public final void setProgress(int);
|
||||
method public final void setProgressBarIndeterminate(boolean);
|
||||
@@ -16224,19 +16226,14 @@ package android.media.session {
|
||||
}
|
||||
|
||||
public final class PlaybackState implements android.os.Parcelable {
|
||||
ctor public PlaybackState();
|
||||
ctor public PlaybackState(android.media.session.PlaybackState);
|
||||
method public int describeContents();
|
||||
method public long getActions();
|
||||
method public long getBufferPosition();
|
||||
method public java.lang.CharSequence getErrorMessage();
|
||||
method public float getPlaybackRate();
|
||||
method public long getLastPositionUpdateTime();
|
||||
method public float getPlaybackSpeed();
|
||||
method public long getPosition();
|
||||
method public int getState();
|
||||
method public void setActions(long);
|
||||
method public void setBufferPosition(long);
|
||||
method public void setErrorMessage(java.lang.CharSequence);
|
||||
method public void setState(int, long, float);
|
||||
method public void writeToParcel(android.os.Parcel, int);
|
||||
field public static final long ACTION_FAST_FORWARD = 64L; // 0x40L
|
||||
field public static final long ACTION_PAUSE = 2L; // 0x2L
|
||||
@@ -16263,6 +16260,17 @@ package android.media.session {
|
||||
field public static final int STATE_STOPPED = 1; // 0x1
|
||||
}
|
||||
|
||||
public static final class PlaybackState.Builder {
|
||||
ctor public PlaybackState.Builder();
|
||||
ctor public PlaybackState.Builder(android.media.session.PlaybackState);
|
||||
method public android.media.session.PlaybackState build();
|
||||
method public android.media.session.PlaybackState.Builder setActions(long);
|
||||
method public android.media.session.PlaybackState.Builder setBufferPosition(long);
|
||||
method public android.media.session.PlaybackState.Builder setErrorMessage(java.lang.CharSequence);
|
||||
method public android.media.session.PlaybackState.Builder setState(int, long, float, long);
|
||||
method public android.media.session.PlaybackState.Builder setState(int, long, float);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
package android.media.tv {
|
||||
@@ -34285,6 +34293,7 @@ package android.view {
|
||||
method protected final int getForcedWindowFlags();
|
||||
method public abstract android.view.LayoutInflater getLayoutInflater();
|
||||
method protected final int getLocalFeatures();
|
||||
method public android.media.session.MediaController getMediaController();
|
||||
method public abstract int getNavigationBarColor();
|
||||
method public android.transition.Transition getSharedElementEnterTransition();
|
||||
method public android.transition.Transition getSharedElementExitTransition();
|
||||
@@ -34341,6 +34350,7 @@ package android.view {
|
||||
method public void setLayout(int, int);
|
||||
method public void setLocalFocus(boolean, boolean);
|
||||
method public void setLogo(int);
|
||||
method public void setMediaController(android.media.session.MediaController);
|
||||
method public abstract void setNavigationBarColor(int);
|
||||
method public void setSharedElementEnterTransition(android.transition.Transition);
|
||||
method public void setSharedElementExitTransition(android.transition.Transition);
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -23,6 +23,8 @@ import android.content.res.Configuration;
|
||||
import android.content.res.TypedArray;
|
||||
import android.graphics.PixelFormat;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.media.session.MediaController;
|
||||
import android.media.session.MediaSession;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.os.IBinder;
|
||||
@@ -157,7 +159,7 @@ public abstract class Window {
|
||||
private static final String PROPERTY_HARDWARE_UI = "persist.sys.ui.hw";
|
||||
|
||||
private final Context mContext;
|
||||
|
||||
|
||||
private TypedArray mWindowStyle;
|
||||
private Callback mCallback;
|
||||
private OnWindowDismissedCallback mOnWindowDismissedCallback;
|
||||
@@ -181,7 +183,7 @@ public abstract class Window {
|
||||
private int mDefaultWindowFormat = PixelFormat.OPAQUE;
|
||||
|
||||
private boolean mHasSoftInputMode = false;
|
||||
|
||||
|
||||
private boolean mDestroyed;
|
||||
|
||||
// The current window attributes.
|
||||
@@ -227,7 +229,7 @@ public abstract class Window {
|
||||
* @return boolean Return true if this event was consumed.
|
||||
*/
|
||||
public boolean dispatchTouchEvent(MotionEvent event);
|
||||
|
||||
|
||||
/**
|
||||
* Called to process trackball events. At the very least your
|
||||
* implementation must call
|
||||
@@ -313,14 +315,14 @@ public abstract class Window {
|
||||
* Called when a panel's menu is opened by the user. This may also be
|
||||
* called when the menu is changing from one type to another (for
|
||||
* example, from the icon menu to the expanded menu).
|
||||
*
|
||||
*
|
||||
* @param featureId The panel that the menu is in.
|
||||
* @param menu The menu that is opened.
|
||||
* @return Return true to allow the menu to open, or false to prevent
|
||||
* the menu from opening.
|
||||
*/
|
||||
public boolean onMenuOpened(int featureId, Menu menu);
|
||||
|
||||
|
||||
/**
|
||||
* Called when a panel's menu item has been selected by the user.
|
||||
*
|
||||
@@ -364,31 +366,31 @@ public abstract class Window {
|
||||
* for more information.
|
||||
*/
|
||||
public void onAttachedToWindow();
|
||||
|
||||
|
||||
/**
|
||||
* Called when the window has been attached to the window manager.
|
||||
* See {@link View#onDetachedFromWindow() View.onDetachedFromWindow()}
|
||||
* for more information.
|
||||
*/
|
||||
public void onDetachedFromWindow();
|
||||
|
||||
|
||||
/**
|
||||
* Called when a panel is being closed. If another logical subsequent
|
||||
* panel is being opened (and this panel is being closed to make room for the subsequent
|
||||
* panel), this method will NOT be called.
|
||||
*
|
||||
*
|
||||
* @param featureId The panel that is being displayed.
|
||||
* @param menu If onCreatePanelView() returned null, this is the Menu
|
||||
* being displayed in the panel.
|
||||
*/
|
||||
public void onPanelClosed(int featureId, Menu menu);
|
||||
|
||||
|
||||
/**
|
||||
* Called when the user signals the desire to start a search.
|
||||
*
|
||||
*
|
||||
* @return true if search launched, false if activity refuses (blocks)
|
||||
*
|
||||
* @see android.app.Activity#onSearchRequested()
|
||||
*
|
||||
* @see android.app.Activity#onSearchRequested()
|
||||
*/
|
||||
public boolean onSearchRequested();
|
||||
|
||||
@@ -457,7 +459,7 @@ public abstract class Window {
|
||||
return mWindowStyle;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set the container for this window. If not set, the DecorWindow
|
||||
* operates as a top-level window; otherwise, it negotiates with the
|
||||
@@ -488,7 +490,7 @@ public abstract class Window {
|
||||
public final boolean hasChildren() {
|
||||
return mHasChildren;
|
||||
}
|
||||
|
||||
|
||||
/** @hide */
|
||||
public final void destroy() {
|
||||
mDestroyed = true;
|
||||
@@ -622,14 +624,14 @@ public abstract class Window {
|
||||
* callback will be used to tell you about state changes to the surface.
|
||||
*/
|
||||
public abstract void takeSurface(SurfaceHolder.Callback2 callback);
|
||||
|
||||
|
||||
/**
|
||||
* Take ownership of this window's InputQueue. The window will no
|
||||
* longer read and dispatch input events from the queue; it is your
|
||||
* responsibility to do so.
|
||||
*/
|
||||
public abstract void takeInputQueue(InputQueue.Callback callback);
|
||||
|
||||
|
||||
/**
|
||||
* Return whether this window is being displayed with a floating style
|
||||
* (based on the {@link android.R.attr#windowIsFloating} attribute in
|
||||
@@ -740,7 +742,7 @@ public abstract class Window {
|
||||
}
|
||||
dispatchWindowAttributesChanged(attrs);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Convenience function to set the flag bits as specified in flags, as
|
||||
* per {@link #setFlags}.
|
||||
@@ -756,7 +758,7 @@ public abstract class Window {
|
||||
public void addPrivateFlags(int flags) {
|
||||
setPrivateFlags(flags, flags);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Convenience function to clear the flag bits as specified in flags, as
|
||||
* per {@link #setFlags}.
|
||||
@@ -772,7 +774,7 @@ public abstract class Window {
|
||||
* Set the flags of the window, as per the
|
||||
* {@link WindowManager.LayoutParams WindowManager.LayoutParams}
|
||||
* flags.
|
||||
*
|
||||
*
|
||||
* <p>Note that some flags must be set before the window decoration is
|
||||
* created (by the first call to
|
||||
* {@link #setContentView(View, android.view.ViewGroup.LayoutParams)} or
|
||||
@@ -859,20 +861,20 @@ public abstract class Window {
|
||||
protected final int getForcedWindowFlags() {
|
||||
return mForcedWindowFlags;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Has the app specified their own soft input mode?
|
||||
*/
|
||||
protected final boolean hasSoftInputMode() {
|
||||
return mHasSoftInputMode;
|
||||
}
|
||||
|
||||
|
||||
/** @hide */
|
||||
public void setCloseOnTouchOutside(boolean close) {
|
||||
mCloseOnTouchOutside = close;
|
||||
mSetCloseOnTouchOutside = true;
|
||||
}
|
||||
|
||||
|
||||
/** @hide */
|
||||
public void setCloseOnTouchOutsideIfNotSet(boolean close) {
|
||||
if (!mSetCloseOnTouchOutside) {
|
||||
@@ -880,10 +882,10 @@ public abstract class Window {
|
||||
mSetCloseOnTouchOutside = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/** @hide */
|
||||
public abstract void alwaysReadCloseOnTouchAttr();
|
||||
|
||||
|
||||
/** @hide */
|
||||
public boolean shouldCloseOnTouch(Context context, MotionEvent event) {
|
||||
if (mCloseOnTouchOutside && event.getAction() == MotionEvent.ACTION_DOWN
|
||||
@@ -892,7 +894,7 @@ public abstract class Window {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
private boolean isOutOfBounds(Context context, MotionEvent event) {
|
||||
final int x = (int) event.getX();
|
||||
final int y = (int) event.getY();
|
||||
@@ -902,7 +904,7 @@ public abstract class Window {
|
||||
|| (x > (decorView.getWidth()+slop))
|
||||
|| (y > (decorView.getHeight()+slop));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Enable extended screen features. This must be called before
|
||||
* setContentView(). May be called as many times as desired as long as it
|
||||
@@ -989,7 +991,7 @@ public abstract class Window {
|
||||
* of the window that can not, from this point forward, be changed: the
|
||||
* features that have been requested with {@link #requestFeature(int)},
|
||||
* and certain window flags as described in {@link #setFlags(int, int)}.
|
||||
*
|
||||
*
|
||||
* @param view The desired content to display.
|
||||
* @param params Layout parameters for the view.
|
||||
*/
|
||||
@@ -1037,7 +1039,7 @@ public abstract class Window {
|
||||
public abstract void togglePanel(int featureId, KeyEvent event);
|
||||
|
||||
public abstract void invalidatePanelMenu(int featureId);
|
||||
|
||||
|
||||
public abstract boolean performPanelShortcut(int featureId,
|
||||
int keyCode,
|
||||
KeyEvent event,
|
||||
@@ -1052,17 +1054,17 @@ public abstract class Window {
|
||||
|
||||
/**
|
||||
* Should be called when the configuration is changed.
|
||||
*
|
||||
*
|
||||
* @param newConfig The new configuration.
|
||||
*/
|
||||
public abstract void onConfigurationChanged(Configuration newConfig);
|
||||
|
||||
|
||||
/**
|
||||
* Change the background of this window to a Drawable resource. Setting the
|
||||
* background to null will make the window be opaque. To make the window
|
||||
* transparent, you can use an empty drawable (for instance a ColorDrawable
|
||||
* with the color 0 or the system drawable android:drawable/empty.)
|
||||
*
|
||||
*
|
||||
* @param resid The resource identifier of a drawable resource which will be
|
||||
* installed as the new background.
|
||||
*/
|
||||
@@ -1173,7 +1175,7 @@ public abstract class Window {
|
||||
*
|
||||
*/
|
||||
public abstract boolean superDispatchTouchEvent(MotionEvent event);
|
||||
|
||||
|
||||
/**
|
||||
* Used by custom windows, such as Dialog, to pass the trackball event
|
||||
* further down the view hierarchy. Application developers should
|
||||
@@ -1181,7 +1183,7 @@ public abstract class Window {
|
||||
*
|
||||
*/
|
||||
public abstract boolean superDispatchTrackballEvent(MotionEvent event);
|
||||
|
||||
|
||||
/**
|
||||
* Used by custom windows, such as Dialog, to pass the generic motion event
|
||||
* further down the view hierarchy. Application developers should
|
||||
@@ -1194,11 +1196,11 @@ public abstract class Window {
|
||||
* Retrieve the top-level window decor view (containing the standard
|
||||
* window frame/decorations and the client's content inside of that), which
|
||||
* can be added as a window to the window manager.
|
||||
*
|
||||
*
|
||||
* <p><em>Note that calling this function for the first time "locks in"
|
||||
* various window characteristics as described in
|
||||
* {@link #setContentView(View, android.view.ViewGroup.LayoutParams)}.</em></p>
|
||||
*
|
||||
*
|
||||
* @return Returns the top-level window decor view.
|
||||
*/
|
||||
public abstract View getDecorView();
|
||||
@@ -1206,16 +1208,16 @@ public abstract class Window {
|
||||
/**
|
||||
* Retrieve the current decor view, but only if it has already been created;
|
||||
* otherwise returns null.
|
||||
*
|
||||
*
|
||||
* @return Returns the top-level window decor or null.
|
||||
* @see #getDecorView
|
||||
*/
|
||||
public abstract View peekDecorView();
|
||||
|
||||
public abstract Bundle saveHierarchyState();
|
||||
|
||||
|
||||
public abstract void restoreHierarchyState(Bundle savedInstanceState);
|
||||
|
||||
|
||||
protected abstract void onActive();
|
||||
|
||||
/**
|
||||
@@ -1233,10 +1235,10 @@ public abstract class Window {
|
||||
{
|
||||
return mFeatures;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Query for the availability of a certain feature.
|
||||
*
|
||||
*
|
||||
* @param feature The feature ID to check
|
||||
* @return true if the feature is enabled, false otherwise.
|
||||
*/
|
||||
@@ -1290,9 +1292,9 @@ public abstract class Window {
|
||||
* @param event the {@link android.view.KeyEvent} to use to help check.
|
||||
*/
|
||||
public abstract boolean isShortcutKey(int keyCode, KeyEvent event);
|
||||
|
||||
|
||||
/**
|
||||
* @see android.app.Activity#setVolumeControlStream(int)
|
||||
* @see android.app.Activity#setVolumeControlStream(int)
|
||||
*/
|
||||
public abstract void setVolumeControlStream(int streamType);
|
||||
|
||||
@@ -1301,6 +1303,19 @@ public abstract class Window {
|
||||
*/
|
||||
public abstract int getVolumeControlStream();
|
||||
|
||||
/**
|
||||
* @see android.app.Activity#setMediaController(android.media.session.MediaController)
|
||||
*/
|
||||
public void setMediaController(MediaController controller) {
|
||||
}
|
||||
|
||||
/**
|
||||
* @see android.app.Activity#getMediaController()
|
||||
*/
|
||||
public MediaController getMediaController() {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set extra options that will influence the UI for this window.
|
||||
* @param uiOptions Flags specifying extra options for this window.
|
||||
|
||||
@@ -682,9 +682,13 @@ public class RemoteControlClient
|
||||
// USE_SESSIONS
|
||||
if (mSession != null) {
|
||||
int pbState = PlaybackState.getStateFromRccState(state);
|
||||
mSessionPlaybackState.setState(pbState, hasPosition ?
|
||||
mPlaybackPositionMs : PlaybackState.PLAYBACK_POSITION_UNKNOWN,
|
||||
playbackSpeed);
|
||||
long position = hasPosition ? mPlaybackPositionMs
|
||||
: PlaybackState.PLAYBACK_POSITION_UNKNOWN;
|
||||
|
||||
PlaybackState.Builder bob = new PlaybackState.Builder(mSessionPlaybackState);
|
||||
bob.setState(pbState, position, playbackSpeed, SystemClock.elapsedRealtime());
|
||||
bob.setErrorMessage(null);
|
||||
mSessionPlaybackState = bob.build();
|
||||
mSession.setPlaybackState(mSessionPlaybackState);
|
||||
}
|
||||
}
|
||||
@@ -745,8 +749,9 @@ public class RemoteControlClient
|
||||
|
||||
// USE_SESSIONS
|
||||
if (mSession != null) {
|
||||
mSessionPlaybackState.setActions(PlaybackState
|
||||
.getActionsFromRccControlFlags(transportControlFlags));
|
||||
PlaybackState.Builder bob = new PlaybackState.Builder(mSessionPlaybackState);
|
||||
bob.setActions(PlaybackState.getActionsFromRccControlFlags(transportControlFlags));
|
||||
mSessionPlaybackState = bob.build();
|
||||
mSession.setPlaybackState(mSessionPlaybackState);
|
||||
}
|
||||
}
|
||||
@@ -946,7 +951,7 @@ public class RemoteControlClient
|
||||
/**
|
||||
* Cache for the current playback state using Session APIs.
|
||||
*/
|
||||
private final PlaybackState mSessionPlaybackState = new PlaybackState();
|
||||
private PlaybackState mSessionPlaybackState = null;
|
||||
|
||||
/**
|
||||
* Cache for metadata using Session APIs. This is re-initialized in apply().
|
||||
|
||||
@@ -1020,7 +1020,7 @@ public final class RemoteController
|
||||
l.onClientPlaybackStateUpdate(playstate);
|
||||
} else {
|
||||
l.onClientPlaybackStateUpdate(playstate, state.getLastPositionUpdateTime(),
|
||||
state.getPosition(), state.getPlaybackRate());
|
||||
state.getPosition(), state.getPlaybackSpeed());
|
||||
}
|
||||
if (state != null) {
|
||||
l.onClientTransportControlUpdate(PlaybackState.getRccControlFlagsFromActions(state
|
||||
|
||||
@@ -184,41 +184,29 @@ public final class PlaybackState implements Parcelable {
|
||||
*/
|
||||
public final static long PLAYBACK_POSITION_UNKNOWN = -1;
|
||||
|
||||
private int mState;
|
||||
private long mPosition;
|
||||
private long mBufferPosition;
|
||||
private float mRate;
|
||||
private long mActions;
|
||||
private CharSequence mErrorMessage;
|
||||
private long mUpdateTime;
|
||||
private final int mState;
|
||||
private final long mPosition;
|
||||
private final long mBufferPosition;
|
||||
private final float mSpeed;
|
||||
private final long mActions;
|
||||
private final CharSequence mErrorMessage;
|
||||
private final long mUpdateTime;
|
||||
|
||||
/**
|
||||
* Create an empty PlaybackState. At minimum a state and actions should be
|
||||
* set before publishing a PlaybackState.
|
||||
*/
|
||||
public PlaybackState() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new PlaybackState from an existing PlaybackState. All fields
|
||||
* will be copied to the new state.
|
||||
*
|
||||
* @param from The PlaybackState to duplicate
|
||||
*/
|
||||
public PlaybackState(PlaybackState from) {
|
||||
mState = from.mState;
|
||||
mPosition = from.mPosition;
|
||||
mRate = from.mRate;
|
||||
mUpdateTime = from.mUpdateTime;
|
||||
mBufferPosition = from.mBufferPosition;
|
||||
mActions = from.mActions;
|
||||
mErrorMessage = from.mErrorMessage;
|
||||
private PlaybackState(int state, long position, long updateTime, float speed,
|
||||
long bufferPosition, long actions, CharSequence error) {
|
||||
mState = state;
|
||||
mPosition = position;
|
||||
mSpeed = speed;
|
||||
mUpdateTime = updateTime;
|
||||
mBufferPosition = bufferPosition;
|
||||
mActions = actions;
|
||||
mErrorMessage = error;
|
||||
}
|
||||
|
||||
private PlaybackState(Parcel in) {
|
||||
mState = in.readInt();
|
||||
mPosition = in.readLong();
|
||||
mRate = in.readFloat();
|
||||
mSpeed = in.readFloat();
|
||||
mUpdateTime = in.readLong();
|
||||
mBufferPosition = in.readLong();
|
||||
mActions = in.readLong();
|
||||
@@ -232,7 +220,7 @@ public final class PlaybackState implements Parcelable {
|
||||
bob.append("state=").append(mState);
|
||||
bob.append(", position=").append(mPosition);
|
||||
bob.append(", buffered position=").append(mBufferPosition);
|
||||
bob.append(", rate=").append(mRate);
|
||||
bob.append(", speed=").append(mSpeed);
|
||||
bob.append(", updated=").append(mUpdateTime);
|
||||
bob.append(", actions=").append(mActions);
|
||||
bob.append(", error=").append(mErrorMessage);
|
||||
@@ -249,7 +237,7 @@ public final class PlaybackState implements Parcelable {
|
||||
public void writeToParcel(Parcel dest, int flags) {
|
||||
dest.writeInt(mState);
|
||||
dest.writeLong(mPosition);
|
||||
dest.writeFloat(mRate);
|
||||
dest.writeFloat(mSpeed);
|
||||
dest.writeLong(mUpdateTime);
|
||||
dest.writeLong(mBufferPosition);
|
||||
dest.writeLong(mActions);
|
||||
@@ -271,41 +259,6 @@ public final class PlaybackState implements Parcelable {
|
||||
public int getState() {
|
||||
return mState;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the current state of playback.
|
||||
* <p>
|
||||
* The position must be in ms and indicates the current playback position
|
||||
* within the track. If the position is unknown use
|
||||
* {@link #PLAYBACK_POSITION_UNKNOWN}.
|
||||
* <p>
|
||||
* The rate is a multiple of normal playback and should be 0 when paused and
|
||||
* negative when rewinding. Normal playback rate is 1.0.
|
||||
* <p>
|
||||
* The state must be one of the following:
|
||||
* <ul>
|
||||
* <li> {@link PlaybackState#STATE_NONE}</li>
|
||||
* <li> {@link PlaybackState#STATE_STOPPED}</li>
|
||||
* <li> {@link PlaybackState#STATE_PLAYING}</li>
|
||||
* <li> {@link PlaybackState#STATE_PAUSED}</li>
|
||||
* <li> {@link PlaybackState#STATE_FAST_FORWARDING}</li>
|
||||
* <li> {@link PlaybackState#STATE_REWINDING}</li>
|
||||
* <li> {@link PlaybackState#STATE_BUFFERING}</li>
|
||||
* <li> {@link PlaybackState#STATE_ERROR}</li>
|
||||
* </ul>
|
||||
*
|
||||
* @param state The current state of playback.
|
||||
* @param position The position in the current track in ms.
|
||||
* @param playbackRate The current rate of playback as a multiple of normal
|
||||
* playback.
|
||||
*/
|
||||
public void setState(int state, long position, float playbackRate) {
|
||||
this.mState = state;
|
||||
this.mPosition = position;
|
||||
this.mRate = playbackRate;
|
||||
mUpdateTime = SystemClock.elapsedRealtime();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current playback position in ms.
|
||||
*/
|
||||
@@ -323,23 +276,14 @@ public final class PlaybackState implements Parcelable {
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the current buffer position in ms. This is the farthest playback
|
||||
* point that can be reached from the current position using only buffered
|
||||
* content.
|
||||
*/
|
||||
public void setBufferPosition(long bufferPosition) {
|
||||
mBufferPosition = bufferPosition;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current playback rate as a multiple of normal playback. This
|
||||
* Get the current playback speed as a multiple of normal playback. This
|
||||
* should be negative when rewinding. A value of 1 means normal playback and
|
||||
* 0 means paused.
|
||||
*
|
||||
* @return The current rate of playback.
|
||||
* @return The current speed of playback.
|
||||
*/
|
||||
public float getPlaybackRate() {
|
||||
return mRate;
|
||||
public float getPlaybackSpeed() {
|
||||
return mSpeed;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -361,25 +305,6 @@ public final class PlaybackState implements Parcelable {
|
||||
return mActions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the current capabilities available on this session. This should use a
|
||||
* bitmask of the available capabilities.
|
||||
* <ul>
|
||||
* <li> {@link PlaybackState#ACTION_SKIP_TO_PREVIOUS}</li>
|
||||
* <li> {@link PlaybackState#ACTION_REWIND}</li>
|
||||
* <li> {@link PlaybackState#ACTION_PLAY}</li>
|
||||
* <li> {@link PlaybackState#ACTION_PAUSE}</li>
|
||||
* <li> {@link PlaybackState#ACTION_STOP}</li>
|
||||
* <li> {@link PlaybackState#ACTION_FAST_FORWARD}</li>
|
||||
* <li> {@link PlaybackState#ACTION_SKIP_TO_NEXT}</li>
|
||||
* <li> {@link PlaybackState#ACTION_SEEK_TO}</li>
|
||||
* <li> {@link PlaybackState#ACTION_SET_RATING}</li>
|
||||
* </ul>
|
||||
*/
|
||||
public void setActions(long capabilities) {
|
||||
mActions = capabilities;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a user readable error message. This should be set when the state is
|
||||
* {@link PlaybackState#STATE_ERROR}.
|
||||
@@ -393,20 +318,11 @@ public final class PlaybackState implements Parcelable {
|
||||
* position has never been set this will return 0;
|
||||
*
|
||||
* @return The last time the position was updated.
|
||||
* @hide
|
||||
*/
|
||||
public long getLastPositionUpdateTime() {
|
||||
return mUpdateTime;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a user readable error message. This should be set when the state is
|
||||
* {@link PlaybackState#STATE_ERROR}.
|
||||
*/
|
||||
public void setErrorMessage(CharSequence errorMessage) {
|
||||
mErrorMessage = errorMessage;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the {@link PlaybackState} state for the given
|
||||
* {@link RemoteControlClient} state.
|
||||
@@ -574,4 +490,175 @@ public final class PlaybackState implements Parcelable {
|
||||
return new PlaybackState[size];
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Builder for {@link PlaybackState} objects.
|
||||
*/
|
||||
public static final class Builder {
|
||||
private int mState;
|
||||
private long mPosition;
|
||||
private long mBufferPosition;
|
||||
private float mSpeed;
|
||||
private long mActions;
|
||||
private CharSequence mErrorMessage;
|
||||
private long mUpdateTime;
|
||||
|
||||
/**
|
||||
* Creates an initially empty state builder.
|
||||
*/
|
||||
public Builder() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a builder with the same initial values as those in the from
|
||||
* state.
|
||||
*
|
||||
* @param from The state to use for initializing the builder.
|
||||
*/
|
||||
public Builder(PlaybackState from) {
|
||||
if (from == null) {
|
||||
return;
|
||||
}
|
||||
mState = from.mState;
|
||||
mPosition = from.mPosition;
|
||||
mBufferPosition = from.mBufferPosition;
|
||||
mSpeed = from.mSpeed;
|
||||
mActions = from.mActions;
|
||||
mErrorMessage = from.mErrorMessage;
|
||||
mUpdateTime = from.mUpdateTime;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the current state of playback.
|
||||
* <p>
|
||||
* The position must be in ms and indicates the current playback
|
||||
* position within the track. If the position is unknown use
|
||||
* {@link #PLAYBACK_POSITION_UNKNOWN}. When not using an unknown
|
||||
* position the time at which the position was updated must be provided.
|
||||
* It is okay to use {@link SystemClock#elapsedRealtime()} if the
|
||||
* current position was just retrieved.
|
||||
* <p>
|
||||
* The speed is a multiple of normal playback and should be 0 when
|
||||
* paused and negative when rewinding. Normal playback speed is 1.0.
|
||||
* <p>
|
||||
* The state must be one of the following:
|
||||
* <ul>
|
||||
* <li> {@link PlaybackState#STATE_NONE}</li>
|
||||
* <li> {@link PlaybackState#STATE_STOPPED}</li>
|
||||
* <li> {@link PlaybackState#STATE_PLAYING}</li>
|
||||
* <li> {@link PlaybackState#STATE_PAUSED}</li>
|
||||
* <li> {@link PlaybackState#STATE_FAST_FORWARDING}</li>
|
||||
* <li> {@link PlaybackState#STATE_REWINDING}</li>
|
||||
* <li> {@link PlaybackState#STATE_BUFFERING}</li>
|
||||
* <li> {@link PlaybackState#STATE_ERROR}</li>
|
||||
* </ul>
|
||||
*
|
||||
* @param state The current state of playback.
|
||||
* @param position The position in the current track in ms.
|
||||
* @param playbackSpeed The current speed of playback as a multiple of
|
||||
* normal playback.
|
||||
* @param updateTime The time in the {@link SystemClock#elapsedRealtime}
|
||||
* timebase that the position was updated at.
|
||||
* @return this
|
||||
*/
|
||||
public Builder setState(int state, long position, float playbackSpeed, long updateTime) {
|
||||
mState = state;
|
||||
mPosition = position;
|
||||
mUpdateTime = updateTime;
|
||||
mSpeed = playbackSpeed;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the current state of playback.
|
||||
* <p>
|
||||
* The position must be in ms and indicates the current playback
|
||||
* position within the track. If the position is unknown use
|
||||
* {@link #PLAYBACK_POSITION_UNKNOWN}. The update time will be set to
|
||||
* the current {@link SystemClock#elapsedRealtime()}.
|
||||
* <p>
|
||||
* The speed is a multiple of normal playback and should be 0 when
|
||||
* paused and negative when rewinding. Normal playback speed is 1.0.
|
||||
* <p>
|
||||
* The state must be one of the following:
|
||||
* <ul>
|
||||
* <li> {@link PlaybackState#STATE_NONE}</li>
|
||||
* <li> {@link PlaybackState#STATE_STOPPED}</li>
|
||||
* <li> {@link PlaybackState#STATE_PLAYING}</li>
|
||||
* <li> {@link PlaybackState#STATE_PAUSED}</li>
|
||||
* <li> {@link PlaybackState#STATE_FAST_FORWARDING}</li>
|
||||
* <li> {@link PlaybackState#STATE_REWINDING}</li>
|
||||
* <li> {@link PlaybackState#STATE_BUFFERING}</li>
|
||||
* <li> {@link PlaybackState#STATE_ERROR}</li>
|
||||
* </ul>
|
||||
*
|
||||
* @param state The current state of playback.
|
||||
* @param position The position in the current track in ms.
|
||||
* @param playbackSpeed The current speed of playback as a multiple of
|
||||
* normal playback.
|
||||
* @return this
|
||||
*/
|
||||
public Builder setState(int state, long position, float playbackSpeed) {
|
||||
return setState(state, position, playbackSpeed, SystemClock.elapsedRealtime());
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the current actions available on this session. This should use a
|
||||
* bitmask of possible actions.
|
||||
* <ul>
|
||||
* <li> {@link PlaybackState#ACTION_SKIP_TO_PREVIOUS}</li>
|
||||
* <li> {@link PlaybackState#ACTION_REWIND}</li>
|
||||
* <li> {@link PlaybackState#ACTION_PLAY}</li>
|
||||
* <li> {@link PlaybackState#ACTION_PAUSE}</li>
|
||||
* <li> {@link PlaybackState#ACTION_STOP}</li>
|
||||
* <li> {@link PlaybackState#ACTION_FAST_FORWARD}</li>
|
||||
* <li> {@link PlaybackState#ACTION_SKIP_TO_NEXT}</li>
|
||||
* <li> {@link PlaybackState#ACTION_SEEK_TO}</li>
|
||||
* <li> {@link PlaybackState#ACTION_SET_RATING}</li>
|
||||
* </ul>
|
||||
*
|
||||
* @param actions The set of actions allowed.
|
||||
* @return this
|
||||
*/
|
||||
public Builder setActions(long actions) {
|
||||
mActions = actions;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the current buffer position in ms. This is the farthest playback
|
||||
* point that can be reached from the current position using only
|
||||
* buffered content.
|
||||
*
|
||||
* @param bufferPosition The position in ms that playback is buffered
|
||||
* to.
|
||||
* @return this
|
||||
*/
|
||||
public Builder setBufferPosition(long bufferPosition) {
|
||||
mBufferPosition = bufferPosition;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a user readable error message. This should be set when the state
|
||||
* is {@link PlaybackState#STATE_ERROR}.
|
||||
*
|
||||
* @param error The error message for display to the user.
|
||||
* @return this
|
||||
*/
|
||||
public Builder setErrorMessage(CharSequence error) {
|
||||
mErrorMessage = error;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build and return the PlaybackState instance with these values.
|
||||
*
|
||||
* @return A new state instance.
|
||||
*/
|
||||
public PlaybackState build() {
|
||||
return new PlaybackState(mState, mPosition, mUpdateTime, mSpeed, mBufferPosition,
|
||||
mActions, mErrorMessage);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -49,6 +49,9 @@ import android.graphics.PixelFormat;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.media.AudioManager;
|
||||
import android.media.session.MediaController;
|
||||
import android.media.session.MediaSession;
|
||||
import android.media.session.MediaSessionLegacyHelper;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
@@ -224,6 +227,7 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
|
||||
private boolean mClosingActionMenu;
|
||||
|
||||
private int mVolumeControlStreamType = AudioManager.USE_DEFAULT_STREAM_TYPE;
|
||||
private MediaController mMediaController;
|
||||
|
||||
private AudioManager mAudioManager;
|
||||
private KeyguardManager mKeyguardManager;
|
||||
@@ -1688,15 +1692,42 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
|
||||
|
||||
switch (keyCode) {
|
||||
case KeyEvent.KEYCODE_VOLUME_UP:
|
||||
case KeyEvent.KEYCODE_VOLUME_DOWN:
|
||||
case KeyEvent.KEYCODE_VOLUME_DOWN: {
|
||||
int direction = keyCode == KeyEvent.KEYCODE_VOLUME_UP ? AudioManager.ADJUST_RAISE
|
||||
: AudioManager.ADJUST_LOWER;
|
||||
// If we have a session send it the volume command, otherwise
|
||||
// use the suggested stream.
|
||||
if (mMediaController != null) {
|
||||
mMediaController.adjustVolumeBy(direction, AudioManager.FLAG_SHOW_UI);
|
||||
} else {
|
||||
MediaSessionLegacyHelper.getHelper(getContext()).sendAdjustVolumeBy(
|
||||
mVolumeControlStreamType, direction, AudioManager.FLAG_SHOW_UI);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
case KeyEvent.KEYCODE_VOLUME_MUTE: {
|
||||
// Similar code is in PhoneFallbackEventHandler in case the window
|
||||
// doesn't have one of these. In this case, we execute it here and
|
||||
// eat the event instead, because we have mVolumeControlStreamType
|
||||
// and they don't.
|
||||
getAudioManager().handleKeyDown(event, mVolumeControlStreamType);
|
||||
return true;
|
||||
}
|
||||
// These are all the recognized media key codes in
|
||||
// KeyEvent.isMediaKey()
|
||||
case KeyEvent.KEYCODE_MEDIA_PLAY:
|
||||
case KeyEvent.KEYCODE_MEDIA_PAUSE:
|
||||
case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE:
|
||||
case KeyEvent.KEYCODE_MUTE:
|
||||
case KeyEvent.KEYCODE_HEADSETHOOK:
|
||||
case KeyEvent.KEYCODE_MEDIA_STOP:
|
||||
case KeyEvent.KEYCODE_MEDIA_NEXT:
|
||||
case KeyEvent.KEYCODE_MEDIA_PREVIOUS:
|
||||
case KeyEvent.KEYCODE_MEDIA_REWIND:
|
||||
case KeyEvent.KEYCODE_MEDIA_RECORD:
|
||||
case KeyEvent.KEYCODE_MEDIA_FAST_FORWARD: {
|
||||
if (mMediaController != null) {
|
||||
if (mMediaController.dispatchMediaButtonEvent(event)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
case KeyEvent.KEYCODE_MENU: {
|
||||
onKeyDownPanel((featureId < 0) ? FEATURE_OPTIONS_PANEL : featureId, event);
|
||||
@@ -1750,7 +1781,19 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
|
||||
|
||||
switch (keyCode) {
|
||||
case KeyEvent.KEYCODE_VOLUME_UP:
|
||||
case KeyEvent.KEYCODE_VOLUME_DOWN:
|
||||
case KeyEvent.KEYCODE_VOLUME_DOWN: {
|
||||
// If we have a session send it the volume command, otherwise
|
||||
// use the suggested stream.
|
||||
if (mMediaController != null) {
|
||||
mMediaController.adjustVolumeBy(0, AudioManager.FLAG_PLAY_SOUND
|
||||
| AudioManager.FLAG_VIBRATE);
|
||||
} else {
|
||||
MediaSessionLegacyHelper.getHelper(getContext()).sendAdjustVolumeBy(
|
||||
mVolumeControlStreamType, 0,
|
||||
AudioManager.FLAG_PLAY_SOUND | AudioManager.FLAG_VIBRATE);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
case KeyEvent.KEYCODE_VOLUME_MUTE: {
|
||||
// Similar code is in PhoneFallbackEventHandler in case the window
|
||||
// doesn't have one of these. In this case, we execute it here and
|
||||
@@ -1759,6 +1802,25 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
|
||||
getAudioManager().handleKeyUp(event, mVolumeControlStreamType);
|
||||
return true;
|
||||
}
|
||||
// These are all the recognized media key codes in
|
||||
// KeyEvent.isMediaKey()
|
||||
case KeyEvent.KEYCODE_MEDIA_PLAY:
|
||||
case KeyEvent.KEYCODE_MEDIA_PAUSE:
|
||||
case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE:
|
||||
case KeyEvent.KEYCODE_MUTE:
|
||||
case KeyEvent.KEYCODE_HEADSETHOOK:
|
||||
case KeyEvent.KEYCODE_MEDIA_STOP:
|
||||
case KeyEvent.KEYCODE_MEDIA_NEXT:
|
||||
case KeyEvent.KEYCODE_MEDIA_PREVIOUS:
|
||||
case KeyEvent.KEYCODE_MEDIA_REWIND:
|
||||
case KeyEvent.KEYCODE_MEDIA_RECORD:
|
||||
case KeyEvent.KEYCODE_MEDIA_FAST_FORWARD: {
|
||||
if (mMediaController != null) {
|
||||
if (mMediaController.dispatchMediaButtonEvent(event)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
case KeyEvent.KEYCODE_MENU: {
|
||||
onKeyUpPanel(featureId < 0 ? FEATURE_OPTIONS_PANEL : featureId,
|
||||
@@ -3773,6 +3835,16 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
|
||||
return mVolumeControlStreamType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setMediaController(MediaController controller) {
|
||||
mMediaController = controller;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MediaController getMediaController() {
|
||||
return mMediaController;
|
||||
}
|
||||
|
||||
private boolean isTranslucent() {
|
||||
TypedArray a = getWindowStyle();
|
||||
return a.getBoolean(a.getResourceId(
|
||||
|
||||
@@ -505,16 +505,19 @@ public class MediaSessionRecord implements IBinder.DeathRecipient {
|
||||
|| state.getState() == PlaybackState.STATE_FAST_FORWARDING
|
||||
|| state.getState() == PlaybackState.STATE_REWINDING) {
|
||||
long updateTime = state.getLastPositionUpdateTime();
|
||||
long currentTime = SystemClock.elapsedRealtime();
|
||||
if (updateTime > 0) {
|
||||
long position = (long) (state.getPlaybackRate()
|
||||
* (SystemClock.elapsedRealtime() - updateTime)) + state.getPosition();
|
||||
long position = (long) (state.getPlaybackSpeed()
|
||||
* (currentTime - updateTime)) + state.getPosition();
|
||||
if (duration >= 0 && position > duration) {
|
||||
position = duration;
|
||||
} else if (position < 0) {
|
||||
position = 0;
|
||||
}
|
||||
result = new PlaybackState(state);
|
||||
result.setState(state.getState(), position, state.getPlaybackRate());
|
||||
PlaybackState.Builder builder = new PlaybackState.Builder(state);
|
||||
builder.setState(state.getState(), position, state.getPlaybackSpeed(),
|
||||
currentTime);
|
||||
result = builder.build();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,12 +18,14 @@ package com.android.onemedia;
|
||||
|
||||
import android.media.MediaMetadata;
|
||||
import android.media.session.MediaController;
|
||||
import android.media.session.MediaSession;
|
||||
import android.media.session.MediaSessionManager;
|
||||
import android.media.session.PlaybackState;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.IBinder;
|
||||
import android.os.RemoteException;
|
||||
import android.app.Activity;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
@@ -43,7 +45,7 @@ public class PlayerController {
|
||||
protected MediaController.TransportControls mTransportControls;
|
||||
|
||||
private final Intent mServiceIntent;
|
||||
private Context mContext;
|
||||
private Activity mContext;
|
||||
private Listener mListener;
|
||||
private SessionCallback mControllerCb;
|
||||
private MediaSessionManager mManager;
|
||||
@@ -51,7 +53,7 @@ public class PlayerController {
|
||||
|
||||
private boolean mResumed;
|
||||
|
||||
public PlayerController(Context context, Intent serviceIntent) {
|
||||
public PlayerController(Activity context, Intent serviceIntent) {
|
||||
mContext = context;
|
||||
if (serviceIntent == null) {
|
||||
mServiceIntent = new Intent(mContext, PlayerService.class);
|
||||
@@ -140,6 +142,7 @@ public class PlayerController {
|
||||
mBinder = null;
|
||||
mController = null;
|
||||
mTransportControls = null;
|
||||
mContext.setMediaController(null);
|
||||
Log.d(TAG, "Disconnected from PlayerService");
|
||||
|
||||
if (mListener != null) {
|
||||
@@ -151,12 +154,15 @@ public class PlayerController {
|
||||
public void onServiceConnected(ComponentName name, IBinder service) {
|
||||
mBinder = IPlayerService.Stub.asInterface(service);
|
||||
Log.d(TAG, "service is " + service + " binder is " + mBinder);
|
||||
MediaSession.Token token;
|
||||
try {
|
||||
mController = MediaController.fromToken(mBinder.getSessionToken());
|
||||
token = mBinder.getSessionToken();
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, "Error getting session", e);
|
||||
return;
|
||||
}
|
||||
mController = MediaController.fromToken(token);
|
||||
mContext.setMediaController(mController);
|
||||
mController.addCallback(mControllerCb, mHandler);
|
||||
mTransportControls = mController.getTransportControls();
|
||||
Log.d(TAG, "Ready to use PlayerService");
|
||||
|
||||
@@ -28,6 +28,7 @@ import android.media.session.PlaybackState;
|
||||
import android.os.Bundle;
|
||||
import android.support.media.protocols.MediaPlayerProtocol;
|
||||
import android.support.media.protocols.MediaPlayerProtocol.MediaStatus;
|
||||
import android.os.SystemClock;
|
||||
import android.util.Log;
|
||||
import android.view.KeyEvent;
|
||||
|
||||
@@ -59,9 +60,9 @@ public class PlayerSession {
|
||||
mRenderer = new LocalRenderer(context, null);
|
||||
mCallback = new SessionCb();
|
||||
mRenderListener = new RenderListener();
|
||||
mPlaybackState = new PlaybackState();
|
||||
mPlaybackState.setActions(PlaybackState.ACTION_PAUSE
|
||||
| PlaybackState.ACTION_PLAY);
|
||||
PlaybackState.Builder psBob = new PlaybackState.Builder();
|
||||
psBob.setActions(PlaybackState.ACTION_PAUSE | PlaybackState.ACTION_PLAY);
|
||||
mPlaybackState = psBob.build();
|
||||
|
||||
mRenderer.registerListener(mRenderListener);
|
||||
}
|
||||
@@ -131,7 +132,10 @@ public class PlayerSession {
|
||||
private void updateState(int newState) {
|
||||
float rate = newState == PlaybackState.STATE_PLAYING ? 1 : 0;
|
||||
long position = mRenderer == null ? -1 : mRenderer.getSeekPosition();
|
||||
mPlaybackState.setState(newState, position, rate);
|
||||
PlaybackState.Builder bob = new PlaybackState.Builder(mPlaybackState);
|
||||
bob.setState(newState, position, rate, SystemClock.elapsedRealtime());
|
||||
bob.setErrorMessage(null);
|
||||
mPlaybackState = bob.build();
|
||||
mSession.setPlaybackState(mPlaybackState);
|
||||
}
|
||||
|
||||
@@ -144,10 +148,12 @@ public class PlayerSession {
|
||||
@Override
|
||||
public void onError(int type, int extra, Bundle extras, Throwable error) {
|
||||
Log.d(TAG, "Sending onError with type " + type + " and extra " + extra);
|
||||
mPlaybackState.setState(PlaybackState.STATE_ERROR, -1, 0);
|
||||
PlaybackState.Builder bob = new PlaybackState.Builder(mPlaybackState);
|
||||
bob.setState(PlaybackState.STATE_ERROR, -1, 0, 0);
|
||||
if (error != null) {
|
||||
mPlaybackState.setErrorMessage(error.getLocalizedMessage());
|
||||
bob.setErrorMessage(error.getLocalizedMessage());
|
||||
}
|
||||
mPlaybackState = bob.build();
|
||||
mSession.setPlaybackState(mPlaybackState);
|
||||
if (mListener != null) {
|
||||
mListener.onPlayStateChanged(mPlaybackState);
|
||||
@@ -156,36 +162,41 @@ public class PlayerSession {
|
||||
|
||||
@Override
|
||||
public void onStateChanged(int newState) {
|
||||
if (newState != Renderer.STATE_ERROR) {
|
||||
mPlaybackState.setErrorMessage(null);
|
||||
}
|
||||
long position = -1;
|
||||
if (mRenderer != null) {
|
||||
position = mRenderer.getSeekPosition();
|
||||
}
|
||||
int pbState;
|
||||
float rate = 0;
|
||||
String errorMsg = null;
|
||||
switch (newState) {
|
||||
case Renderer.STATE_ENDED:
|
||||
case Renderer.STATE_STOPPED:
|
||||
mPlaybackState.setState(PlaybackState.STATE_STOPPED, position, 0);
|
||||
pbState = PlaybackState.STATE_STOPPED;
|
||||
break;
|
||||
case Renderer.STATE_INIT:
|
||||
case Renderer.STATE_PREPARING:
|
||||
mPlaybackState.setState(PlaybackState.STATE_BUFFERING, position, 0);
|
||||
pbState = PlaybackState.STATE_BUFFERING;
|
||||
break;
|
||||
case Renderer.STATE_ERROR:
|
||||
mPlaybackState.setState(PlaybackState.STATE_ERROR, position, 0);
|
||||
pbState = PlaybackState.STATE_ERROR;
|
||||
break;
|
||||
case Renderer.STATE_PAUSED:
|
||||
mPlaybackState.setState(PlaybackState.STATE_PAUSED, position, 0);
|
||||
pbState = PlaybackState.STATE_PAUSED;
|
||||
break;
|
||||
case Renderer.STATE_PLAYING:
|
||||
mPlaybackState.setState(PlaybackState.STATE_PLAYING, position, 1);
|
||||
pbState = PlaybackState.STATE_PLAYING;
|
||||
rate = 1;
|
||||
break;
|
||||
default:
|
||||
mPlaybackState.setState(PlaybackState.STATE_ERROR, position, 0);
|
||||
mPlaybackState.setErrorMessage("unkown state");
|
||||
pbState = PlaybackState.STATE_ERROR;
|
||||
errorMsg = "unknown state";
|
||||
break;
|
||||
}
|
||||
PlaybackState.Builder bob = new PlaybackState.Builder(mPlaybackState);
|
||||
bob.setState(pbState, position, rate, SystemClock.elapsedRealtime());
|
||||
bob.setErrorMessage(errorMsg);
|
||||
mPlaybackState = bob.build();
|
||||
mSession.setPlaybackState(mPlaybackState);
|
||||
if (mListener != null) {
|
||||
mListener.onPlayStateChanged(mPlaybackState);
|
||||
@@ -200,7 +211,10 @@ public class PlayerSession {
|
||||
public void onFocusLost() {
|
||||
Log.d(TAG, "Focus lost, changing state to " + Renderer.STATE_PAUSED);
|
||||
long position = mRenderer == null ? -1 : mRenderer.getSeekPosition();
|
||||
mPlaybackState.setState(PlaybackState.STATE_PAUSED, position, 0);
|
||||
PlaybackState.Builder bob = new PlaybackState.Builder(mPlaybackState);
|
||||
bob.setState(PlaybackState.STATE_PAUSED, position, 0, SystemClock.elapsedRealtime());
|
||||
bob.setErrorMessage(null);
|
||||
mPlaybackState = bob.build();
|
||||
mSession.setPlaybackState(mPlaybackState);
|
||||
if (mListener != null) {
|
||||
mListener.onPlayStateChanged(mPlaybackState);
|
||||
|
||||
@@ -29,6 +29,9 @@ import android.os.Process;
|
||||
import android.support.media.protocols.MediaPlayerProtocol;
|
||||
import android.support.media.protocols.MediaPlayerProtocol.MediaInfo;
|
||||
import android.support.media.protocols.MediaPlayerProtocol.MediaStatus;
|
||||
import android.os.Looper;
|
||||
import android.os.ResultReceiver;
|
||||
import android.os.SystemClock;
|
||||
import android.util.Log;
|
||||
|
||||
import com.android.onemedia.playback.LocalRenderer;
|
||||
@@ -60,9 +63,9 @@ public class OneMediaRouteProvider extends MediaRouteService {
|
||||
mHandler = new Handler();
|
||||
mRenderer = new LocalRenderer(this, null);
|
||||
mRenderListener = new RenderListener();
|
||||
mPlaybackState = new PlaybackState();
|
||||
mPlaybackState.setActions(PlaybackState.ACTION_PAUSE
|
||||
| PlaybackState.ACTION_PLAY);
|
||||
PlaybackState.Builder bob = new PlaybackState.Builder();
|
||||
bob.setActions(PlaybackState.ACTION_PAUSE | PlaybackState.ACTION_PLAY);
|
||||
mPlaybackState = bob.build();
|
||||
|
||||
mRenderer.registerListener(mRenderListener);
|
||||
}
|
||||
@@ -178,36 +181,41 @@ public class OneMediaRouteProvider extends MediaRouteService {
|
||||
|
||||
@Override
|
||||
public void onStateChanged(int newState) {
|
||||
if (newState != Renderer.STATE_ERROR) {
|
||||
mPlaybackState.setErrorMessage(null);
|
||||
}
|
||||
long position = -1;
|
||||
if (mRenderer != null) {
|
||||
position = mRenderer.getSeekPosition();
|
||||
}
|
||||
int pbState;
|
||||
float rate = 0;
|
||||
String errorMsg = null;
|
||||
switch (newState) {
|
||||
case Renderer.STATE_ENDED:
|
||||
case Renderer.STATE_STOPPED:
|
||||
mPlaybackState.setState(PlaybackState.STATE_STOPPED, position, 0);
|
||||
pbState = PlaybackState.STATE_STOPPED;
|
||||
break;
|
||||
case Renderer.STATE_INIT:
|
||||
case Renderer.STATE_PREPARING:
|
||||
mPlaybackState.setState(PlaybackState.STATE_BUFFERING, position, 0);
|
||||
pbState = PlaybackState.STATE_BUFFERING;
|
||||
break;
|
||||
case Renderer.STATE_ERROR:
|
||||
mPlaybackState.setState(PlaybackState.STATE_ERROR, position, 0);
|
||||
pbState = PlaybackState.STATE_ERROR;
|
||||
break;
|
||||
case Renderer.STATE_PAUSED:
|
||||
mPlaybackState.setState(PlaybackState.STATE_PAUSED, position, 0);
|
||||
pbState = PlaybackState.STATE_PAUSED;
|
||||
break;
|
||||
case Renderer.STATE_PLAYING:
|
||||
mPlaybackState.setState(PlaybackState.STATE_PLAYING, position, 1);
|
||||
pbState = PlaybackState.STATE_PLAYING;
|
||||
rate = 1;
|
||||
break;
|
||||
default:
|
||||
mPlaybackState.setState(PlaybackState.STATE_ERROR, position, 0);
|
||||
mPlaybackState.setErrorMessage("unkown state");
|
||||
pbState = PlaybackState.STATE_ERROR;
|
||||
errorMsg = "unknown state";
|
||||
break;
|
||||
}
|
||||
PlaybackState.Builder bob = new PlaybackState.Builder(mPlaybackState);
|
||||
bob.setState(pbState, position, rate, SystemClock.elapsedRealtime());
|
||||
bob.setErrorMessage(errorMsg);
|
||||
mPlaybackState = bob.build();
|
||||
|
||||
sendStatusUpdate(mPlaybackState.getState());
|
||||
}
|
||||
@@ -218,8 +226,9 @@ public class OneMediaRouteProvider extends MediaRouteService {
|
||||
|
||||
@Override
|
||||
public void onFocusLost() {
|
||||
Log.d(TAG, "Focus lost, changing state to " + Renderer.STATE_PAUSED);
|
||||
mPlaybackState.setState(PlaybackState.STATE_PAUSED, mRenderer.getSeekPosition(), 0);
|
||||
Log.d(TAG, "Focus lost, pausing");
|
||||
// Don't update state here, we'll get a separate call to
|
||||
// onStateChanged when it pauses
|
||||
mRenderer.onPause();
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user