Merge "Begin refactor of MediaFocusControl"
This commit is contained in:
committed by
Android (Google) Code Review
commit
cd60e3a57c
220
media/java/android/media/MediaController.java
Normal file
220
media/java/android/media/MediaController.java
Normal file
@@ -0,0 +1,220 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2014 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.media;
|
||||||
|
|
||||||
|
import android.app.PendingIntent;
|
||||||
|
import android.content.ComponentName;
|
||||||
|
import android.media.MediaFocusControl.RcClientDeathHandler;
|
||||||
|
import android.os.IBinder;
|
||||||
|
import android.os.IBinder.DeathRecipient;
|
||||||
|
import android.os.RemoteException;
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
|
import java.io.PrintWriter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @hide
|
||||||
|
* Class to handle all the information about a media player, encapsulating information
|
||||||
|
* about its use RemoteControlClient, playback type and volume... The lifecycle of each
|
||||||
|
* instance is managed by android.media.MediaFocusControl, from its addition to the player stack
|
||||||
|
* stack to its release.
|
||||||
|
*/
|
||||||
|
class MediaController implements DeathRecipient {
|
||||||
|
|
||||||
|
// on purpose not using this classe's name, as it will only be used from MediaFocusControl
|
||||||
|
private static final String TAG = "MediaFocusControl";
|
||||||
|
private static final boolean DEBUG = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A global counter for RemoteControlClient identifiers
|
||||||
|
*/
|
||||||
|
private static int sLastRccId = 0;
|
||||||
|
|
||||||
|
//FIXME should be final static
|
||||||
|
public MediaFocusControl mController;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The target for the ACTION_MEDIA_BUTTON events.
|
||||||
|
* Always non null.
|
||||||
|
*/
|
||||||
|
final public PendingIntent mMediaIntent;
|
||||||
|
/**
|
||||||
|
* The registered media button event receiver.
|
||||||
|
* Always non null.
|
||||||
|
*/
|
||||||
|
final public ComponentName mReceiverComponent;
|
||||||
|
|
||||||
|
public int mRccId = RemoteControlClient.RCSE_ID_UNREGISTERED;
|
||||||
|
|
||||||
|
public IBinder mToken;
|
||||||
|
public String mCallingPackageName;
|
||||||
|
public int mCallingUid;
|
||||||
|
/**
|
||||||
|
* Provides access to the information to display on the remote control.
|
||||||
|
* May be null (when a media button event receiver is registered,
|
||||||
|
* but no remote control client has been registered) */
|
||||||
|
public IRemoteControlClient mRcClient;
|
||||||
|
public RcClientDeathHandler mRcClientDeathHandler;
|
||||||
|
/**
|
||||||
|
* Information only used for non-local playback
|
||||||
|
*/
|
||||||
|
public int mPlaybackType;
|
||||||
|
public int mPlaybackVolume;
|
||||||
|
public int mPlaybackVolumeMax;
|
||||||
|
public int mPlaybackVolumeHandling;
|
||||||
|
public int mPlaybackStream;
|
||||||
|
public RccPlaybackState mPlaybackState;
|
||||||
|
public IRemoteVolumeObserver mRemoteVolumeObs;
|
||||||
|
|
||||||
|
|
||||||
|
protected static class RccPlaybackState {
|
||||||
|
public int mState;
|
||||||
|
public long mPositionMs;
|
||||||
|
public float mSpeed;
|
||||||
|
|
||||||
|
public RccPlaybackState(int state, long positionMs, float speed) {
|
||||||
|
mState = state;
|
||||||
|
mPositionMs = positionMs;
|
||||||
|
mSpeed = speed;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void reset() {
|
||||||
|
mState = RemoteControlClient.PLAYSTATE_STOPPED;
|
||||||
|
mPositionMs = RemoteControlClient.PLAYBACK_POSITION_INVALID;
|
||||||
|
mSpeed = RemoteControlClient.PLAYBACK_SPEED_1X;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return stateToString() + ", " + posToString() + ", " + mSpeed + "X";
|
||||||
|
}
|
||||||
|
|
||||||
|
private String posToString() {
|
||||||
|
if (mPositionMs == RemoteControlClient.PLAYBACK_POSITION_INVALID) {
|
||||||
|
return "PLAYBACK_POSITION_INVALID";
|
||||||
|
} else if (mPositionMs == RemoteControlClient.PLAYBACK_POSITION_ALWAYS_UNKNOWN) {
|
||||||
|
return "PLAYBACK_POSITION_ALWAYS_UNKNOWN";
|
||||||
|
} else {
|
||||||
|
return (String.valueOf(mPositionMs) + "ms");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private String stateToString() {
|
||||||
|
switch (mState) {
|
||||||
|
case RemoteControlClient.PLAYSTATE_NONE:
|
||||||
|
return "PLAYSTATE_NONE";
|
||||||
|
case RemoteControlClient.PLAYSTATE_STOPPED:
|
||||||
|
return "PLAYSTATE_STOPPED";
|
||||||
|
case RemoteControlClient.PLAYSTATE_PAUSED:
|
||||||
|
return "PLAYSTATE_PAUSED";
|
||||||
|
case RemoteControlClient.PLAYSTATE_PLAYING:
|
||||||
|
return "PLAYSTATE_PLAYING";
|
||||||
|
case RemoteControlClient.PLAYSTATE_FAST_FORWARDING:
|
||||||
|
return "PLAYSTATE_FAST_FORWARDING";
|
||||||
|
case RemoteControlClient.PLAYSTATE_REWINDING:
|
||||||
|
return "PLAYSTATE_REWINDING";
|
||||||
|
case RemoteControlClient.PLAYSTATE_SKIPPING_FORWARDS:
|
||||||
|
return "PLAYSTATE_SKIPPING_FORWARDS";
|
||||||
|
case RemoteControlClient.PLAYSTATE_SKIPPING_BACKWARDS:
|
||||||
|
return "PLAYSTATE_SKIPPING_BACKWARDS";
|
||||||
|
case RemoteControlClient.PLAYSTATE_BUFFERING:
|
||||||
|
return "PLAYSTATE_BUFFERING";
|
||||||
|
case RemoteControlClient.PLAYSTATE_ERROR:
|
||||||
|
return "PLAYSTATE_ERROR";
|
||||||
|
default:
|
||||||
|
return "[invalid playstate]";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void dump(PrintWriter pw) {
|
||||||
|
// FIXME to implement, remove dump from MediaFocusControl that accesses private members
|
||||||
|
}
|
||||||
|
|
||||||
|
public void resetPlaybackInfo() {
|
||||||
|
mPlaybackType = RemoteControlClient.PLAYBACK_TYPE_LOCAL;
|
||||||
|
mPlaybackVolume = RemoteControlClient.DEFAULT_PLAYBACK_VOLUME;
|
||||||
|
mPlaybackVolumeMax = RemoteControlClient.DEFAULT_PLAYBACK_VOLUME;
|
||||||
|
mPlaybackVolumeHandling = RemoteControlClient.DEFAULT_PLAYBACK_VOLUME_HANDLING;
|
||||||
|
mPlaybackStream = AudioManager.STREAM_MUSIC;
|
||||||
|
mPlaybackState.reset();
|
||||||
|
mRemoteVolumeObs = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** precondition: mediaIntent != null */
|
||||||
|
public MediaController(MediaFocusControl controller, PendingIntent mediaIntent,
|
||||||
|
ComponentName eventReceiver, IBinder token) {
|
||||||
|
mController = controller;
|
||||||
|
mMediaIntent = mediaIntent;
|
||||||
|
mReceiverComponent = eventReceiver;
|
||||||
|
mToken = token;
|
||||||
|
mCallingUid = -1;
|
||||||
|
mRcClient = null;
|
||||||
|
mRccId = ++sLastRccId;
|
||||||
|
mPlaybackState = new RccPlaybackState(
|
||||||
|
RemoteControlClient.PLAYSTATE_STOPPED,
|
||||||
|
RemoteControlClient.PLAYBACK_POSITION_INVALID,
|
||||||
|
RemoteControlClient.PLAYBACK_SPEED_1X);
|
||||||
|
|
||||||
|
resetPlaybackInfo();
|
||||||
|
if (mToken != null) {
|
||||||
|
try {
|
||||||
|
mToken.linkToDeath(this, 0);
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
//FIXME do not access the event handler directly
|
||||||
|
mController.mEventHandler.post(new Runnable() {
|
||||||
|
@Override public void run() {
|
||||||
|
mController.unregisterMediaButtonIntent(mMediaIntent);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void unlinkToRcClientDeath() {
|
||||||
|
if ((mRcClientDeathHandler != null) && (mRcClientDeathHandler.mCb != null)) {
|
||||||
|
try {
|
||||||
|
mRcClientDeathHandler.mCb.unlinkToDeath(mRcClientDeathHandler, 0);
|
||||||
|
mRcClientDeathHandler = null;
|
||||||
|
} catch (java.util.NoSuchElementException e) {
|
||||||
|
// not much we can do here
|
||||||
|
Log.e(TAG, "Error in unlinkToRcClientDeath()", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// FIXME rename to "release"? (as in FocusRequester class)
|
||||||
|
public void destroy() {
|
||||||
|
unlinkToRcClientDeath();
|
||||||
|
if (mToken != null) {
|
||||||
|
mToken.unlinkToDeath(this, 0);
|
||||||
|
mToken = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void binderDied() {
|
||||||
|
mController.unregisterMediaButtonIntent(mMediaIntent);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void finalize() throws Throwable {
|
||||||
|
destroy(); // unlink exception handled inside method
|
||||||
|
super.finalize();
|
||||||
|
}
|
||||||
|
}
|
||||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user