Work on removing non-session media routing code
Change-Id: I73e7d22f2f8772c7b07ccf32d962161d79d5db74
This commit is contained in:
@@ -50,12 +50,6 @@ import java.util.ArrayList;
|
||||
*/
|
||||
public class AudioManager {
|
||||
|
||||
// If we should use the new sessions APIs.
|
||||
private final static boolean USE_SESSIONS = true;
|
||||
// If we should use the legacy APIs. If both are true information will be
|
||||
// duplicated through both paths. Currently this flag isn't used.
|
||||
private final static boolean USE_LEGACY = true;
|
||||
|
||||
private final Context mContext;
|
||||
private long mVolumeKeyUpTime;
|
||||
private final boolean mUseMasterVolume;
|
||||
@@ -483,17 +477,8 @@ public class AudioManager {
|
||||
* or {@link KeyEvent#KEYCODE_MEDIA_AUDIO_TRACK}.
|
||||
*/
|
||||
public void dispatchMediaKeyEvent(KeyEvent keyEvent) {
|
||||
if (USE_SESSIONS) {
|
||||
MediaSessionLegacyHelper helper = MediaSessionLegacyHelper.getHelper(mContext);
|
||||
helper.sendMediaButtonEvent(keyEvent, false);
|
||||
} else {
|
||||
IAudioService service = getService();
|
||||
try {
|
||||
service.dispatchMediaKeyEvent(keyEvent);
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, "dispatchMediaKeyEvent threw exception ", e);
|
||||
}
|
||||
}
|
||||
MediaSessionLegacyHelper helper = MediaSessionLegacyHelper.getHelper(mContext);
|
||||
helper.sendMediaButtonEvent(keyEvent, false);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -644,12 +629,8 @@ public class AudioManager {
|
||||
if (mUseMasterVolume) {
|
||||
service.adjustMasterVolume(direction, flags, mContext.getOpPackageName());
|
||||
} else {
|
||||
if (USE_SESSIONS) {
|
||||
MediaSessionLegacyHelper helper = MediaSessionLegacyHelper.getHelper(mContext);
|
||||
helper.sendAdjustVolumeBy(USE_DEFAULT_STREAM_TYPE, direction, flags);
|
||||
} else {
|
||||
service.adjustVolume(direction, flags, mContext.getOpPackageName());
|
||||
}
|
||||
MediaSessionLegacyHelper helper = MediaSessionLegacyHelper.getHelper(mContext);
|
||||
helper.sendAdjustVolumeBy(USE_DEFAULT_STREAM_TYPE, direction, flags);
|
||||
}
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, "Dead object in adjustVolume", e);
|
||||
@@ -679,13 +660,8 @@ public class AudioManager {
|
||||
if (mUseMasterVolume) {
|
||||
service.adjustMasterVolume(direction, flags, mContext.getOpPackageName());
|
||||
} else {
|
||||
if (USE_SESSIONS) {
|
||||
MediaSessionLegacyHelper helper = MediaSessionLegacyHelper.getHelper(mContext);
|
||||
helper.sendAdjustVolumeBy(suggestedStreamType, direction, flags);
|
||||
} else {
|
||||
service.adjustSuggestedStreamVolume(direction, suggestedStreamType, flags,
|
||||
mContext.getOpPackageName());
|
||||
}
|
||||
MediaSessionLegacyHelper helper = MediaSessionLegacyHelper.getHelper(mContext);
|
||||
helper.sendAdjustVolumeBy(suggestedStreamType, direction, flags);
|
||||
}
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, "Dead object in adjustSuggestedStreamVolume", e);
|
||||
@@ -2215,16 +2191,15 @@ public class AudioManager {
|
||||
}
|
||||
IAudioService service = getService();
|
||||
try {
|
||||
// pi != null
|
||||
// pi != null, this is currently still needed to support across
|
||||
// reboot launching of the last app.
|
||||
service.registerMediaButtonIntent(pi, eventReceiver,
|
||||
eventReceiver == null ? mToken : null);
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, "Dead object in registerMediaButtonIntent"+e);
|
||||
}
|
||||
if (USE_SESSIONS) {
|
||||
MediaSessionLegacyHelper helper = MediaSessionLegacyHelper.getHelper(mContext);
|
||||
helper.addMediaButtonListener(pi, mContext);
|
||||
}
|
||||
MediaSessionLegacyHelper helper = MediaSessionLegacyHelper.getHelper(mContext);
|
||||
helper.addMediaButtonListener(pi, mContext);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2298,10 +2273,8 @@ public class AudioManager {
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, "Dead object in unregisterMediaButtonIntent"+e);
|
||||
}
|
||||
if (USE_SESSIONS) {
|
||||
MediaSessionLegacyHelper helper = MediaSessionLegacyHelper.getHelper(mContext);
|
||||
helper.removeMediaButtonListener(pi);
|
||||
}
|
||||
MediaSessionLegacyHelper helper = MediaSessionLegacyHelper.getHelper(mContext);
|
||||
helper.removeMediaButtonListener(pi);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2315,20 +2288,7 @@ public class AudioManager {
|
||||
if ((rcClient == null) || (rcClient.getRcMediaIntent() == null)) {
|
||||
return;
|
||||
}
|
||||
IAudioService service = getService();
|
||||
try {
|
||||
int rcseId = service.registerRemoteControlClient(
|
||||
rcClient.getRcMediaIntent(), /* mediaIntent */
|
||||
rcClient.getIRemoteControlClient(),/* rcClient */
|
||||
// used to match media button event receiver and audio focus
|
||||
mContext.getPackageName()); /* packageName */
|
||||
rcClient.setRcseId(rcseId);
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, "Dead object in registerRemoteControlClient"+e);
|
||||
}
|
||||
if (USE_SESSIONS) {
|
||||
rcClient.registerWithSession(MediaSessionLegacyHelper.getHelper(mContext));
|
||||
}
|
||||
rcClient.registerWithSession(MediaSessionLegacyHelper.getHelper(mContext));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2341,16 +2301,7 @@ public class AudioManager {
|
||||
if ((rcClient == null) || (rcClient.getRcMediaIntent() == null)) {
|
||||
return;
|
||||
}
|
||||
IAudioService service = getService();
|
||||
try {
|
||||
service.unregisterRemoteControlClient(rcClient.getRcMediaIntent(), /* mediaIntent */
|
||||
rcClient.getIRemoteControlClient()); /* rcClient */
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, "Dead object in unregisterRemoteControlClient"+e);
|
||||
}
|
||||
if (USE_SESSIONS) {
|
||||
rcClient.unregisterWithSession(MediaSessionLegacyHelper.getHelper(mContext));
|
||||
}
|
||||
rcClient.unregisterWithSession(MediaSessionLegacyHelper.getHelper(mContext));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2368,25 +2319,8 @@ public class AudioManager {
|
||||
if (rctlr == null) {
|
||||
return false;
|
||||
}
|
||||
if (USE_SESSIONS) {
|
||||
rctlr.startListeningToSessions();
|
||||
return true;
|
||||
} else {
|
||||
IAudioService service = getService();
|
||||
final RemoteController.OnClientUpdateListener l = rctlr.getUpdateListener();
|
||||
final ComponentName listenerComponent = new ComponentName(mContext, l.getClass());
|
||||
try {
|
||||
int[] artworkDimensions = rctlr.getArtworkSize();
|
||||
boolean reg = service.registerRemoteController(rctlr.getRcDisplay(),
|
||||
artworkDimensions[0]/* w */, artworkDimensions[1]/* h */,
|
||||
listenerComponent);
|
||||
rctlr.setIsRegistered(reg);
|
||||
return reg;
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, "Dead object in registerRemoteController " + e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
rctlr.startListeningToSessions();
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2398,17 +2332,7 @@ public class AudioManager {
|
||||
if (rctlr == null) {
|
||||
return;
|
||||
}
|
||||
if (USE_SESSIONS) {
|
||||
rctlr.stopListeningToSessions();
|
||||
} else {
|
||||
IAudioService service = getService();
|
||||
try {
|
||||
service.unregisterRemoteControlDisplay(rctlr.getRcDisplay());
|
||||
rctlr.setIsRegistered(false);
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, "Dead object in unregisterRemoteControlDisplay " + e);
|
||||
}
|
||||
}
|
||||
rctlr.stopListeningToSessions();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -108,8 +108,7 @@ public class AudioService extends IAudioService.Stub {
|
||||
/** Debug volumes */
|
||||
protected static final boolean DEBUG_VOL = false;
|
||||
|
||||
/** Reroute calls to media session apis */
|
||||
private static final boolean USE_SESSIONS = true;
|
||||
/** debug calls to media session apis */
|
||||
private static final boolean DEBUG_SESSIONS = true;
|
||||
|
||||
/** Allow volume changes to set ringer mode to silent? */
|
||||
@@ -4484,27 +4483,19 @@ public class AudioService extends IAudioService.Stub {
|
||||
}
|
||||
|
||||
public void dispatchMediaKeyEvent(KeyEvent keyEvent) {
|
||||
if (USE_SESSIONS) {
|
||||
if (DEBUG_SESSIONS) {
|
||||
int pid = getCallingPid();
|
||||
Log.w(TAG, "Call to dispatchMediaKeyEvent from " + pid);
|
||||
}
|
||||
MediaSessionLegacyHelper.getHelper(mContext).sendMediaButtonEvent(keyEvent, false);
|
||||
} else {
|
||||
mMediaFocusControl.dispatchMediaKeyEvent(keyEvent);
|
||||
if (DEBUG_SESSIONS) {
|
||||
int pid = getCallingPid();
|
||||
Log.w(TAG, "Call to dispatchMediaKeyEvent from " + pid);
|
||||
}
|
||||
MediaSessionLegacyHelper.getHelper(mContext).sendMediaButtonEvent(keyEvent, false);
|
||||
}
|
||||
|
||||
public void dispatchMediaKeyEventUnderWakelock(KeyEvent keyEvent) {
|
||||
if (USE_SESSIONS) {
|
||||
if (DEBUG_SESSIONS) {
|
||||
int pid = getCallingPid();
|
||||
Log.w(TAG, "Call to dispatchMediaKeyEventUnderWakelock from " + pid);
|
||||
}
|
||||
MediaSessionLegacyHelper.getHelper(mContext).sendMediaButtonEvent(keyEvent, true);
|
||||
} else {
|
||||
mMediaFocusControl.dispatchMediaKeyEventUnderWakelock(keyEvent);
|
||||
if (DEBUG_SESSIONS) {
|
||||
int pid = getCallingPid();
|
||||
Log.w(TAG, "Call to dispatchMediaKeyEventUnderWakelock from " + pid);
|
||||
}
|
||||
MediaSessionLegacyHelper.getHelper(mContext).sendMediaButtonEvent(keyEvent, true);
|
||||
}
|
||||
|
||||
//==========================================================================================
|
||||
|
||||
@@ -60,7 +60,6 @@ import java.util.concurrent.CopyOnWriteArrayList;
|
||||
public class MediaRouter {
|
||||
private static final String TAG = "MediaRouter";
|
||||
private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
|
||||
private static final boolean USE_SESSIONS = true;
|
||||
|
||||
static class Static implements DisplayManager.DisplayListener {
|
||||
final Context mAppContext;
|
||||
@@ -2104,11 +2103,7 @@ public class MediaRouter {
|
||||
public void setPlaybackType(int type) {
|
||||
if (mPlaybackType != type) {
|
||||
mPlaybackType = type;
|
||||
if (USE_SESSIONS) {
|
||||
configureSessionVolume();
|
||||
} else {
|
||||
setPlaybackInfoOnRcc(RemoteControlClient.PLAYBACKINFO_PLAYBACK_TYPE, type);
|
||||
}
|
||||
configureSessionVolume();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2121,12 +2116,7 @@ public class MediaRouter {
|
||||
public void setVolumeHandling(int volumeHandling) {
|
||||
if (mVolumeHandling != volumeHandling) {
|
||||
mVolumeHandling = volumeHandling;
|
||||
if (USE_SESSIONS) {
|
||||
configureSessionVolume();
|
||||
} else {
|
||||
setPlaybackInfoOnRcc(
|
||||
RemoteControlClient.PLAYBACKINFO_VOLUME_HANDLING, volumeHandling);
|
||||
}
|
||||
configureSessionVolume();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2139,12 +2129,8 @@ public class MediaRouter {
|
||||
volume = Math.max(0, Math.min(volume, getVolumeMax()));
|
||||
if (mVolume != volume) {
|
||||
mVolume = volume;
|
||||
if (USE_SESSIONS) {
|
||||
if (mSvp != null) {
|
||||
mSvp.notifyVolumeChanged();
|
||||
}
|
||||
} else {
|
||||
setPlaybackInfoOnRcc(RemoteControlClient.PLAYBACKINFO_VOLUME, volume);
|
||||
if (mSvp != null) {
|
||||
mSvp.notifyVolumeChanged();
|
||||
}
|
||||
dispatchRouteVolumeChanged(this);
|
||||
if (mGroup != null) {
|
||||
@@ -2184,11 +2170,7 @@ public class MediaRouter {
|
||||
public void setVolumeMax(int volumeMax) {
|
||||
if (mVolumeMax != volumeMax) {
|
||||
mVolumeMax = volumeMax;
|
||||
if (USE_SESSIONS) {
|
||||
configureSessionVolume();
|
||||
} else {
|
||||
setPlaybackInfoOnRcc(RemoteControlClient.PLAYBACKINFO_VOLUME_MAX, volumeMax);
|
||||
}
|
||||
configureSessionVolume();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2199,40 +2181,12 @@ public class MediaRouter {
|
||||
public void setPlaybackStream(int stream) {
|
||||
if (mPlaybackStream != stream) {
|
||||
mPlaybackStream = stream;
|
||||
if (USE_SESSIONS) {
|
||||
configureSessionVolume();
|
||||
} else {
|
||||
setPlaybackInfoOnRcc(RemoteControlClient.PLAYBACKINFO_USES_STREAM, stream);
|
||||
}
|
||||
configureSessionVolume();
|
||||
}
|
||||
}
|
||||
|
||||
private void updatePlaybackInfoOnRcc() {
|
||||
if (USE_SESSIONS) {
|
||||
configureSessionVolume();
|
||||
} else {
|
||||
if ((mRcc != null)
|
||||
&& (mRcc.getRcseId() != RemoteControlClient.RCSE_ID_UNREGISTERED)) {
|
||||
mRcc.setPlaybackInformation(
|
||||
RemoteControlClient.PLAYBACKINFO_VOLUME_MAX, mVolumeMax);
|
||||
mRcc.setPlaybackInformation(
|
||||
RemoteControlClient.PLAYBACKINFO_VOLUME, mVolume);
|
||||
mRcc.setPlaybackInformation(
|
||||
RemoteControlClient.PLAYBACKINFO_VOLUME_HANDLING, mVolumeHandling);
|
||||
mRcc.setPlaybackInformation(
|
||||
RemoteControlClient.PLAYBACKINFO_USES_STREAM, mPlaybackStream);
|
||||
mRcc.setPlaybackInformation(
|
||||
RemoteControlClient.PLAYBACKINFO_PLAYBACK_TYPE, mPlaybackType);
|
||||
// let AudioService know whom to call when remote volume
|
||||
// needs to be updated
|
||||
try {
|
||||
sStatic.mAudioService.registerRemoteVolumeObserverForRcc(
|
||||
mRcc.getRcseId() /* rccId */, mRemoteVolObserver /* rvo */);
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, "Error registering remote volume observer", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
configureSessionVolume();
|
||||
}
|
||||
|
||||
private void configureSessionVolume() {
|
||||
@@ -2272,12 +2226,6 @@ public class MediaRouter {
|
||||
}
|
||||
}
|
||||
|
||||
private void setPlaybackInfoOnRcc(int what, int value) {
|
||||
if (mRcc != null) {
|
||||
mRcc.setPlaybackInformation(what, value);
|
||||
}
|
||||
}
|
||||
|
||||
class SessionVolumeProvider extends RemoteVolumeProvider {
|
||||
|
||||
public SessionVolumeProvider(int volumeControl, int maxVolume) {
|
||||
|
||||
@@ -56,7 +56,7 @@ class PlayerRecord implements DeathRecipient {
|
||||
*/
|
||||
final private ComponentName mReceiverComponent;
|
||||
|
||||
private int mRccId = RemoteControlClient.RCSE_ID_UNREGISTERED;
|
||||
private int mRccId = -1;
|
||||
|
||||
/**
|
||||
* A non-null token implies this record tracks a "live" player whose death is being monitored.
|
||||
|
||||
@@ -561,6 +561,8 @@ public class RemoteControlClient
|
||||
return;
|
||||
}
|
||||
synchronized (mCacheLock) {
|
||||
// Still build the old metadata so when creating a new editor
|
||||
// you get the expected values.
|
||||
// assign the edited data
|
||||
mMetadata = new Bundle(mEditorMetadata);
|
||||
// add the information about editable keys
|
||||
@@ -570,16 +572,6 @@ public class RemoteControlClient
|
||||
}
|
||||
mOriginalArtwork = mEditorArtwork;
|
||||
mEditorArtwork = null;
|
||||
if (mMetadataChanged & mArtworkChanged) {
|
||||
// send to remote control display if conditions are met
|
||||
sendMetadataWithArtwork_syncCacheLock(null, 0, 0);
|
||||
} else if (mMetadataChanged) {
|
||||
// send to remote control display if conditions are met
|
||||
sendMetadata_syncCacheLock(null);
|
||||
} else if (mArtworkChanged) {
|
||||
// send to remote control display if conditions are met
|
||||
sendArtwork_syncCacheLock(null, 0, 0);
|
||||
}
|
||||
|
||||
// USE_SESSIONS
|
||||
if (mSession != null && mMetadataBuilder != null) {
|
||||
@@ -687,14 +679,6 @@ public class RemoteControlClient
|
||||
// keep track of when the state change occurred
|
||||
mPlaybackStateChangeTimeMs = SystemClock.elapsedRealtime();
|
||||
|
||||
// send to remote control display if conditions are met
|
||||
sendPlaybackState_syncCacheLock(null);
|
||||
// update AudioService
|
||||
sendAudioServiceNewPlaybackState_syncCacheLock();
|
||||
|
||||
// handle automatic playback position refreshes
|
||||
initiateCheckForDrift_syncCacheLock();
|
||||
|
||||
// USE_SESSIONS
|
||||
if (mSession != null) {
|
||||
int pbState = PlaybackState.getStateFromRccState(state);
|
||||
@@ -707,29 +691,7 @@ public class RemoteControlClient
|
||||
}
|
||||
}
|
||||
|
||||
private void initiateCheckForDrift_syncCacheLock() {
|
||||
if (mEventHandler == null) {
|
||||
return;
|
||||
}
|
||||
mEventHandler.removeMessages(MSG_POSITION_DRIFT_CHECK);
|
||||
if (!mNeedsPositionSync) {
|
||||
return;
|
||||
}
|
||||
if (mPlaybackPositionMs < 0) {
|
||||
// the current playback state has no known playback position, it's no use
|
||||
// trying to see if there is any drift at this point
|
||||
// (this also bypasses this mechanism for older apps that use the old
|
||||
// setPlaybackState(int) API)
|
||||
return;
|
||||
}
|
||||
if (playbackPositionShouldMove(mPlaybackState)) {
|
||||
// playback position moving, schedule next position drift check
|
||||
mEventHandler.sendMessageDelayed(
|
||||
mEventHandler.obtainMessage(MSG_POSITION_DRIFT_CHECK),
|
||||
getCheckPeriodFromSpeed(mPlaybackSpeed));
|
||||
}
|
||||
}
|
||||
|
||||
// TODO investigate if we still need position drift checking
|
||||
private void onPositionDriftCheck() {
|
||||
if (DEBUG) { Log.d(TAG, "onPositionDriftCheck()"); }
|
||||
synchronized(mCacheLock) {
|
||||
@@ -781,9 +743,6 @@ public class RemoteControlClient
|
||||
// store locally
|
||||
mTransportControlFlags = transportControlFlags;
|
||||
|
||||
// send to remote control display if conditions are met
|
||||
sendTransportControlInfo_syncCacheLock(null);
|
||||
|
||||
// USE_SESSIONS
|
||||
if (mSession != null) {
|
||||
mSessionPlaybackState.setActions(PlaybackState
|
||||
@@ -866,17 +825,7 @@ public class RemoteControlClient
|
||||
*/
|
||||
public void setPlaybackPositionUpdateListener(OnPlaybackPositionUpdateListener l) {
|
||||
synchronized(mCacheLock) {
|
||||
int oldCapa = mPlaybackPositionCapabilities;
|
||||
if (l != null) {
|
||||
mPlaybackPositionCapabilities |= MEDIA_POSITION_WRITABLE;
|
||||
} else {
|
||||
mPlaybackPositionCapabilities &= ~MEDIA_POSITION_WRITABLE;
|
||||
}
|
||||
mPositionUpdateListener = l;
|
||||
if (oldCapa != mPlaybackPositionCapabilities) {
|
||||
// tell RCDs that this RCC's playback position capabilities have changed
|
||||
sendTransportControlInfo_syncCacheLock(null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -888,17 +837,7 @@ public class RemoteControlClient
|
||||
*/
|
||||
public void setOnGetPlaybackPositionListener(OnGetPlaybackPositionListener l) {
|
||||
synchronized(mCacheLock) {
|
||||
int oldCapa = mPlaybackPositionCapabilities;
|
||||
if (l != null) {
|
||||
mPlaybackPositionCapabilities |= MEDIA_POSITION_READABLE;
|
||||
} else {
|
||||
mPlaybackPositionCapabilities &= ~MEDIA_POSITION_READABLE;
|
||||
}
|
||||
mPositionProvider = l;
|
||||
if (oldCapa != mPlaybackPositionCapabilities) {
|
||||
// tell RCDs that this RCC's playback position capabilities have changed
|
||||
sendTransportControlInfo_syncCacheLock(null);
|
||||
}
|
||||
if ((mPositionProvider != null) && (mEventHandler != null)
|
||||
&& playbackPositionShouldMove(mPlaybackState)) {
|
||||
// playback position is already moving, but now we have a position provider,
|
||||
@@ -925,124 +864,12 @@ public class RemoteControlClient
|
||||
*/
|
||||
public static int MEDIA_POSITION_WRITABLE = 1 << 1;
|
||||
|
||||
private int mPlaybackPositionCapabilities = 0;
|
||||
|
||||
/** @hide */
|
||||
public final static int DEFAULT_PLAYBACK_VOLUME_HANDLING = PLAYBACK_VOLUME_VARIABLE;
|
||||
/** @hide */
|
||||
// hard-coded to the same number of steps as AudioService.MAX_STREAM_VOLUME[STREAM_MUSIC]
|
||||
public final static int DEFAULT_PLAYBACK_VOLUME = 15;
|
||||
|
||||
private int mPlaybackType = PLAYBACK_TYPE_LOCAL;
|
||||
private int mPlaybackVolumeMax = DEFAULT_PLAYBACK_VOLUME;
|
||||
private int mPlaybackVolume = DEFAULT_PLAYBACK_VOLUME;
|
||||
private int mPlaybackVolumeHandling = DEFAULT_PLAYBACK_VOLUME_HANDLING;
|
||||
private int mPlaybackStream = AudioManager.STREAM_MUSIC;
|
||||
|
||||
/**
|
||||
* @hide
|
||||
* Set information describing information related to the playback of media so the system
|
||||
* can implement additional behavior to handle non-local playback usecases.
|
||||
* @param what a key to specify the type of information to set. Valid keys are
|
||||
* {@link #PLAYBACKINFO_PLAYBACK_TYPE},
|
||||
* {@link #PLAYBACKINFO_USES_STREAM},
|
||||
* {@link #PLAYBACKINFO_VOLUME},
|
||||
* {@link #PLAYBACKINFO_VOLUME_MAX},
|
||||
* and {@link #PLAYBACKINFO_VOLUME_HANDLING}.
|
||||
* @param value the value for the supplied information to set.
|
||||
*/
|
||||
public void setPlaybackInformation(int what, int value) {
|
||||
synchronized(mCacheLock) {
|
||||
switch (what) {
|
||||
case PLAYBACKINFO_PLAYBACK_TYPE:
|
||||
if ((value >= PLAYBACK_TYPE_MIN) && (value <= PLAYBACK_TYPE_MAX)) {
|
||||
if (mPlaybackType != value) {
|
||||
mPlaybackType = value;
|
||||
sendAudioServiceNewPlaybackInfo_syncCacheLock(what, value);
|
||||
}
|
||||
} else {
|
||||
Log.w(TAG, "using invalid value for PLAYBACKINFO_PLAYBACK_TYPE");
|
||||
}
|
||||
break;
|
||||
case PLAYBACKINFO_VOLUME:
|
||||
if ((value > -1) && (value <= mPlaybackVolumeMax)) {
|
||||
if (mPlaybackVolume != value) {
|
||||
mPlaybackVolume = value;
|
||||
sendAudioServiceNewPlaybackInfo_syncCacheLock(what, value);
|
||||
}
|
||||
} else {
|
||||
Log.w(TAG, "using invalid value for PLAYBACKINFO_VOLUME");
|
||||
}
|
||||
break;
|
||||
case PLAYBACKINFO_VOLUME_MAX:
|
||||
if (value > 0) {
|
||||
if (mPlaybackVolumeMax != value) {
|
||||
mPlaybackVolumeMax = value;
|
||||
sendAudioServiceNewPlaybackInfo_syncCacheLock(what, value);
|
||||
}
|
||||
} else {
|
||||
Log.w(TAG, "using invalid value for PLAYBACKINFO_VOLUME_MAX");
|
||||
}
|
||||
break;
|
||||
case PLAYBACKINFO_USES_STREAM:
|
||||
if ((value >= 0) && (value < AudioSystem.getNumStreamTypes())) {
|
||||
mPlaybackStream = value;
|
||||
} else {
|
||||
Log.w(TAG, "using invalid value for PLAYBACKINFO_USES_STREAM");
|
||||
}
|
||||
break;
|
||||
case PLAYBACKINFO_VOLUME_HANDLING:
|
||||
if ((value >= PLAYBACK_VOLUME_FIXED) && (value <= PLAYBACK_VOLUME_VARIABLE)) {
|
||||
if (mPlaybackVolumeHandling != value) {
|
||||
mPlaybackVolumeHandling = value;
|
||||
sendAudioServiceNewPlaybackInfo_syncCacheLock(what, value);
|
||||
}
|
||||
} else {
|
||||
Log.w(TAG, "using invalid value for PLAYBACKINFO_VOLUME_HANDLING");
|
||||
}
|
||||
break;
|
||||
default:
|
||||
// not throwing an exception or returning an error if more keys are to be
|
||||
// supported in the future
|
||||
Log.w(TAG, "setPlaybackInformation() ignoring unknown key " + what);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @hide
|
||||
* Return playback information represented as an integer value.
|
||||
* @param what a key to specify the type of information to retrieve. Valid keys are
|
||||
* {@link #PLAYBACKINFO_PLAYBACK_TYPE},
|
||||
* {@link #PLAYBACKINFO_USES_STREAM},
|
||||
* {@link #PLAYBACKINFO_VOLUME},
|
||||
* {@link #PLAYBACKINFO_VOLUME_MAX},
|
||||
* and {@link #PLAYBACKINFO_VOLUME_HANDLING}.
|
||||
* @return the current value for the given information type, or
|
||||
* {@link #PLAYBACKINFO_INVALID_VALUE} if an error occurred or the request is invalid, or
|
||||
* the value is unknown.
|
||||
*/
|
||||
public int getIntPlaybackInformation(int what) {
|
||||
synchronized(mCacheLock) {
|
||||
switch (what) {
|
||||
case PLAYBACKINFO_PLAYBACK_TYPE:
|
||||
return mPlaybackType;
|
||||
case PLAYBACKINFO_VOLUME:
|
||||
return mPlaybackVolume;
|
||||
case PLAYBACKINFO_VOLUME_MAX:
|
||||
return mPlaybackVolumeMax;
|
||||
case PLAYBACKINFO_USES_STREAM:
|
||||
return mPlaybackStream;
|
||||
case PLAYBACKINFO_VOLUME_HANDLING:
|
||||
return mPlaybackVolumeHandling;
|
||||
default:
|
||||
Log.e(TAG, "getIntPlaybackInformation() unknown key " + what);
|
||||
return PLAYBACKINFO_INVALID_VALUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Lock for all cached data
|
||||
*/
|
||||
@@ -1102,13 +929,6 @@ public class RemoteControlClient
|
||||
* The current remote control client generation ID across the system, as known by this object
|
||||
*/
|
||||
private int mCurrentClientGenId = -1;
|
||||
/**
|
||||
* The remote control client generation ID, the last time it was told it was the current RC.
|
||||
* If (mCurrentClientGenId == mInternalClientGenId) is true, it means that this remote control
|
||||
* client is the "focused" one, and that whenever this client's info is updated, it needs to
|
||||
* send it to the known IRemoteControlDisplay interfaces.
|
||||
*/
|
||||
private int mInternalClientGenId = -2;
|
||||
|
||||
/**
|
||||
* The media button intent description associated with this remote control client
|
||||
@@ -1133,31 +953,6 @@ public class RemoteControlClient
|
||||
*/
|
||||
private MediaMetadata mMediaMetadata;
|
||||
|
||||
/**
|
||||
* A class to encapsulate all the information about a remote control display.
|
||||
* A RemoteControlClient's metadata and state may be displayed on multiple IRemoteControlDisplay
|
||||
*/
|
||||
private class DisplayInfoForClient {
|
||||
/** may never be null */
|
||||
private IRemoteControlDisplay mRcDisplay;
|
||||
private int mArtworkExpectedWidth;
|
||||
private int mArtworkExpectedHeight;
|
||||
private boolean mWantsPositionSync = false;
|
||||
private boolean mEnabled = true;
|
||||
|
||||
DisplayInfoForClient(IRemoteControlDisplay rcd, int w, int h) {
|
||||
mRcDisplay = rcd;
|
||||
mArtworkExpectedWidth = w;
|
||||
mArtworkExpectedHeight = h;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The list of remote control displays to which this client will send information.
|
||||
* Accessed and modified synchronized on mCacheLock
|
||||
*/
|
||||
private ArrayList<DisplayInfoForClient> mRcDisplays = new ArrayList<DisplayInfoForClient>(1);
|
||||
|
||||
/**
|
||||
* @hide
|
||||
* Accessor to media button intent description (includes target component)
|
||||
@@ -1165,155 +960,12 @@ public class RemoteControlClient
|
||||
public PendingIntent getRcMediaIntent() {
|
||||
return mRcMediaIntent;
|
||||
}
|
||||
/**
|
||||
* @hide
|
||||
* Accessor to IRemoteControlClient
|
||||
*/
|
||||
public IRemoteControlClient getIRemoteControlClient() {
|
||||
return mIRCC;
|
||||
}
|
||||
|
||||
/**
|
||||
* The IRemoteControlClient implementation
|
||||
*/
|
||||
private final IRemoteControlClient mIRCC = new IRemoteControlClient.Stub() {
|
||||
|
||||
//TODO change name to informationRequestForAllDisplays()
|
||||
public void onInformationRequested(int generationId, int infoFlags) {
|
||||
// only post messages, we can't block here
|
||||
if (mEventHandler != null) {
|
||||
// signal new client
|
||||
mEventHandler.removeMessages(MSG_NEW_INTERNAL_CLIENT_GEN);
|
||||
mEventHandler.sendMessage(
|
||||
mEventHandler.obtainMessage(MSG_NEW_INTERNAL_CLIENT_GEN,
|
||||
/*arg1*/ generationId, /*arg2, ignored*/ 0));
|
||||
// send the information
|
||||
mEventHandler.removeMessages(MSG_REQUEST_PLAYBACK_STATE);
|
||||
mEventHandler.removeMessages(MSG_REQUEST_METADATA);
|
||||
mEventHandler.removeMessages(MSG_REQUEST_TRANSPORTCONTROL);
|
||||
mEventHandler.removeMessages(MSG_REQUEST_ARTWORK);
|
||||
mEventHandler.removeMessages(MSG_REQUEST_METADATA_ARTWORK);
|
||||
mEventHandler.sendMessage(
|
||||
mEventHandler.obtainMessage(MSG_REQUEST_PLAYBACK_STATE, null));
|
||||
mEventHandler.sendMessage(
|
||||
mEventHandler.obtainMessage(MSG_REQUEST_TRANSPORTCONTROL, null));
|
||||
mEventHandler.sendMessage(mEventHandler.obtainMessage(MSG_REQUEST_METADATA_ARTWORK,
|
||||
0, 0, null));
|
||||
}
|
||||
}
|
||||
|
||||
public void informationRequestForDisplay(IRemoteControlDisplay rcd, int w, int h) {
|
||||
// only post messages, we can't block here
|
||||
if (mEventHandler != null) {
|
||||
mEventHandler.sendMessage(
|
||||
mEventHandler.obtainMessage(MSG_REQUEST_TRANSPORTCONTROL, rcd));
|
||||
mEventHandler.sendMessage(
|
||||
mEventHandler.obtainMessage(MSG_REQUEST_PLAYBACK_STATE, rcd));
|
||||
if ((w > 0) && (h > 0)) {
|
||||
mEventHandler.sendMessage(
|
||||
mEventHandler.obtainMessage(MSG_REQUEST_METADATA_ARTWORK, w, h, rcd));
|
||||
} else {
|
||||
mEventHandler.sendMessage(
|
||||
mEventHandler.obtainMessage(MSG_REQUEST_METADATA, rcd));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void setCurrentClientGenerationId(int clientGeneration) {
|
||||
// only post messages, we can't block here
|
||||
if (mEventHandler != null) {
|
||||
mEventHandler.removeMessages(MSG_NEW_CURRENT_CLIENT_GEN);
|
||||
mEventHandler.sendMessage(mEventHandler.obtainMessage(
|
||||
MSG_NEW_CURRENT_CLIENT_GEN, clientGeneration, 0/*ignored*/));
|
||||
}
|
||||
}
|
||||
|
||||
public void plugRemoteControlDisplay(IRemoteControlDisplay rcd, int w, int h) {
|
||||
// only post messages, we can't block here
|
||||
if ((mEventHandler != null) && (rcd != null)) {
|
||||
mEventHandler.sendMessage(mEventHandler.obtainMessage(
|
||||
MSG_PLUG_DISPLAY, w, h, rcd));
|
||||
}
|
||||
}
|
||||
|
||||
public void unplugRemoteControlDisplay(IRemoteControlDisplay rcd) {
|
||||
// only post messages, we can't block here
|
||||
if ((mEventHandler != null) && (rcd != null)) {
|
||||
mEventHandler.sendMessage(mEventHandler.obtainMessage(
|
||||
MSG_UNPLUG_DISPLAY, rcd));
|
||||
}
|
||||
}
|
||||
|
||||
public void setBitmapSizeForDisplay(IRemoteControlDisplay rcd, int w, int h) {
|
||||
// only post messages, we can't block here
|
||||
if ((mEventHandler != null) && (rcd != null)) {
|
||||
mEventHandler.sendMessage(mEventHandler.obtainMessage(
|
||||
MSG_UPDATE_DISPLAY_ARTWORK_SIZE, w, h, rcd));
|
||||
}
|
||||
}
|
||||
|
||||
public void setWantsSyncForDisplay(IRemoteControlDisplay rcd, boolean wantsSync) {
|
||||
// only post messages, we can't block here
|
||||
if ((mEventHandler != null) && (rcd != null)) {
|
||||
mEventHandler.sendMessage(mEventHandler.obtainMessage(
|
||||
MSG_DISPLAY_WANTS_POS_SYNC, wantsSync ? 1 : 0, 0/*arg2 ignored*/, rcd));
|
||||
}
|
||||
}
|
||||
|
||||
public void enableRemoteControlDisplay(IRemoteControlDisplay rcd, boolean enabled) {
|
||||
// only post messages, we can't block here
|
||||
if ((mEventHandler != null) && (rcd != null)) {
|
||||
mEventHandler.sendMessage(mEventHandler.obtainMessage(
|
||||
MSG_DISPLAY_ENABLE, enabled ? 1 : 0, 0/*arg2 ignored*/, rcd));
|
||||
}
|
||||
}
|
||||
|
||||
public void seekTo(int generationId, long timeMs) {
|
||||
// only post messages, we can't block here
|
||||
if (mEventHandler != null) {
|
||||
mEventHandler.removeMessages(MSG_SEEK_TO);
|
||||
mEventHandler.sendMessage(mEventHandler.obtainMessage(
|
||||
MSG_SEEK_TO, generationId /* arg1 */, 0 /* arg2, ignored */,
|
||||
new Long(timeMs)));
|
||||
}
|
||||
}
|
||||
|
||||
public void updateMetadata(int generationId, int key, Rating value) {
|
||||
// only post messages, we can't block here
|
||||
if (mEventHandler != null) {
|
||||
mEventHandler.sendMessage(mEventHandler.obtainMessage(
|
||||
MSG_UPDATE_METADATA, generationId /* arg1 */, key /* arg2*/, value));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @hide
|
||||
* Default value for the unique identifier
|
||||
*/
|
||||
public final static int RCSE_ID_UNREGISTERED = -1;
|
||||
/**
|
||||
* Unique identifier of the RemoteControlStackEntry in AudioService with which
|
||||
* this RemoteControlClient is associated.
|
||||
*/
|
||||
private int mRcseId = RCSE_ID_UNREGISTERED;
|
||||
/**
|
||||
* @hide
|
||||
* To be only used by AudioManager after it has received the unique id from
|
||||
* IAudioService.registerRemoteControlClient()
|
||||
* @param id the unique identifier of the RemoteControlStackEntry in AudioService with which
|
||||
* this RemoteControlClient is associated.
|
||||
*/
|
||||
public void setRcseId(int id) {
|
||||
mRcseId = id;
|
||||
}
|
||||
|
||||
/**
|
||||
* @hide
|
||||
*/
|
||||
public int getRcseId() {
|
||||
return mRcseId;
|
||||
}
|
||||
|
||||
// USE_SESSIONS
|
||||
private MediaSession.TransportControlsCallback mTransportListener
|
||||
@@ -1327,31 +979,13 @@ public class RemoteControlClient
|
||||
@Override
|
||||
public void onSetRating(Rating rating) {
|
||||
if ((mTransportControlFlags & FLAG_KEY_MEDIA_RATING) != 0) {
|
||||
if (mEventHandler != null) {
|
||||
mEventHandler.sendMessage(mEventHandler.obtainMessage(
|
||||
MSG_UPDATE_METADATA, mCurrentClientGenId,
|
||||
MetadataEditor.RATING_KEY_BY_USER, rating));
|
||||
}
|
||||
onUpdateMetadata(mCurrentClientGenId, MetadataEditor.RATING_KEY_BY_USER, rating);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
private EventHandler mEventHandler;
|
||||
private final static int MSG_REQUEST_PLAYBACK_STATE = 1;
|
||||
private final static int MSG_REQUEST_METADATA = 2;
|
||||
private final static int MSG_REQUEST_TRANSPORTCONTROL = 3;
|
||||
private final static int MSG_REQUEST_ARTWORK = 4;
|
||||
private final static int MSG_NEW_INTERNAL_CLIENT_GEN = 5;
|
||||
private final static int MSG_NEW_CURRENT_CLIENT_GEN = 6;
|
||||
private final static int MSG_PLUG_DISPLAY = 7;
|
||||
private final static int MSG_UNPLUG_DISPLAY = 8;
|
||||
private final static int MSG_UPDATE_DISPLAY_ARTWORK_SIZE = 9;
|
||||
private final static int MSG_SEEK_TO = 10;
|
||||
private final static int MSG_POSITION_DRIFT_CHECK = 11;
|
||||
private final static int MSG_DISPLAY_WANTS_POS_SYNC = 12;
|
||||
private final static int MSG_UPDATE_METADATA = 13;
|
||||
private final static int MSG_REQUEST_METADATA_ARTWORK = 14;
|
||||
private final static int MSG_DISPLAY_ENABLE = 15;
|
||||
|
||||
private class EventHandler extends Handler {
|
||||
public EventHandler(RemoteControlClient rcc, Looper looper) {
|
||||
@@ -1361,410 +995,18 @@ public class RemoteControlClient
|
||||
@Override
|
||||
public void handleMessage(Message msg) {
|
||||
switch(msg.what) {
|
||||
case MSG_REQUEST_PLAYBACK_STATE:
|
||||
synchronized (mCacheLock) {
|
||||
sendPlaybackState_syncCacheLock((IRemoteControlDisplay)msg.obj);
|
||||
}
|
||||
break;
|
||||
case MSG_REQUEST_METADATA:
|
||||
synchronized (mCacheLock) {
|
||||
sendMetadata_syncCacheLock((IRemoteControlDisplay)msg.obj);
|
||||
}
|
||||
break;
|
||||
case MSG_REQUEST_TRANSPORTCONTROL:
|
||||
synchronized (mCacheLock) {
|
||||
sendTransportControlInfo_syncCacheLock((IRemoteControlDisplay)msg.obj);
|
||||
}
|
||||
break;
|
||||
case MSG_REQUEST_ARTWORK:
|
||||
synchronized (mCacheLock) {
|
||||
sendArtwork_syncCacheLock((IRemoteControlDisplay)msg.obj,
|
||||
msg.arg1, msg.arg2);
|
||||
}
|
||||
break;
|
||||
case MSG_REQUEST_METADATA_ARTWORK:
|
||||
synchronized (mCacheLock) {
|
||||
sendMetadataWithArtwork_syncCacheLock((IRemoteControlDisplay)msg.obj,
|
||||
msg.arg1, msg.arg2);
|
||||
}
|
||||
break;
|
||||
case MSG_NEW_INTERNAL_CLIENT_GEN:
|
||||
onNewInternalClientGen(msg.arg1);
|
||||
break;
|
||||
case MSG_NEW_CURRENT_CLIENT_GEN:
|
||||
onNewCurrentClientGen(msg.arg1);
|
||||
break;
|
||||
case MSG_PLUG_DISPLAY:
|
||||
onPlugDisplay((IRemoteControlDisplay)msg.obj, msg.arg1, msg.arg2);
|
||||
break;
|
||||
case MSG_UNPLUG_DISPLAY:
|
||||
onUnplugDisplay((IRemoteControlDisplay)msg.obj);
|
||||
break;
|
||||
case MSG_UPDATE_DISPLAY_ARTWORK_SIZE:
|
||||
onUpdateDisplayArtworkSize((IRemoteControlDisplay)msg.obj, msg.arg1, msg.arg2);
|
||||
break;
|
||||
case MSG_SEEK_TO:
|
||||
onSeekTo(msg.arg1, ((Long)msg.obj).longValue());
|
||||
break;
|
||||
case MSG_POSITION_DRIFT_CHECK:
|
||||
onPositionDriftCheck();
|
||||
break;
|
||||
case MSG_DISPLAY_WANTS_POS_SYNC:
|
||||
onDisplayWantsSync((IRemoteControlDisplay)msg.obj, msg.arg1 == 1);
|
||||
break;
|
||||
case MSG_UPDATE_METADATA:
|
||||
onUpdateMetadata(msg.arg1, msg.arg2, msg.obj);
|
||||
break;
|
||||
case MSG_DISPLAY_ENABLE:
|
||||
onDisplayEnable((IRemoteControlDisplay)msg.obj, msg.arg1 == 1);
|
||||
break;
|
||||
default:
|
||||
Log.e(TAG, "Unknown event " + msg.what + " in RemoteControlClient handler");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//===========================================================
|
||||
// Communication with the IRemoteControlDisplay (the displays known to the system)
|
||||
|
||||
private void sendPlaybackState_syncCacheLock(IRemoteControlDisplay target) {
|
||||
if (mCurrentClientGenId == mInternalClientGenId) {
|
||||
if (target != null) {
|
||||
try {
|
||||
target.setPlaybackState(mInternalClientGenId,
|
||||
mPlaybackState, mPlaybackStateChangeTimeMs, mPlaybackPositionMs,
|
||||
mPlaybackSpeed);
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, "Error in setPlaybackState() for dead display " + target, e);
|
||||
}
|
||||
return;
|
||||
}
|
||||
// target == null implies all displays must be updated
|
||||
final Iterator<DisplayInfoForClient> displayIterator = mRcDisplays.iterator();
|
||||
while (displayIterator.hasNext()) {
|
||||
final DisplayInfoForClient di = displayIterator.next();
|
||||
if (di.mEnabled) {
|
||||
try {
|
||||
di.mRcDisplay.setPlaybackState(mInternalClientGenId,
|
||||
mPlaybackState, mPlaybackStateChangeTimeMs, mPlaybackPositionMs,
|
||||
mPlaybackSpeed);
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, "Error in setPlaybackState(), dead display " + di.mRcDisplay, e);
|
||||
displayIterator.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void sendMetadata_syncCacheLock(IRemoteControlDisplay target) {
|
||||
if (mCurrentClientGenId == mInternalClientGenId) {
|
||||
if (target != null) {
|
||||
try {
|
||||
target.setMetadata(mInternalClientGenId, mMetadata);
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, "Error in setMetadata() for dead display " + target, e);
|
||||
}
|
||||
return;
|
||||
}
|
||||
// target == null implies all displays must be updated
|
||||
final Iterator<DisplayInfoForClient> displayIterator = mRcDisplays.iterator();
|
||||
while (displayIterator.hasNext()) {
|
||||
final DisplayInfoForClient di = displayIterator.next();
|
||||
if (di.mEnabled) {
|
||||
try {
|
||||
di.mRcDisplay.setMetadata(mInternalClientGenId, mMetadata);
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, "Error in setMetadata(), dead display " + di.mRcDisplay, e);
|
||||
displayIterator.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void sendTransportControlInfo_syncCacheLock(IRemoteControlDisplay target) {
|
||||
if (mCurrentClientGenId == mInternalClientGenId) {
|
||||
if (target != null) {
|
||||
try {
|
||||
target.setTransportControlInfo(mInternalClientGenId,
|
||||
mTransportControlFlags, mPlaybackPositionCapabilities);
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, "Error in setTransportControlFlags() for dead display " + target,
|
||||
e);
|
||||
}
|
||||
return;
|
||||
}
|
||||
// target == null implies all displays must be updated
|
||||
final Iterator<DisplayInfoForClient> displayIterator = mRcDisplays.iterator();
|
||||
while (displayIterator.hasNext()) {
|
||||
final DisplayInfoForClient di = displayIterator.next();
|
||||
if (di.mEnabled) {
|
||||
try {
|
||||
di.mRcDisplay.setTransportControlInfo(mInternalClientGenId,
|
||||
mTransportControlFlags, mPlaybackPositionCapabilities);
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, "Error in setTransportControlFlags(), dead display " + di.mRcDisplay,
|
||||
e);
|
||||
displayIterator.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void sendArtwork_syncCacheLock(IRemoteControlDisplay target, int w, int h) {
|
||||
// FIXME modify to cache all requested sizes?
|
||||
if (mCurrentClientGenId == mInternalClientGenId) {
|
||||
if (target != null) {
|
||||
final DisplayInfoForClient di = new DisplayInfoForClient(target, w, h);
|
||||
sendArtworkToDisplay(di);
|
||||
return;
|
||||
}
|
||||
// target == null implies all displays must be updated
|
||||
final Iterator<DisplayInfoForClient> displayIterator = mRcDisplays.iterator();
|
||||
while (displayIterator.hasNext()) {
|
||||
if (!sendArtworkToDisplay(displayIterator.next())) {
|
||||
displayIterator.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Send artwork to an IRemoteControlDisplay.
|
||||
* @param di encapsulates the IRemoteControlDisplay that will receive the artwork, and its
|
||||
* dimension requirements.
|
||||
* @return false if there was an error communicating with the IRemoteControlDisplay.
|
||||
*/
|
||||
private boolean sendArtworkToDisplay(DisplayInfoForClient di) {
|
||||
if ((di.mArtworkExpectedWidth > 0) && (di.mArtworkExpectedHeight > 0)) {
|
||||
Bitmap artwork = scaleBitmapIfTooBig(mOriginalArtwork,
|
||||
di.mArtworkExpectedWidth, di.mArtworkExpectedHeight);
|
||||
try {
|
||||
di.mRcDisplay.setArtwork(mInternalClientGenId, artwork);
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, "Error in sendArtworkToDisplay(), dead display " + di.mRcDisplay, e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private void sendMetadataWithArtwork_syncCacheLock(IRemoteControlDisplay target, int w, int h) {
|
||||
// FIXME modify to cache all requested sizes?
|
||||
if (mCurrentClientGenId == mInternalClientGenId) {
|
||||
if (target != null) {
|
||||
try {
|
||||
if ((w > 0) && (h > 0)) {
|
||||
Bitmap artwork = scaleBitmapIfTooBig(mOriginalArtwork, w, h);
|
||||
target.setAllMetadata(mInternalClientGenId, mMetadata, artwork);
|
||||
} else {
|
||||
target.setMetadata(mInternalClientGenId, mMetadata);
|
||||
}
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, "Error in set(All)Metadata() for dead display " + target, e);
|
||||
}
|
||||
return;
|
||||
}
|
||||
// target == null implies all displays must be updated
|
||||
final Iterator<DisplayInfoForClient> displayIterator = mRcDisplays.iterator();
|
||||
while (displayIterator.hasNext()) {
|
||||
final DisplayInfoForClient di = displayIterator.next();
|
||||
try {
|
||||
if (di.mEnabled) {
|
||||
if ((di.mArtworkExpectedWidth > 0) && (di.mArtworkExpectedHeight > 0)) {
|
||||
Bitmap artwork = scaleBitmapIfTooBig(mOriginalArtwork,
|
||||
di.mArtworkExpectedWidth, di.mArtworkExpectedHeight);
|
||||
di.mRcDisplay.setAllMetadata(mInternalClientGenId, mMetadata, artwork);
|
||||
} else {
|
||||
di.mRcDisplay.setMetadata(mInternalClientGenId, mMetadata);
|
||||
}
|
||||
}
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, "Error when setting metadata, dead display " + di.mRcDisplay, e);
|
||||
displayIterator.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//===========================================================
|
||||
// Communication with AudioService
|
||||
|
||||
private static IAudioService sService;
|
||||
|
||||
private static IAudioService getService()
|
||||
{
|
||||
if (sService != null) {
|
||||
return sService;
|
||||
}
|
||||
IBinder b = ServiceManager.getService(Context.AUDIO_SERVICE);
|
||||
sService = IAudioService.Stub.asInterface(b);
|
||||
return sService;
|
||||
}
|
||||
|
||||
private void sendAudioServiceNewPlaybackInfo_syncCacheLock(int what, int value) {
|
||||
if (mRcseId == RCSE_ID_UNREGISTERED) {
|
||||
return;
|
||||
}
|
||||
//Log.d(TAG, "sending to AudioService key=" + what + ", value=" + value);
|
||||
IAudioService service = getService();
|
||||
try {
|
||||
service.setPlaybackInfoForRcc(mRcseId, what, value);
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, "Dead object in setPlaybackInfoForRcc", e);
|
||||
}
|
||||
}
|
||||
|
||||
private void sendAudioServiceNewPlaybackState_syncCacheLock() {
|
||||
if (mRcseId == RCSE_ID_UNREGISTERED) {
|
||||
return;
|
||||
}
|
||||
IAudioService service = getService();
|
||||
try {
|
||||
service.setPlaybackStateForRcc(mRcseId,
|
||||
mPlaybackState, mPlaybackPositionMs, mPlaybackSpeed);
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, "Dead object in setPlaybackStateForRcc", e);
|
||||
}
|
||||
}
|
||||
|
||||
//===========================================================
|
||||
// Message handlers
|
||||
|
||||
private void onNewInternalClientGen(int clientGeneration) {
|
||||
synchronized (mCacheLock) {
|
||||
// this remote control client is told it is the "focused" one:
|
||||
// it implies that now (mCurrentClientGenId == mInternalClientGenId) is true
|
||||
mInternalClientGenId = clientGeneration;
|
||||
}
|
||||
}
|
||||
|
||||
private void onNewCurrentClientGen(int clientGeneration) {
|
||||
synchronized (mCacheLock) {
|
||||
mCurrentClientGenId = clientGeneration;
|
||||
}
|
||||
}
|
||||
|
||||
/** pre-condition rcd != null */
|
||||
private void onPlugDisplay(IRemoteControlDisplay rcd, int w, int h) {
|
||||
synchronized(mCacheLock) {
|
||||
// do we have this display already?
|
||||
boolean displayKnown = false;
|
||||
final Iterator<DisplayInfoForClient> displayIterator = mRcDisplays.iterator();
|
||||
while (displayIterator.hasNext() && !displayKnown) {
|
||||
final DisplayInfoForClient di = displayIterator.next();
|
||||
displayKnown = di.mRcDisplay.asBinder().equals(rcd.asBinder());
|
||||
if (displayKnown) {
|
||||
// this display was known but the change in artwork size will cause the
|
||||
// artwork to be refreshed
|
||||
if ((di.mArtworkExpectedWidth != w) || (di.mArtworkExpectedHeight != h)) {
|
||||
di.mArtworkExpectedWidth = w;
|
||||
di.mArtworkExpectedHeight = h;
|
||||
if (!sendArtworkToDisplay(di)) {
|
||||
displayIterator.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!displayKnown) {
|
||||
mRcDisplays.add(new DisplayInfoForClient(rcd, w, h));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** pre-condition rcd != null */
|
||||
private void onUnplugDisplay(IRemoteControlDisplay rcd) {
|
||||
synchronized(mCacheLock) {
|
||||
Iterator<DisplayInfoForClient> displayIterator = mRcDisplays.iterator();
|
||||
while (displayIterator.hasNext()) {
|
||||
final DisplayInfoForClient di = displayIterator.next();
|
||||
if (di.mRcDisplay.asBinder().equals(rcd.asBinder())) {
|
||||
displayIterator.remove();
|
||||
break;
|
||||
}
|
||||
}
|
||||
// list of RCDs has changed, reevaluate whether position check is still needed
|
||||
boolean oldNeedsPositionSync = mNeedsPositionSync;
|
||||
boolean newNeedsPositionSync = false;
|
||||
displayIterator = mRcDisplays.iterator();
|
||||
while (displayIterator.hasNext()) {
|
||||
final DisplayInfoForClient di = displayIterator.next();
|
||||
if (di.mWantsPositionSync) {
|
||||
newNeedsPositionSync = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
mNeedsPositionSync = newNeedsPositionSync;
|
||||
if (oldNeedsPositionSync != mNeedsPositionSync) {
|
||||
// update needed?
|
||||
initiateCheckForDrift_syncCacheLock();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** pre-condition rcd != null */
|
||||
private void onUpdateDisplayArtworkSize(IRemoteControlDisplay rcd, int w, int h) {
|
||||
synchronized(mCacheLock) {
|
||||
final Iterator<DisplayInfoForClient> displayIterator = mRcDisplays.iterator();
|
||||
while (displayIterator.hasNext()) {
|
||||
final DisplayInfoForClient di = displayIterator.next();
|
||||
if (di.mRcDisplay.asBinder().equals(rcd.asBinder()) &&
|
||||
((di.mArtworkExpectedWidth != w) || (di.mArtworkExpectedHeight != h))) {
|
||||
di.mArtworkExpectedWidth = w;
|
||||
di.mArtworkExpectedHeight = h;
|
||||
if (di.mEnabled) {
|
||||
if (!sendArtworkToDisplay(di)) {
|
||||
displayIterator.remove();
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** pre-condition rcd != null */
|
||||
private void onDisplayWantsSync(IRemoteControlDisplay rcd, boolean wantsSync) {
|
||||
synchronized(mCacheLock) {
|
||||
boolean oldNeedsPositionSync = mNeedsPositionSync;
|
||||
boolean newNeedsPositionSync = false;
|
||||
final Iterator<DisplayInfoForClient> displayIterator = mRcDisplays.iterator();
|
||||
// go through the list of RCDs and for each entry, check both whether this is the RCD
|
||||
// that gets upated, and whether the list has one entry that wants position sync
|
||||
while (displayIterator.hasNext()) {
|
||||
final DisplayInfoForClient di = displayIterator.next();
|
||||
if (di.mEnabled) {
|
||||
if (di.mRcDisplay.asBinder().equals(rcd.asBinder())) {
|
||||
di.mWantsPositionSync = wantsSync;
|
||||
}
|
||||
if (di.mWantsPositionSync) {
|
||||
newNeedsPositionSync = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
mNeedsPositionSync = newNeedsPositionSync;
|
||||
if (oldNeedsPositionSync != mNeedsPositionSync) {
|
||||
// update needed?
|
||||
initiateCheckForDrift_syncCacheLock();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** pre-condition rcd != null */
|
||||
private void onDisplayEnable(IRemoteControlDisplay rcd, boolean enable) {
|
||||
synchronized(mCacheLock) {
|
||||
final Iterator<DisplayInfoForClient> displayIterator = mRcDisplays.iterator();
|
||||
while (displayIterator.hasNext()) {
|
||||
final DisplayInfoForClient di = displayIterator.next();
|
||||
if (di.mRcDisplay.asBinder().equals(rcd.asBinder())) {
|
||||
di.mEnabled = enable;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void onSeekTo(int generationId, long timeMs) {
|
||||
synchronized (mCacheLock) {
|
||||
if ((mCurrentClientGenId == generationId) && (mPositionUpdateListener != null)) {
|
||||
@@ -1784,42 +1026,6 @@ public class RemoteControlClient
|
||||
//===========================================================
|
||||
// Internal utilities
|
||||
|
||||
/**
|
||||
* Scale a bitmap to fit the smallest dimension by uniformly scaling the incoming bitmap.
|
||||
* If the bitmap fits, then do nothing and return the original.
|
||||
*
|
||||
* @param bitmap
|
||||
* @param maxWidth
|
||||
* @param maxHeight
|
||||
* @return
|
||||
*/
|
||||
|
||||
private Bitmap scaleBitmapIfTooBig(Bitmap bitmap, int maxWidth, int maxHeight) {
|
||||
if (bitmap != null) {
|
||||
final int width = bitmap.getWidth();
|
||||
final int height = bitmap.getHeight();
|
||||
if (width > maxWidth || height > maxHeight) {
|
||||
float scale = Math.min((float) maxWidth / width, (float) maxHeight / height);
|
||||
int newWidth = Math.round(scale * width);
|
||||
int newHeight = Math.round(scale * height);
|
||||
Bitmap.Config newConfig = bitmap.getConfig();
|
||||
if (newConfig == null) {
|
||||
newConfig = Bitmap.Config.ARGB_8888;
|
||||
}
|
||||
Bitmap outBitmap = Bitmap.createBitmap(newWidth, newHeight, newConfig);
|
||||
Canvas canvas = new Canvas(outBitmap);
|
||||
Paint paint = new Paint();
|
||||
paint.setAntiAlias(true);
|
||||
paint.setFilterBitmap(true);
|
||||
canvas.drawBitmap(bitmap, null,
|
||||
new RectF(0, 0, outBitmap.getWidth(), outBitmap.getHeight()), paint);
|
||||
bitmap = outBitmap;
|
||||
}
|
||||
}
|
||||
return bitmap;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns whether, for the given playback state, the playback position is expected to
|
||||
* be changing.
|
||||
|
||||
@@ -40,9 +40,6 @@ public class PhoneFallbackEventHandler implements FallbackEventHandler {
|
||||
private static String TAG = "PhoneFallbackEventHandler";
|
||||
private static final boolean DEBUG = false;
|
||||
|
||||
// Use the new sessions APIs
|
||||
private static final boolean USE_SESSIONS = true;
|
||||
|
||||
Context mContext;
|
||||
View mView;
|
||||
|
||||
@@ -294,21 +291,7 @@ public class PhoneFallbackEventHandler implements FallbackEventHandler {
|
||||
}
|
||||
|
||||
private void handleMediaKeyEvent(KeyEvent keyEvent) {
|
||||
if (USE_SESSIONS) {
|
||||
MediaSessionLegacyHelper.getHelper(mContext).sendMediaButtonEvent(keyEvent, false);
|
||||
} else {
|
||||
IAudioService audioService = IAudioService.Stub.asInterface(
|
||||
ServiceManager.checkService(Context.AUDIO_SERVICE));
|
||||
if (audioService != null) {
|
||||
try {
|
||||
audioService.dispatchMediaKeyEvent(keyEvent);
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, "dispatchMediaKeyEvent threw exception " + e);
|
||||
}
|
||||
} else {
|
||||
Slog.w(TAG, "Unable to find IAudioService for media key event.");
|
||||
}
|
||||
}
|
||||
MediaSessionLegacyHelper.getHelper(mContext).sendMediaButtonEvent(keyEvent, false);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -144,9 +144,6 @@ public class PhoneWindowManager implements WindowManagerPolicy {
|
||||
static final boolean ENABLE_CAR_DOCK_HOME_CAPTURE = true;
|
||||
static final boolean ENABLE_DESK_DOCK_HOME_CAPTURE = false;
|
||||
|
||||
// Whether to use the new Session APIs
|
||||
static final boolean USE_SESSIONS = true;
|
||||
|
||||
static final int SHORT_PRESS_POWER_NOTHING = 0;
|
||||
static final int SHORT_PRESS_POWER_GO_TO_SLEEP = 1;
|
||||
static final int SHORT_PRESS_POWER_REALLY_GO_TO_SLEEP = 2;
|
||||
@@ -3974,6 +3971,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
|
||||
* controlled by this device, or through remote submix).
|
||||
*/
|
||||
boolean isMusicActive() {
|
||||
|
||||
final AudioManager am = (AudioManager)mContext.getSystemService(Context.AUDIO_SERVICE);
|
||||
if (am == null) {
|
||||
Log.w(TAG, "isMusicActive: couldn't get AudioManager reference");
|
||||
@@ -3982,43 +3980,6 @@ public class PhoneWindowManager implements WindowManagerPolicy {
|
||||
return am.isLocalOrRemoteMusicActive();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tell the audio service to adjust the volume appropriate to the event.
|
||||
* @param keycode
|
||||
*/
|
||||
void handleVolumeKey(int stream, int keycode) {
|
||||
IAudioService audioService = getAudioService();
|
||||
if (audioService == null) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
// when audio is playing locally, we shouldn't have to hold a wake lock
|
||||
// during the call, but we do it as a precaution for the rare possibility
|
||||
// that the music stops right before we call this.
|
||||
// Otherwise we might also be in a remote playback case.
|
||||
// TODO: Actually handle MUTE.
|
||||
mBroadcastWakeLock.acquire();
|
||||
if (stream == AudioSystem.STREAM_MUSIC) {
|
||||
audioService.adjustLocalOrRemoteStreamVolume(stream,
|
||||
keycode == KeyEvent.KEYCODE_VOLUME_UP
|
||||
? AudioManager.ADJUST_RAISE
|
||||
: AudioManager.ADJUST_LOWER,
|
||||
mContext.getOpPackageName());
|
||||
} else {
|
||||
audioService.adjustStreamVolume(stream,
|
||||
keycode == KeyEvent.KEYCODE_VOLUME_UP
|
||||
? AudioManager.ADJUST_RAISE
|
||||
: AudioManager.ADJUST_LOWER,
|
||||
0,
|
||||
mContext.getOpPackageName());
|
||||
}
|
||||
} catch (RemoteException e) {
|
||||
Log.w(TAG, "IAudioService.adjust*StreamVolume() threw RemoteException " + e);
|
||||
} finally {
|
||||
mBroadcastWakeLock.release();
|
||||
}
|
||||
}
|
||||
|
||||
final Object mScreenshotLock = new Object();
|
||||
ServiceConnection mScreenshotConnection = null;
|
||||
|
||||
@@ -4201,16 +4162,20 @@ public class PhoneWindowManager implements WindowManagerPolicy {
|
||||
if (telephonyManager.isOffhook()
|
||||
&& (result & ACTION_PASS_TO_USER) == 0) {
|
||||
// If we are in call but we decided not to pass the key to
|
||||
// the application, handle the volume change here.
|
||||
handleVolumeKey(AudioManager.STREAM_VOICE_CALL, keyCode);
|
||||
// the application, just pass it to the session service.
|
||||
|
||||
MediaSessionLegacyHelper.getHelper(mContext)
|
||||
.sendMediaButtonEvent(event, true);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (isMusicActive() && (result & ACTION_PASS_TO_USER) == 0) {
|
||||
// If music is playing but we decided not to pass the key to the
|
||||
// application, handle the volume change here.
|
||||
handleVolumeKey(AudioManager.STREAM_MUSIC, keyCode);
|
||||
if ((result & ACTION_PASS_TO_USER) == 0) {
|
||||
// If we aren't passing to the user and no one else
|
||||
// handled it send it to the session manager to figure
|
||||
// out.
|
||||
MediaSessionLegacyHelper.getHelper(mContext)
|
||||
.sendMediaButtonEvent(event, true);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -4459,18 +4424,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
|
||||
|
||||
void dispatchMediaKeyWithWakeLockToAudioService(KeyEvent event) {
|
||||
if (ActivityManagerNative.isSystemReady()) {
|
||||
if (USE_SESSIONS) {
|
||||
MediaSessionLegacyHelper.getHelper(mContext).sendMediaButtonEvent(event, true);
|
||||
} else {
|
||||
IAudioService audioService = getAudioService();
|
||||
if (audioService != null) {
|
||||
try {
|
||||
audioService.dispatchMediaKeyEventUnderWakelock(event);
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, "dispatchMediaKeyEvent threw exception " + e);
|
||||
}
|
||||
}
|
||||
}
|
||||
MediaSessionLegacyHelper.getHelper(mContext).sendMediaButtonEvent(event, true);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user