Merge "Remote volume handling in MediaRouter" into jb-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
18ddb6ce6f
@@ -193,11 +193,12 @@ LOCAL_SRC_FILES += \
|
|||||||
location/java/android/location/INetInitiatedListener.aidl \
|
location/java/android/location/INetInitiatedListener.aidl \
|
||||||
media/java/android/media/IAudioService.aidl \
|
media/java/android/media/IAudioService.aidl \
|
||||||
media/java/android/media/IAudioFocusDispatcher.aidl \
|
media/java/android/media/IAudioFocusDispatcher.aidl \
|
||||||
media/java/android/media/IAudioRoutesObserver.aidl \
|
media/java/android/media/IAudioRoutesObserver.aidl \
|
||||||
media/java/android/media/IMediaScannerListener.aidl \
|
media/java/android/media/IMediaScannerListener.aidl \
|
||||||
media/java/android/media/IMediaScannerService.aidl \
|
media/java/android/media/IMediaScannerService.aidl \
|
||||||
media/java/android/media/IRemoteControlClient.aidl \
|
media/java/android/media/IRemoteControlClient.aidl \
|
||||||
media/java/android/media/IRemoteControlDisplay.aidl \
|
media/java/android/media/IRemoteControlDisplay.aidl \
|
||||||
|
media/java/android/media/IRemoteVolumeObserver.aidl \
|
||||||
media/java/android/media/IRingtonePlayer.aidl \
|
media/java/android/media/IRingtonePlayer.aidl \
|
||||||
telephony/java/com/android/internal/telephony/IPhoneStateListener.aidl \
|
telephony/java/com/android/internal/telephony/IPhoneStateListener.aidl \
|
||||||
telephony/java/com/android/internal/telephony/IPhoneSubInfo.aidl \
|
telephony/java/com/android/internal/telephony/IPhoneSubInfo.aidl \
|
||||||
|
|||||||
@@ -2152,19 +2152,6 @@ public class Intent implements Parcelable, Cloneable {
|
|||||||
public static final String ACTION_USB_AUDIO_DEVICE_PLUG =
|
public static final String ACTION_USB_AUDIO_DEVICE_PLUG =
|
||||||
"android.intent.action.USB_AUDIO_DEVICE_PLUG";
|
"android.intent.action.USB_AUDIO_DEVICE_PLUG";
|
||||||
|
|
||||||
/**
|
|
||||||
* @hide (to be un-hidden)
|
|
||||||
* Broadcast Action: the volume handled by the receiver should be updated based on the
|
|
||||||
* mutually exclusive extras, {@link #EXTRA_VOLUME_UPDATE_DIRECTION}
|
|
||||||
* and {@link #EXTRA_VOLUME_UPDATE_VALUE}.
|
|
||||||
*
|
|
||||||
* @see #EXTRA_VOLUME_UPDATE_DIRECTION
|
|
||||||
* @see #EXTRA_VOLUME_UPDATE_VALUE
|
|
||||||
* @see android.media.RemoteControlClient
|
|
||||||
*/
|
|
||||||
@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
|
|
||||||
public static final String ACTION_VOLUME_UPDATE = "android.intent.action.VOLUME_UPDATE";
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <p>Broadcast Action: The user has switched on advanced settings in the settings app:</p>
|
* <p>Broadcast Action: The user has switched on advanced settings in the settings app:</p>
|
||||||
* <ul>
|
* <ul>
|
||||||
@@ -2854,26 +2841,6 @@ public class Intent implements Parcelable, Cloneable {
|
|||||||
public static final String EXTRA_USERID =
|
public static final String EXTRA_USERID =
|
||||||
"android.intent.extra.user_id";
|
"android.intent.extra.user_id";
|
||||||
|
|
||||||
/**
|
|
||||||
* @hide (to be un-hidden)
|
|
||||||
* An integer indicating whether the volume is to be increased (positive value) or decreased
|
|
||||||
* (negative value). For bundled changes, the absolute value indicates the number of changes
|
|
||||||
* in the same direction, e.g. +3 corresponds to three "volume up" changes.
|
|
||||||
* @see #ACTION_VOLUME_UPDATE
|
|
||||||
*/
|
|
||||||
public static final String EXTRA_VOLUME_UPDATE_DIRECTION =
|
|
||||||
"android.intent.extra.VOLUME_UPDATE_DIRECTION";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @hide (to be un-hidden)
|
|
||||||
* An integer indicating the new volume value, always between 0 and the value set for
|
|
||||||
* {@link RemoteControlClient#PLAYBACKINFO_VOLUME_MAX} with
|
|
||||||
* {@link RemoteControlClient#setPlaybackInformation(int, int)}
|
|
||||||
* @see #ACTION_VOLUME_UPDATE
|
|
||||||
*/
|
|
||||||
public static final String EXTRA_VOLUME_UPDATE_VALUE =
|
|
||||||
"android.intent.extra.VOLUME_UPDATE_VALUE";
|
|
||||||
|
|
||||||
// ---------------------------------------------------------------------
|
// ---------------------------------------------------------------------
|
||||||
// ---------------------------------------------------------------------
|
// ---------------------------------------------------------------------
|
||||||
// Intent flags (see mFlags variable).
|
// Intent flags (see mFlags variable).
|
||||||
|
|||||||
@@ -4243,6 +4243,7 @@ public class AudioService extends IAudioService.Stub implements OnFinished {
|
|||||||
public int mPlaybackVolumeHandling;
|
public int mPlaybackVolumeHandling;
|
||||||
public int mPlaybackStream;
|
public int mPlaybackStream;
|
||||||
public int mPlaybackState;
|
public int mPlaybackState;
|
||||||
|
public IRemoteVolumeObserver mRemoteVolumeObs;
|
||||||
|
|
||||||
public void resetPlaybackInfo() {
|
public void resetPlaybackInfo() {
|
||||||
mPlaybackType = RemoteControlClient.PLAYBACK_TYPE_LOCAL;
|
mPlaybackType = RemoteControlClient.PLAYBACK_TYPE_LOCAL;
|
||||||
@@ -4251,6 +4252,7 @@ public class AudioService extends IAudioService.Stub implements OnFinished {
|
|||||||
mPlaybackVolumeHandling = RemoteControlClient.DEFAULT_PLAYBACK_VOLUME_HANDLING;
|
mPlaybackVolumeHandling = RemoteControlClient.DEFAULT_PLAYBACK_VOLUME_HANDLING;
|
||||||
mPlaybackStream = AudioManager.STREAM_MUSIC;
|
mPlaybackStream = AudioManager.STREAM_MUSIC;
|
||||||
mPlaybackState = RemoteControlClient.PLAYSTATE_STOPPED;
|
mPlaybackState = RemoteControlClient.PLAYSTATE_STOPPED;
|
||||||
|
mRemoteVolumeObs = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** precondition: mediaIntent != null, eventReceiver != null */
|
/** precondition: mediaIntent != null, eventReceiver != null */
|
||||||
@@ -4335,7 +4337,9 @@ public class AudioService extends IAudioService.Stub implements OnFinished {
|
|||||||
" -- state: " + rcse.mPlaybackState +
|
" -- state: " + rcse.mPlaybackState +
|
||||||
" -- vol handling: " + rcse.mPlaybackVolumeHandling +
|
" -- vol handling: " + rcse.mPlaybackVolumeHandling +
|
||||||
" -- vol: " + rcse.mPlaybackVolume +
|
" -- vol: " + rcse.mPlaybackVolume +
|
||||||
" -- volMax: " + rcse.mPlaybackVolumeMax);
|
" -- volMax: " + rcse.mPlaybackVolumeMax +
|
||||||
|
" -- volObs: " + rcse.mRemoteVolumeObs);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
synchronized (mMainRemote) {
|
synchronized (mMainRemote) {
|
||||||
@@ -5018,6 +5022,20 @@ public class AudioService extends IAudioService.Stub implements OnFinished {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FIXME send a message instead of updating the stack synchronously
|
||||||
|
public void registerRemoteVolumeObserverForRcc(int rccId, IRemoteVolumeObserver rvo) {
|
||||||
|
synchronized(mRCStack) {
|
||||||
|
Iterator<RemoteControlStackEntry> stackIterator = mRCStack.iterator();
|
||||||
|
while(stackIterator.hasNext()) {
|
||||||
|
RemoteControlStackEntry rcse = stackIterator.next();
|
||||||
|
if (rcse.mRccId == rccId) {
|
||||||
|
rcse.mRemoteVolumeObs = rvo;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks if a remote client is active on the supplied stream type. Update the remote stream
|
* Checks if a remote client is active on the supplied stream type. Update the remote stream
|
||||||
* volume state if found and playing
|
* volume state if found and playing
|
||||||
@@ -5100,23 +5118,24 @@ public class AudioService extends IAudioService.Stub implements OnFinished {
|
|||||||
// only handling discrete events
|
// only handling discrete events
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
String packageForRcc = null;
|
IRemoteVolumeObserver rvo = null;
|
||||||
synchronized (mRCStack) {
|
synchronized (mRCStack) {
|
||||||
Iterator<RemoteControlStackEntry> stackIterator = mRCStack.iterator();
|
Iterator<RemoteControlStackEntry> stackIterator = mRCStack.iterator();
|
||||||
while(stackIterator.hasNext()) {
|
while(stackIterator.hasNext()) {
|
||||||
RemoteControlStackEntry rcse = stackIterator.next();
|
RemoteControlStackEntry rcse = stackIterator.next();
|
||||||
//FIXME OPTIMIZE store this info in mMainRemote so we don't have to iterate?
|
//FIXME OPTIMIZE store this info in mMainRemote so we don't have to iterate?
|
||||||
if (rcse.mRccId == rccId) {
|
if (rcse.mRccId == rccId) {
|
||||||
packageForRcc = rcse.mReceiverComponent.getPackageName();
|
rvo = rcse.mRemoteVolumeObs;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (packageForRcc != null) {
|
if (rvo != null) {
|
||||||
Intent intent = new Intent(Intent.ACTION_VOLUME_UPDATE);
|
try {
|
||||||
intent.putExtra(Intent.EXTRA_VOLUME_UPDATE_DIRECTION, direction);
|
rvo.dispatchRemoteVolumeUpdate(direction, -1);
|
||||||
intent.setPackage(packageForRcc);
|
} catch (RemoteException e) {
|
||||||
mContext.sendBroadcast(intent);
|
Log.e(TAG, "Error dispatching relative volume update", e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -5147,23 +5166,24 @@ public class AudioService extends IAudioService.Stub implements OnFinished {
|
|||||||
}
|
}
|
||||||
rccId = mMainRemote.mRccId;
|
rccId = mMainRemote.mRccId;
|
||||||
}
|
}
|
||||||
String packageForRcc = null;
|
IRemoteVolumeObserver rvo = null;
|
||||||
synchronized (mRCStack) {
|
synchronized (mRCStack) {
|
||||||
Iterator<RemoteControlStackEntry> stackIterator = mRCStack.iterator();
|
Iterator<RemoteControlStackEntry> stackIterator = mRCStack.iterator();
|
||||||
while(stackIterator.hasNext()) {
|
while(stackIterator.hasNext()) {
|
||||||
RemoteControlStackEntry rcse = stackIterator.next();
|
RemoteControlStackEntry rcse = stackIterator.next();
|
||||||
if (rcse.mRccId == rccId) {
|
if (rcse.mRccId == rccId) {
|
||||||
//FIXME OPTIMIZE store this info in mMainRemote so we don't have to iterate?
|
//FIXME OPTIMIZE store this info in mMainRemote so we don't have to iterate?
|
||||||
packageForRcc = rcse.mReceiverComponent.getPackageName();
|
rvo = rcse.mRemoteVolumeObs;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (packageForRcc != null) {
|
if (rvo != null) {
|
||||||
Intent intent = new Intent(Intent.ACTION_VOLUME_UPDATE);
|
try {
|
||||||
intent.putExtra(Intent.EXTRA_VOLUME_UPDATE_VALUE, vol);
|
rvo.dispatchRemoteVolumeUpdate(0, vol);
|
||||||
intent.setPackage(packageForRcc);
|
} catch (RemoteException e) {
|
||||||
mContext.sendBroadcast(intent);
|
Log.e(TAG, "Error dispatching absolute volume update", e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ import android.media.IAudioFocusDispatcher;
|
|||||||
import android.media.IAudioRoutesObserver;
|
import android.media.IAudioRoutesObserver;
|
||||||
import android.media.IRemoteControlClient;
|
import android.media.IRemoteControlClient;
|
||||||
import android.media.IRemoteControlDisplay;
|
import android.media.IRemoteControlDisplay;
|
||||||
|
import android.media.IRemoteVolumeObserver;
|
||||||
import android.media.IRingtonePlayer;
|
import android.media.IRingtonePlayer;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.view.KeyEvent;
|
import android.view.KeyEvent;
|
||||||
@@ -135,6 +136,7 @@ interface IAudioService {
|
|||||||
oneway void setPlaybackInfoForRcc(int rccId, int what, int value);
|
oneway void setPlaybackInfoForRcc(int rccId, int what, int value);
|
||||||
int getRemoteStreamMaxVolume();
|
int getRemoteStreamMaxVolume();
|
||||||
int getRemoteStreamVolume();
|
int getRemoteStreamVolume();
|
||||||
|
oneway void registerRemoteVolumeObserverForRcc(int rccId, in IRemoteVolumeObserver rvo);
|
||||||
|
|
||||||
void startBluetoothSco(IBinder cb);
|
void startBluetoothSco(IBinder cb);
|
||||||
void stopBluetoothSco(IBinder cb);
|
void stopBluetoothSco(IBinder cb);
|
||||||
|
|||||||
26
media/java/android/media/IRemoteVolumeObserver.aidl
Normal file
26
media/java/android/media/IRemoteVolumeObserver.aidl
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2012 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;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* AIDL for the AudioService to report requests for remote volume update requests.
|
||||||
|
* @hide
|
||||||
|
*/
|
||||||
|
oneway interface IRemoteVolumeObserver {
|
||||||
|
void dispatchRemoteVolumeUpdate(int direction, int value);
|
||||||
|
}
|
||||||
@@ -589,9 +589,46 @@ public class MediaRouter {
|
|||||||
RouteGroup mGroup;
|
RouteGroup mGroup;
|
||||||
final RouteCategory mCategory;
|
final RouteCategory mCategory;
|
||||||
Drawable mIcon;
|
Drawable mIcon;
|
||||||
|
// playback information
|
||||||
|
int mPlaybackType = PLAYBACK_TYPE_LOCAL;
|
||||||
|
int mVolumeMax = RemoteControlClient.DEFAULT_PLAYBACK_VOLUME;
|
||||||
|
int mVolume = RemoteControlClient.DEFAULT_PLAYBACK_VOLUME;
|
||||||
|
int mVolumeHandling = RemoteControlClient.DEFAULT_PLAYBACK_VOLUME_HANDLING;
|
||||||
|
int mPlaybackStream = AudioManager.STREAM_MUSIC;
|
||||||
|
VolumeCallbackInfo mVcb;
|
||||||
|
|
||||||
private Object mTag;
|
private Object mTag;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @hide (to be un-hidden)
|
||||||
|
* The default playback type, "local", indicating the presentation of the media is happening
|
||||||
|
* on the same device (e.g. a phone, a tablet) as where it is controlled from.
|
||||||
|
* @see #setPlaybackType(int)
|
||||||
|
*/
|
||||||
|
public final static int PLAYBACK_TYPE_LOCAL = 0;
|
||||||
|
/**
|
||||||
|
* @hide (to be un-hidden)
|
||||||
|
* A playback type indicating the presentation of the media is happening on
|
||||||
|
* a different device (i.e. the remote device) than where it is controlled from.
|
||||||
|
* @see #setPlaybackType(int)
|
||||||
|
*/
|
||||||
|
public final static int PLAYBACK_TYPE_REMOTE = 1;
|
||||||
|
/**
|
||||||
|
* @hide (to be un-hidden)
|
||||||
|
* Playback information indicating the playback volume is fixed, i.e. it cannot be
|
||||||
|
* controlled from this object. An example of fixed playback volume is a remote player,
|
||||||
|
* playing over HDMI where the user prefers to control the volume on the HDMI sink, rather
|
||||||
|
* than attenuate at the source.
|
||||||
|
* @see #setVolumeHandling(int)
|
||||||
|
*/
|
||||||
|
public final static int PLAYBACK_VOLUME_FIXED = 0;
|
||||||
|
/**
|
||||||
|
* @hide (to be un-hidden)
|
||||||
|
* Playback information indicating the playback volume is variable and can be controlled
|
||||||
|
* from this object.
|
||||||
|
*/
|
||||||
|
public final static int PLAYBACK_VOLUME_VARIABLE = 1;
|
||||||
|
|
||||||
RouteInfo(RouteCategory category) {
|
RouteInfo(RouteCategory category) {
|
||||||
mCategory = category;
|
mCategory = category;
|
||||||
}
|
}
|
||||||
@@ -685,6 +722,71 @@ public class MediaRouter {
|
|||||||
return mTag;
|
return mTag;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @hide (to be un-hidden)
|
||||||
|
* @return the type of playback associated with this route
|
||||||
|
* @see UserRouteInfo#setPlaybackType(int)
|
||||||
|
*/
|
||||||
|
public int getPlaybackType() {
|
||||||
|
return mPlaybackType;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @hide (to be un-hidden)
|
||||||
|
* @return the stream over which the playback associated with this route is performed
|
||||||
|
* @see UserRouteInfo#setPlaybackStream(int)
|
||||||
|
*/
|
||||||
|
public int getPlaybackStream() {
|
||||||
|
return mPlaybackStream;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @hide (to be un-hidden)
|
||||||
|
* @return the volume at which the playback associated with this route is performed
|
||||||
|
* @see UserRouteInfo#setVolume(int)
|
||||||
|
*/
|
||||||
|
public int getVolume() {
|
||||||
|
if (mPlaybackType == PLAYBACK_TYPE_LOCAL) {
|
||||||
|
int vol = 0;
|
||||||
|
try {
|
||||||
|
vol = sStatic.mAudioService.getStreamVolume(mPlaybackStream);
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
Log.e(TAG, "Error getting local stream volume", e);
|
||||||
|
}
|
||||||
|
return vol;
|
||||||
|
} else {
|
||||||
|
return mVolume;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @hide (to be un-hidden)
|
||||||
|
* @return the maximum volume at which the playback associated with this route is performed
|
||||||
|
* @see UserRouteInfo#setVolumeMax(int)
|
||||||
|
*/
|
||||||
|
public int getVolumeMax() {
|
||||||
|
if (mPlaybackType == PLAYBACK_TYPE_LOCAL) {
|
||||||
|
int volMax = 0;
|
||||||
|
try {
|
||||||
|
volMax = sStatic.mAudioService.getStreamMaxVolume(mPlaybackStream);
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
Log.e(TAG, "Error getting local stream volume", e);
|
||||||
|
}
|
||||||
|
return volMax;
|
||||||
|
} else {
|
||||||
|
return mVolumeMax;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @hide (to be un-hidden)
|
||||||
|
* @return how volume is handling on the route
|
||||||
|
* @see UserRouteInfo#setVolumeHandling(int)
|
||||||
|
*/
|
||||||
|
public int getVolumeHandling() {
|
||||||
|
return mVolumeHandling;
|
||||||
|
}
|
||||||
|
|
||||||
void setStatusInt(CharSequence status) {
|
void setStatusInt(CharSequence status) {
|
||||||
if (!status.equals(mStatus)) {
|
if (!status.equals(mStatus)) {
|
||||||
mStatus = status;
|
mStatus = status;
|
||||||
@@ -695,6 +797,24 @@ public class MediaRouter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
final IRemoteVolumeObserver.Stub mRemoteVolObserver = new IRemoteVolumeObserver.Stub() {
|
||||||
|
public void dispatchRemoteVolumeUpdate(final int direction, final int value) {
|
||||||
|
sStatic.mHandler.post(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
//Log.d(TAG, "dispatchRemoteVolumeUpdate dir=" + direction + " val=" + value);
|
||||||
|
if (mVcb != null) {
|
||||||
|
if (direction != 0) {
|
||||||
|
mVcb.vcb.onVolumeUpdateRequest(mVcb.route, direction);
|
||||||
|
} else {
|
||||||
|
mVcb.vcb.onVolumeSetRequest(mVcb.route, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
void routeUpdated() {
|
void routeUpdated() {
|
||||||
updateRoute(this);
|
updateRoute(this);
|
||||||
}
|
}
|
||||||
@@ -757,10 +877,14 @@ public class MediaRouter {
|
|||||||
* RemoteControlClient will be used to reflect and update information
|
* RemoteControlClient will be used to reflect and update information
|
||||||
* such as route volume info in related UIs.</p>
|
* such as route volume info in related UIs.</p>
|
||||||
*
|
*
|
||||||
|
* <p>The RemoteControlClient must have been previously registered with
|
||||||
|
* {@link AudioManager#registerRemoteControlClient(RemoteControlClient)}.</p>
|
||||||
|
*
|
||||||
* @param rcc RemoteControlClient associated with this route
|
* @param rcc RemoteControlClient associated with this route
|
||||||
*/
|
*/
|
||||||
public void setRemoteControlClient(RemoteControlClient rcc) {
|
public void setRemoteControlClient(RemoteControlClient rcc) {
|
||||||
mRcc = rcc;
|
mRcc = rcc;
|
||||||
|
updatePlaybackInfoOnRcc();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -792,6 +916,111 @@ public class MediaRouter {
|
|||||||
public void setIconResource(int resId) {
|
public void setIconResource(int resId) {
|
||||||
setIconDrawable(sStatic.mResources.getDrawable(resId));
|
setIconDrawable(sStatic.mResources.getDrawable(resId));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @hide (to be un-hidden)
|
||||||
|
* Set a callback to be notified of volume update requests
|
||||||
|
* @param vcb
|
||||||
|
*/
|
||||||
|
public void setVolumeCallback(VolumeCallback vcb) {
|
||||||
|
mVcb = new VolumeCallbackInfo(vcb, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @hide (to be un-hidden)
|
||||||
|
* Defines whether playback associated with this route is "local"
|
||||||
|
* ({@link RouteInfo#PLAYBACK_TYPE_LOCAL}) or "remote"
|
||||||
|
* ({@link RouteInfo#PLAYBACK_TYPE_REMOTE}).
|
||||||
|
* @param type
|
||||||
|
*/
|
||||||
|
public void setPlaybackType(int type) {
|
||||||
|
if (mPlaybackType != type) {
|
||||||
|
mPlaybackType = type;
|
||||||
|
setPlaybackInfoOnRcc(RemoteControlClient.PLAYBACKINFO_PLAYBACK_TYPE, type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @hide (to be un-hidden)
|
||||||
|
* Defines whether volume for the playback associated with this route is fixed
|
||||||
|
* ({@link RouteInfo#PLAYBACK_VOLUME_FIXED}) or can modified
|
||||||
|
* ({@link RouteInfo#PLAYBACK_VOLUME_VARIABLE}).
|
||||||
|
* @param volumeHandling
|
||||||
|
*/
|
||||||
|
public void setVolumeHandling(int volumeHandling) {
|
||||||
|
if (mVolumeHandling != volumeHandling) {
|
||||||
|
mVolumeHandling = volumeHandling;
|
||||||
|
setPlaybackInfoOnRcc(
|
||||||
|
RemoteControlClient.PLAYBACKINFO_VOLUME_HANDLING, volumeHandling);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @hide (to be un-hidden)
|
||||||
|
* Defines at what volume the playback associated with this route is performed (for user
|
||||||
|
* feedback purposes). This information is only used when the playback is not local.
|
||||||
|
* @param volume
|
||||||
|
*/
|
||||||
|
public void setVolume(int volume) {
|
||||||
|
if (mVolume != volume) {
|
||||||
|
mVolume = volume;
|
||||||
|
setPlaybackInfoOnRcc(RemoteControlClient.PLAYBACKINFO_VOLUME, volume);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @hide (to be un-hidden)
|
||||||
|
* Defines the maximum volume at which the playback associated with this route is performed
|
||||||
|
* (for user feedback purposes). This information is only used when the playback is not
|
||||||
|
* local.
|
||||||
|
* @param volumeMax
|
||||||
|
*/
|
||||||
|
public void setVolumeMax(int volumeMax) {
|
||||||
|
if (mVolumeMax != volumeMax) {
|
||||||
|
mVolumeMax = volumeMax;
|
||||||
|
setPlaybackInfoOnRcc(RemoteControlClient.PLAYBACKINFO_VOLUME_MAX, volumeMax);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @hide (to be un-hidden)
|
||||||
|
* Defines over what stream type the media is presented.
|
||||||
|
* @param stream
|
||||||
|
*/
|
||||||
|
public void setPlaybackStream(int stream) {
|
||||||
|
if (mPlaybackStream != stream) {
|
||||||
|
mPlaybackStream = stream;
|
||||||
|
setPlaybackInfoOnRcc(RemoteControlClient.PLAYBACKINFO_USES_STREAM, stream);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updatePlaybackInfoOnRcc() {
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setPlaybackInfoOnRcc(int what, int value) {
|
||||||
|
if (mRcc != null) {
|
||||||
|
mRcc.setPlaybackInformation(what, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1206,4 +1435,44 @@ public class MediaRouter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static class VolumeCallbackInfo {
|
||||||
|
public final VolumeCallback vcb;
|
||||||
|
public final RouteInfo route;
|
||||||
|
|
||||||
|
public VolumeCallbackInfo(VolumeCallback vcb, RouteInfo route) {
|
||||||
|
this.vcb = vcb;
|
||||||
|
this.route = route;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @hide (to be un-hidden)
|
||||||
|
* Interface for receiving events about volume changes.
|
||||||
|
* All methods of this interface will be called from the application's main thread.
|
||||||
|
*
|
||||||
|
* <p>A VolumeCallback will only receive events relevant to routes that the callback
|
||||||
|
* was registered for.</p>
|
||||||
|
*
|
||||||
|
* @see UserRouteInfo#setVolumeCallback(VolumeCallback)
|
||||||
|
*/
|
||||||
|
public static abstract class VolumeCallback {
|
||||||
|
/**
|
||||||
|
* Called when the volume for the route should be increased or decreased.
|
||||||
|
* @param info the route affected by this event
|
||||||
|
* @param direction an integer indicating whether the volume is to be increased
|
||||||
|
* (positive value) or decreased (negative value).
|
||||||
|
* For bundled changes, the absolute value indicates the number of changes
|
||||||
|
* in the same direction, e.g. +3 corresponds to three "volume up" changes.
|
||||||
|
*/
|
||||||
|
public abstract void onVolumeUpdateRequest(RouteInfo info, int direction);
|
||||||
|
/**
|
||||||
|
* Called when the volume for the route should be set to the given value
|
||||||
|
* @param info the route affected by this event
|
||||||
|
* @param volume an integer indicating the new volume value that should be used, always
|
||||||
|
* between 0 and the value set by {@link UserRouteInfo#setVolumeMax(int)}.
|
||||||
|
*/
|
||||||
|
public abstract void onVolumeSetRequest(RouteInfo info, int volume);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -134,13 +134,13 @@ public class RemoteControlClient
|
|||||||
public final static int PLAYSTATE_NONE = 0;
|
public final static int PLAYSTATE_NONE = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @hide (to be un-hidden)
|
* @hide
|
||||||
* The default playback type, "local", indicating the presentation of the media is happening on
|
* The default playback type, "local", indicating the presentation of the media is happening on
|
||||||
* the same device (e.g. a phone, a tablet) as where it is controlled from.
|
* the same device (e.g. a phone, a tablet) as where it is controlled from.
|
||||||
*/
|
*/
|
||||||
public final static int PLAYBACK_TYPE_LOCAL = 0;
|
public final static int PLAYBACK_TYPE_LOCAL = 0;
|
||||||
/**
|
/**
|
||||||
* @hide (to be un-hidden)
|
* @hide
|
||||||
* A playback type indicating the presentation of the media is happening on
|
* A playback type indicating the presentation of the media is happening on
|
||||||
* a different device (i.e. the remote device) than where it is controlled from.
|
* a different device (i.e. the remote device) than where it is controlled from.
|
||||||
*/
|
*/
|
||||||
@@ -148,7 +148,7 @@ public class RemoteControlClient
|
|||||||
private final static int PLAYBACK_TYPE_MIN = PLAYBACK_TYPE_LOCAL;
|
private final static int PLAYBACK_TYPE_MIN = PLAYBACK_TYPE_LOCAL;
|
||||||
private final static int PLAYBACK_TYPE_MAX = PLAYBACK_TYPE_REMOTE;
|
private final static int PLAYBACK_TYPE_MAX = PLAYBACK_TYPE_REMOTE;
|
||||||
/**
|
/**
|
||||||
* @hide (to be un-hidden)
|
* @hide
|
||||||
* Playback information indicating the playback volume is fixed, i.e. it cannot be controlled
|
* Playback information indicating the playback volume is fixed, i.e. it cannot be controlled
|
||||||
* from this object. An example of fixed playback volume is a remote player, playing over HDMI
|
* from this object. An example of fixed playback volume is a remote player, playing over HDMI
|
||||||
* where the user prefer to control the volume on the HDMI sink, rather than attenuate at the
|
* where the user prefer to control the volume on the HDMI sink, rather than attenuate at the
|
||||||
@@ -157,7 +157,7 @@ public class RemoteControlClient
|
|||||||
*/
|
*/
|
||||||
public final static int PLAYBACK_VOLUME_FIXED = 0;
|
public final static int PLAYBACK_VOLUME_FIXED = 0;
|
||||||
/**
|
/**
|
||||||
* @hide (to be un-hidden)
|
* @hide
|
||||||
* Playback information indicating the playback volume is variable and can be controlled from
|
* Playback information indicating the playback volume is variable and can be controlled from
|
||||||
* this object.
|
* this object.
|
||||||
* @see #PLAYBACKINFO_VOLUME_HANDLING.
|
* @see #PLAYBACKINFO_VOLUME_HANDLING.
|
||||||
@@ -173,34 +173,34 @@ public class RemoteControlClient
|
|||||||
//==========================================
|
//==========================================
|
||||||
// Public keys for playback information
|
// Public keys for playback information
|
||||||
/**
|
/**
|
||||||
* @hide (to be un-hidden)
|
* @hide
|
||||||
* Playback information that defines the type of playback associated with this
|
* Playback information that defines the type of playback associated with this
|
||||||
* RemoteControlClient. See {@link #PLAYBACK_TYPE_LOCAL} and {@link #PLAYBACK_TYPE_REMOTE}.
|
* RemoteControlClient. See {@link #PLAYBACK_TYPE_LOCAL} and {@link #PLAYBACK_TYPE_REMOTE}.
|
||||||
*/
|
*/
|
||||||
public final static int PLAYBACKINFO_PLAYBACK_TYPE = 1;
|
public final static int PLAYBACKINFO_PLAYBACK_TYPE = 1;
|
||||||
/**
|
/**
|
||||||
* @hide (to be un-hidden)
|
* @hide
|
||||||
* Playback information that defines at what volume the playback associated with this
|
* Playback information that defines at what volume the playback associated with this
|
||||||
* RemoteControlClient is performed. This information is only used when the playback type is not
|
* RemoteControlClient is performed. This information is only used when the playback type is not
|
||||||
* local (see {@link #PLAYBACKINFO_PLAYBACK_TYPE}).
|
* local (see {@link #PLAYBACKINFO_PLAYBACK_TYPE}).
|
||||||
*/
|
*/
|
||||||
public final static int PLAYBACKINFO_VOLUME = 2;
|
public final static int PLAYBACKINFO_VOLUME = 2;
|
||||||
/**
|
/**
|
||||||
* @hide (to be un-hidden)
|
* @hide
|
||||||
* Playback information that defines the maximum volume volume value that is supported
|
* Playback information that defines the maximum volume volume value that is supported
|
||||||
* by the playback associated with this RemoteControlClient. This information is only used
|
* by the playback associated with this RemoteControlClient. This information is only used
|
||||||
* when the playback type is not local (see {@link #PLAYBACKINFO_PLAYBACK_TYPE}).
|
* when the playback type is not local (see {@link #PLAYBACKINFO_PLAYBACK_TYPE}).
|
||||||
*/
|
*/
|
||||||
public final static int PLAYBACKINFO_VOLUME_MAX = 3;
|
public final static int PLAYBACKINFO_VOLUME_MAX = 3;
|
||||||
/**
|
/**
|
||||||
* @hide (to be un-hidden)
|
* @hide
|
||||||
* Playback information that defines how volume is handled for the presentation of the media.
|
* Playback information that defines how volume is handled for the presentation of the media.
|
||||||
* @see #PLAYBACK_VOLUME_FIXED
|
* @see #PLAYBACK_VOLUME_FIXED
|
||||||
* @see #PLAYBACK_VOLUME_VARIABLE
|
* @see #PLAYBACK_VOLUME_VARIABLE
|
||||||
*/
|
*/
|
||||||
public final static int PLAYBACKINFO_VOLUME_HANDLING = 4;
|
public final static int PLAYBACKINFO_VOLUME_HANDLING = 4;
|
||||||
/**
|
/**
|
||||||
* @hide (to be un-hidden)
|
* @hide
|
||||||
* Playback information that defines over what stream type the media is presented.
|
* Playback information that defines over what stream type the media is presented.
|
||||||
*/
|
*/
|
||||||
public final static int PLAYBACKINFO_USES_STREAM = 5;
|
public final static int PLAYBACKINFO_USES_STREAM = 5;
|
||||||
@@ -642,7 +642,7 @@ public class RemoteControlClient
|
|||||||
private int mPlaybackStream = AudioManager.STREAM_MUSIC;
|
private int mPlaybackStream = AudioManager.STREAM_MUSIC;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @hide (to be un-hidden)
|
* @hide
|
||||||
* Set information describing information related to the playback of media so the system
|
* Set information describing information related to the playback of media so the system
|
||||||
* can implement additional behavior to handle non-local playback usecases.
|
* 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
|
* @param what a key to specify the type of information to set. Valid keys are
|
||||||
@@ -713,7 +713,7 @@ public class RemoteControlClient
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @hide (to be un-hidden)
|
* @hide
|
||||||
* Return playback information represented as an integer value.
|
* Return playback information represented as an integer value.
|
||||||
* @param what a key to specify the type of information to retrieve. Valid keys are
|
* @param what a key to specify the type of information to retrieve. Valid keys are
|
||||||
* {@link #PLAYBACKINFO_PLAYBACK_TYPE},
|
* {@link #PLAYBACKINFO_PLAYBACK_TYPE},
|
||||||
@@ -899,6 +899,13 @@ public class RemoteControlClient
|
|||||||
mRcseId = id;
|
mRcseId = id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @hide
|
||||||
|
*/
|
||||||
|
public int getRcseId() {
|
||||||
|
return mRcseId;
|
||||||
|
}
|
||||||
|
|
||||||
private EventHandler mEventHandler;
|
private EventHandler mEventHandler;
|
||||||
private final static int MSG_REQUEST_PLAYBACK_STATE = 1;
|
private final static int MSG_REQUEST_PLAYBACK_STATE = 1;
|
||||||
private final static int MSG_REQUEST_METADATA = 2;
|
private final static int MSG_REQUEST_METADATA = 2;
|
||||||
|
|||||||
Reference in New Issue
Block a user