Merge "AudioService: implement TV system volume" into lmp-dev
diff --git a/media/java/android/media/AudioService.java b/media/java/android/media/AudioService.java
index 8993af8..050c268 100644
--- a/media/java/android/media/AudioService.java
+++ b/media/java/android/media/AudioService.java
@@ -44,6 +44,7 @@
import android.content.res.XmlResourceParser;
import android.database.ContentObserver;
import android.hardware.hdmi.HdmiControlManager;
+import android.hardware.hdmi.HdmiPlaybackClient;
import android.hardware.hdmi.HdmiTvClient;
import android.hardware.usb.UsbManager;
import android.media.MediaPlayer.OnCompletionListener;
@@ -144,7 +145,23 @@
private final Context mContext;
private final ContentResolver mContentResolver;
private final AppOpsManager mAppOps;
- private final boolean mVoiceCapable;
+
+ // the platform has no specific capabilities
+ private static final int PLATFORM_DEFAULT = 0;
+ // the platform is voice call capable (a phone)
+ private static final int PLATFORM_VOICE = 1;
+ // the platform is a television or a set-top box
+ private static final int PLATFORM_TELEVISION = 2;
+ // the platform type affects volume and silent mode behavior
+ private final int mPlatformType;
+
+ private boolean isPlatformVoice() {
+ return mPlatformType == PLATFORM_VOICE;
+ }
+
+ private boolean isPlatformTelevision() {
+ return mPlatformType == PLATFORM_TELEVISION;
+ }
/** The controller for the volume UI. */
private final VolumeController mVolumeController = new VolumeController();
@@ -243,9 +260,10 @@
* NOTE: do not create loops in aliases!
* Some streams alias to different streams according to device category (phone or tablet) or
* use case (in call vs off call...). See updateStreamVolumeAlias() for more details.
- * mStreamVolumeAlias contains the default aliases for a voice capable device (phone) and
- * STREAM_VOLUME_ALIAS_NON_VOICE for a non voice capable device (tablet).*/
- private final int[] STREAM_VOLUME_ALIAS = new int[] {
+ * mStreamVolumeAlias contains STREAM_VOLUME_ALIAS_VOICE aliases for a voice capable device
+ * (phone), STREAM_VOLUME_ALIAS_TELEVISION for a television or set-top box and
+ * STREAM_VOLUME_ALIAS_DEFAULT for other devices (e.g. tablets).*/
+ private final int[] STREAM_VOLUME_ALIAS_VOICE = new int[] {
AudioSystem.STREAM_VOICE_CALL, // STREAM_VOICE_CALL
AudioSystem.STREAM_RING, // STREAM_SYSTEM
AudioSystem.STREAM_RING, // STREAM_RING
@@ -257,7 +275,19 @@
AudioSystem.STREAM_RING, // STREAM_DTMF
AudioSystem.STREAM_MUSIC // STREAM_TTS
};
- private final int[] STREAM_VOLUME_ALIAS_NON_VOICE = new int[] {
+ private final int[] STREAM_VOLUME_ALIAS_TELEVISION = new int[] {
+ AudioSystem.STREAM_MUSIC, // STREAM_VOICE_CALL
+ AudioSystem.STREAM_MUSIC, // STREAM_SYSTEM
+ AudioSystem.STREAM_MUSIC, // STREAM_RING
+ AudioSystem.STREAM_MUSIC, // STREAM_MUSIC
+ AudioSystem.STREAM_MUSIC, // STREAM_ALARM
+ AudioSystem.STREAM_MUSIC, // STREAM_NOTIFICATION
+ AudioSystem.STREAM_MUSIC, // STREAM_BLUETOOTH_SCO
+ AudioSystem.STREAM_MUSIC, // STREAM_SYSTEM_ENFORCED
+ AudioSystem.STREAM_MUSIC, // STREAM_DTMF
+ AudioSystem.STREAM_MUSIC // STREAM_TTS
+ };
+ private final int[] STREAM_VOLUME_ALIAS_DEFAULT = new int[] {
AudioSystem.STREAM_VOICE_CALL, // STREAM_VOICE_CALL
AudioSystem.STREAM_MUSIC, // STREAM_SYSTEM
AudioSystem.STREAM_RING, // STREAM_RING
@@ -455,9 +485,12 @@
public final static int STREAM_REMOTE_MUSIC = -200;
// Devices for which the volume is fixed and VolumePanel slider should be disabled
- final int mFixedVolumeDevices = AudioSystem.DEVICE_OUT_HDMI |
+ int mFixedVolumeDevices = AudioSystem.DEVICE_OUT_HDMI |
AudioSystem.DEVICE_OUT_DGTL_DOCK_HEADSET |
- AudioSystem.DEVICE_OUT_ANLG_DOCK_HEADSET;
+ AudioSystem.DEVICE_OUT_ANLG_DOCK_HEADSET |
+ AudioSystem.DEVICE_OUT_HDMI_ARC |
+ AudioSystem.DEVICE_OUT_SPDIF |
+ AudioSystem.DEVICE_OUT_AUX_LINE;
// TODO merge orientation and rotation
private final boolean mMonitorOrientation;
@@ -491,8 +524,16 @@
mContext = context;
mContentResolver = context.getContentResolver();
mAppOps = (AppOpsManager)context.getSystemService(Context.APP_OPS_SERVICE);
- mVoiceCapable = mContext.getResources().getBoolean(
- com.android.internal.R.bool.config_voice_capable);
+
+ if (mContext.getResources().getBoolean(
+ com.android.internal.R.bool.config_voice_capable)) {
+ mPlatformType = PLATFORM_VOICE;
+ } else if (context.getPackageManager().hasSystemFeature(
+ PackageManager.FEATURE_TELEVISION)) {
+ mPlatformType = PLATFORM_TELEVISION;
+ } else {
+ mPlatformType = PLATFORM_DEFAULT;
+ }
PowerManager pm = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
mAudioEventWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "handleAudioEvent");
@@ -622,10 +663,15 @@
BluetoothProfile.A2DP);
}
- HdmiControlManager hdmiManager =
+ mHdmiManager =
(HdmiControlManager) mContext.getSystemService(Context.HDMI_CONTROL_SERVICE);
- // Null if device is not Tv.
- mHdmiTvClient = hdmiManager.getTvClient();
+ if (mHdmiManager != null) {
+ synchronized (mHdmiManager) {
+ mHdmiTvClient = mHdmiManager.getTvClient();
+ mHdmiPlaybackClient = mHdmiManager.getPlaybackClient();
+ mHdmiCecSink = false;
+ }
+ }
sendMsg(mAudioHandler,
MSG_CONFIGURE_SAFE_MEDIA_VOLUME_FORCED,
@@ -670,6 +716,14 @@
}
}
+ private void checkAllFixedVolumeDevices()
+ {
+ int numStreamTypes = AudioSystem.getNumStreamTypes();
+ for (int streamType = 0; streamType < numStreamTypes; streamType++) {
+ mStreamStates[streamType].checkFixedVolumeDevices();
+ }
+ }
+
private void createStreamStates() {
int numStreamTypes = AudioSystem.getNumStreamTypes();
VolumeStreamState[] streams = mStreamStates = new VolumeStreamState[numStreamTypes];
@@ -678,6 +732,7 @@
streams[i] = new VolumeStreamState(System.VOLUME_SETTINGS[mStreamVolumeAlias[i]], i);
}
+ checkAllFixedVolumeDevices();
checkAllAliasStreamVolumes();
}
@@ -702,19 +757,32 @@
private void updateStreamVolumeAlias(boolean updateVolumes) {
int dtmfStreamAlias;
- if (mVoiceCapable) {
- mStreamVolumeAlias = STREAM_VOLUME_ALIAS;
+
+ switch (mPlatformType) {
+ case PLATFORM_VOICE:
+ mStreamVolumeAlias = STREAM_VOLUME_ALIAS_VOICE;
dtmfStreamAlias = AudioSystem.STREAM_RING;
- } else {
- mStreamVolumeAlias = STREAM_VOLUME_ALIAS_NON_VOICE;
+ break;
+ case PLATFORM_TELEVISION:
+ mStreamVolumeAlias = STREAM_VOLUME_ALIAS_TELEVISION;
+ dtmfStreamAlias = AudioSystem.STREAM_MUSIC;
+ break;
+ default:
+ mStreamVolumeAlias = STREAM_VOLUME_ALIAS_DEFAULT;
dtmfStreamAlias = AudioSystem.STREAM_MUSIC;
}
- if (isInCommunication()) {
- dtmfStreamAlias = AudioSystem.STREAM_VOICE_CALL;
- mRingerModeAffectedStreams &= ~(1 << AudioSystem.STREAM_DTMF);
+
+ if (isPlatformTelevision()) {
+ mRingerModeAffectedStreams = 0;
} else {
- mRingerModeAffectedStreams |= (1 << AudioSystem.STREAM_DTMF);
+ if (isInCommunication()) {
+ dtmfStreamAlias = AudioSystem.STREAM_VOICE_CALL;
+ mRingerModeAffectedStreams &= ~(1 << AudioSystem.STREAM_DTMF);
+ } else {
+ mRingerModeAffectedStreams |= (1 << AudioSystem.STREAM_DTMF);
+ }
}
+
mStreamVolumeAlias[AudioSystem.STREAM_DTMF] = dtmfStreamAlias;
if (updateVolumes) {
mStreamStates[AudioSystem.STREAM_DTMF].setAllIndexes(mStreamStates[dtmfStreamAlias]);
@@ -768,7 +836,7 @@
if (ringerMode != ringerModeFromSettings) {
Settings.Global.putInt(cr, Settings.Global.MODE_RINGER, ringerMode);
}
- if (mUseFixedVolume) {
+ if (mUseFixedVolume || isPlatformTelevision()) {
ringerMode = AudioManager.RINGER_MODE_NORMAL;
}
synchronized(mSettingsLock) {
@@ -998,15 +1066,30 @@
// Check if volume update should be send to Hdmi system audio.
int newIndex = mStreamStates[streamType].getIndex(device);
- if (mHdmiTvClient != null &&
- streamTypeAlias == AudioSystem.STREAM_MUSIC &&
- (flags & AudioManager.FLAG_HDMI_SYSTEM_AUDIO_VOLUME) == 0 &&
- oldIndex != newIndex) {
- int maxIndex = getStreamMaxVolume(streamType);
- synchronized (mHdmiTvClient) {
- if (mHdmiSystemAudioSupported) {
- mHdmiTvClient.setSystemAudioVolume(
- (oldIndex + 5) / 10, (newIndex + 5) / 10, maxIndex);
+ if (mHdmiManager != null) {
+ synchronized (mHdmiManager) {
+ if (mHdmiTvClient != null &&
+ streamTypeAlias == AudioSystem.STREAM_MUSIC &&
+ (flags & AudioManager.FLAG_HDMI_SYSTEM_AUDIO_VOLUME) == 0 &&
+ oldIndex != newIndex) {
+ int maxIndex = getStreamMaxVolume(streamType);
+ synchronized (mHdmiTvClient) {
+ if (mHdmiSystemAudioSupported) {
+ mHdmiTvClient.setSystemAudioVolume(
+ (oldIndex + 5) / 10, (newIndex + 5) / 10, maxIndex);
+ }
+ }
+ }
+ // mHdmiCecSink true => mHdmiPlaybackClient != null
+ if (mHdmiCecSink &&
+ streamTypeAlias == AudioSystem.STREAM_MUSIC &&
+ oldIndex != newIndex) {
+ synchronized (mHdmiPlaybackClient) {
+ int keyCode = (direction == -1) ? KeyEvent.KEYCODE_VOLUME_DOWN :
+ KeyEvent.KEYCODE_VOLUME_UP;
+ mHdmiPlaybackClient.sendKeyEvent(keyCode, true);
+ mHdmiPlaybackClient.sendKeyEvent(keyCode, false);
+ }
}
}
}
@@ -1110,15 +1193,19 @@
}
}
- if (mHdmiTvClient != null &&
- streamTypeAlias == AudioSystem.STREAM_MUSIC &&
- (flags & AudioManager.FLAG_HDMI_SYSTEM_AUDIO_VOLUME) == 0 &&
- oldIndex != index) {
- int maxIndex = getStreamMaxVolume(streamType);
- synchronized (mHdmiTvClient) {
- if (mHdmiSystemAudioSupported) {
- mHdmiTvClient.setSystemAudioVolume(
- (oldIndex + 5) / 10, (index + 5) / 10, maxIndex);
+ if (mHdmiManager != null) {
+ synchronized (mHdmiManager) {
+ if (mHdmiTvClient != null &&
+ streamTypeAlias == AudioSystem.STREAM_MUSIC &&
+ (flags & AudioManager.FLAG_HDMI_SYSTEM_AUDIO_VOLUME) == 0 &&
+ oldIndex != index) {
+ int maxIndex = getStreamMaxVolume(streamType);
+ synchronized (mHdmiTvClient) {
+ if (mHdmiSystemAudioSupported) {
+ mHdmiTvClient.setSystemAudioVolume(
+ (oldIndex + 5) / 10, (index + 5) / 10, maxIndex);
+ }
+ }
}
}
}
@@ -1257,7 +1344,7 @@
// UI update and Broadcast Intent
private void sendVolumeUpdate(int streamType, int oldIndex, int index, int flags) {
- if (!mVoiceCapable && (streamType == AudioSystem.STREAM_RING)) {
+ if (!isPlatformVoice() && (streamType == AudioSystem.STREAM_RING)) {
streamType = AudioSystem.STREAM_NOTIFICATION;
}
@@ -1346,10 +1433,14 @@
}
if (isStreamAffectedByMute(streamType)) {
- if (streamType == AudioSystem.STREAM_MUSIC && mHdmiTvClient != null) {
- synchronized (mHdmiTvClient) {
- if (mHdmiSystemAudioSupported) {
- mHdmiTvClient.setSystemAudioMute(state);
+ if (mHdmiManager != null) {
+ synchronized (mHdmiManager) {
+ if (streamType == AudioSystem.STREAM_MUSIC && mHdmiTvClient != null) {
+ synchronized (mHdmiTvClient) {
+ if (mHdmiSystemAudioSupported) {
+ mHdmiTvClient.setSystemAudioMute(state);
+ }
+ }
}
}
}
@@ -1472,11 +1563,15 @@
/** @see AudioManager#getMasterStreamType() */
public int getMasterStreamType() {
- if (mVoiceCapable) {
- return AudioSystem.STREAM_RING;
- } else {
- return AudioSystem.STREAM_NOTIFICATION;
+ switch (mPlatformType) {
+ case PLATFORM_VOICE:
+ return AudioSystem.STREAM_RING;
+ case PLATFORM_TELEVISION:
+ return AudioSystem.STREAM_MUSIC;
+ default:
+ break;
}
+ return AudioSystem.STREAM_NOTIFICATION;
}
/** @see AudioManager#setMicrophoneMute(boolean) */
@@ -1504,7 +1599,7 @@
/** @see AudioManager#setRingerMode(int) */
public void setRingerMode(int ringerMode) {
- if (mUseFixedVolume) {
+ if (mUseFixedVolume || isPlatformTelevision()) {
return;
}
@@ -1534,7 +1629,7 @@
ringerMode == AudioManager.RINGER_MODE_NORMAL) {
// ring and notifications volume should never be 0 when not silenced
// on voice capable devices
- if (mVoiceCapable &&
+ if (isPlatformVoice() &&
mStreamVolumeAlias[streamType] == AudioSystem.STREAM_RING) {
synchronized (mStreamStates[streamType]) {
Set set = mStreamStates[streamType].mIndex.entrySet();
@@ -2041,6 +2136,7 @@
// muted by ringer mode have the correct volume
setRingerModeInt(getRingerMode(), false);
+ checkAllFixedVolumeDevices();
checkAllAliasStreamVolumes();
synchronized (mSafeMediaVolumeState) {
@@ -2760,11 +2856,18 @@
(1 << AudioSystem.STREAM_NOTIFICATION)|
(1 << AudioSystem.STREAM_SYSTEM);
- if (mVoiceCapable) {
- ringerModeAffectedStreams &= ~(1 << AudioSystem.STREAM_MUSIC);
- } else {
- ringerModeAffectedStreams |= (1 << AudioSystem.STREAM_MUSIC);
+ switch (mPlatformType) {
+ case PLATFORM_VOICE:
+ ringerModeAffectedStreams &= ~(1 << AudioSystem.STREAM_MUSIC);
+ break;
+ case PLATFORM_TELEVISION:
+ ringerModeAffectedStreams = 0;
+ break;
+ default:
+ ringerModeAffectedStreams |= (1 << AudioSystem.STREAM_MUSIC);
+ break;
}
+
synchronized (mCameraSoundForced) {
if (mCameraSoundForced) {
ringerModeAffectedStreams &= ~(1 << AudioSystem.STREAM_SYSTEM_ENFORCED);
@@ -2833,7 +2936,8 @@
}
private int getActiveStreamType(int suggestedStreamType) {
- if (mVoiceCapable) {
+ switch (mPlatformType) {
+ case PLATFORM_VOICE:
if (isInCommunication()) {
if (AudioSystem.getForceUse(AudioSystem.FOR_COMMUNICATION)
== AudioSystem.FORCE_BT_SCO) {
@@ -2863,12 +2967,26 @@
if (DEBUG_VOL)
Log.v(TAG, "getActiveStreamType: Forcing STREAM_MUSIC stream active");
return AudioSystem.STREAM_MUSIC;
- } else {
- if (DEBUG_VOL) Log.v(TAG, "getActiveStreamType: Returning suggested type "
- + suggestedStreamType);
- return suggestedStreamType;
}
- } else {
+ break;
+ case PLATFORM_TELEVISION:
+ if (suggestedStreamType == AudioManager.USE_DEFAULT_STREAM_TYPE) {
+ if (isAfMusicActiveRecently(DEFAULT_STREAM_TYPE_OVERRIDE_DELAY_MS)) {
+ if (DEBUG_VOL) Log.v(TAG, "getActiveStreamType: forcing STREAM_MUSIC");
+ return AudioSystem.STREAM_MUSIC;
+ } else if (mMediaFocusControl.checkUpdateRemoteStateIfActive(
+ AudioSystem.STREAM_MUSIC)) {
+ if (DEBUG_VOL)
+ Log.v(TAG, "getActiveStreamType: Forcing STREAM_REMOTE_MUSIC");
+ return STREAM_REMOTE_MUSIC;
+ } else {
+ if (DEBUG_VOL) Log.v(TAG,
+ "getActiveStreamType: using STREAM_MUSIC as default");
+ return AudioSystem.STREAM_MUSIC;
+ }
+ }
+ break;
+ default:
if (isInCommunication()) {
if (AudioSystem.getForceUse(AudioSystem.FOR_COMMUNICATION)
== AudioSystem.FORCE_BT_SCO) {
@@ -2899,12 +3017,12 @@
"getActiveStreamType: using STREAM_NOTIFICATION as default");
return AudioSystem.STREAM_NOTIFICATION;
}
- } else {
- if (DEBUG_VOL) Log.v(TAG, "getActiveStreamType: Returning suggested type "
- + suggestedStreamType);
- return suggestedStreamType;
}
+ break;
}
+ if (DEBUG_VOL) Log.v(TAG, "getActiveStreamType: Returning suggested type "
+ + suggestedStreamType);
+ return suggestedStreamType;
}
private void broadcastRingerMode(int ringerMode) {
@@ -3098,13 +3216,7 @@
continue;
}
- // ignore settings for fixed volume devices: volume should always be at max or 0
- if ((mStreamVolumeAlias[mStreamType] == AudioSystem.STREAM_MUSIC) &&
- ((device & mFixedVolumeDevices) != 0)) {
- mIndex.put(device, (index != 0) ? mIndexMax : 0);
- } else {
- mIndex.put(device, getValidIndex(10 * index));
- }
+ mIndex.put(device, getValidIndex(10 * index));
}
}
}
@@ -3263,6 +3375,25 @@
return mStreamType;
}
+ public void checkFixedVolumeDevices() {
+ synchronized (VolumeStreamState.class) {
+ // ignore settings for fixed volume devices: volume should always be at max or 0
+ if (mStreamVolumeAlias[mStreamType] == AudioSystem.STREAM_MUSIC) {
+ Set set = mIndex.entrySet();
+ Iterator i = set.iterator();
+ while (i.hasNext()) {
+ Map.Entry entry = (Map.Entry)i.next();
+ int device = ((Integer)entry.getKey()).intValue();
+ int index = ((Integer)entry.getValue()).intValue();
+ if (((device & mFixedVolumeDevices) != 0) && index != 0) {
+ entry.setValue(mIndexMax);
+ }
+ applyDeviceVolume(device);
+ }
+ }
+ }
+ }
+
private int getValidIndex(int index) {
if (index < 0) {
return 0;
@@ -3469,6 +3600,9 @@
if (mUseFixedVolume) {
return;
}
+ if (isPlatformTelevision() && (streamState.mStreamType != AudioSystem.STREAM_MUSIC)) {
+ return;
+ }
System.putIntForUser(mContentResolver,
streamState.getSettingNameForDevice(device),
(streamState.getIndex(device) + 5)/ 10,
@@ -3825,11 +3959,13 @@
mDockAudioMediaEnabled ?
AudioSystem.FORCE_ANALOG_DOCK : AudioSystem.FORCE_NONE);
}
-
- if (mHdmiTvClient != null) {
- setHdmiSystemAudioSupported(mHdmiSystemAudioSupported);
+ if (mHdmiManager != null) {
+ synchronized (mHdmiManager) {
+ if (mHdmiTvClient != null) {
+ setHdmiSystemAudioSupported(mHdmiSystemAudioSupported);
+ }
+ }
}
-
// indicate the end of reconfiguration phase to audio HAL
AudioSystem.setParameters("restarting=false");
break;
@@ -4275,6 +4411,27 @@
null,
MUSIC_ACTIVE_POLL_PERIOD_MS);
}
+ // Television devices without CEC service apply software volume on HDMI output
+ if (isPlatformTelevision() && ((device & AudioSystem.DEVICE_OUT_HDMI) != 0)) {
+ mFixedVolumeDevices |= AudioSystem.DEVICE_OUT_HDMI;
+ checkAllFixedVolumeDevices();
+ if (mHdmiManager != null) {
+ synchronized (mHdmiManager) {
+ if (mHdmiPlaybackClient != null) {
+ mHdmiCecSink = false;
+ mHdmiPlaybackClient.queryDisplayStatus(mHdmiDisplayStatusCallback);
+ }
+ }
+ }
+ }
+ } else {
+ if (isPlatformTelevision() && ((device & AudioSystem.DEVICE_OUT_HDMI) != 0)) {
+ if (mHdmiManager != null) {
+ synchronized (mHdmiManager) {
+ mHdmiCecSink = false;
+ }
+ }
+ }
}
if (!isUsb && (device != AudioSystem.DEVICE_IN_WIRED_HEADSET)) {
sendDeviceConnectionIntent(device, state, name);
@@ -4577,18 +4734,20 @@
if (cameraSoundForced != mCameraSoundForced) {
mCameraSoundForced = cameraSoundForced;
- VolumeStreamState s = mStreamStates[AudioSystem.STREAM_SYSTEM_ENFORCED];
- if (cameraSoundForced) {
- s.setAllIndexesToMax();
- mRingerModeAffectedStreams &=
- ~(1 << AudioSystem.STREAM_SYSTEM_ENFORCED);
- } else {
- s.setAllIndexes(mStreamStates[AudioSystem.STREAM_SYSTEM]);
- mRingerModeAffectedStreams |=
- (1 << AudioSystem.STREAM_SYSTEM_ENFORCED);
+ if (!isPlatformTelevision()) {
+ VolumeStreamState s = mStreamStates[AudioSystem.STREAM_SYSTEM_ENFORCED];
+ if (cameraSoundForced) {
+ s.setAllIndexesToMax();
+ mRingerModeAffectedStreams &=
+ ~(1 << AudioSystem.STREAM_SYSTEM_ENFORCED);
+ } else {
+ s.setAllIndexes(mStreamStates[AudioSystem.STREAM_SYSTEM]);
+ mRingerModeAffectedStreams |=
+ (1 << AudioSystem.STREAM_SYSTEM_ENFORCED);
+ }
+ // take new state into account for streams muted by ringer mode
+ setRingerModeInt(getRingerMode(), false);
}
- // take new state into account for streams muted by ringer mode
- setRingerModeInt(getRingerMode(), false);
sendMsg(mAudioHandler,
MSG_SET_FORCE_USE,
@@ -4804,27 +4963,57 @@
// to HdmiControlService so that audio recevier can handle volume change.
//==========================================================================================
+ private class MyDisplayStatusCallback implements HdmiPlaybackClient.DisplayStatusCallback {
+ public void onComplete(int status) {
+ if (mHdmiManager != null) {
+ synchronized (mHdmiManager) {
+ mHdmiCecSink = (status != HdmiControlManager.POWER_STATUS_UNKNOWN);
+ // Television devices without CEC service apply software volume on HDMI output
+ if (isPlatformTelevision() && !mHdmiCecSink) {
+ mFixedVolumeDevices &= ~AudioSystem.DEVICE_OUT_HDMI;
+ }
+ checkAllFixedVolumeDevices();
+ }
+ }
+ }
+ };
+
// If HDMI-CEC system audio is supported
private boolean mHdmiSystemAudioSupported = false;
// Set only when device is tv.
private HdmiTvClient mHdmiTvClient;
+ // true if the device has system feature PackageManager.FEATURE_TELEVISION.
+ // cached HdmiControlManager interface
+ private HdmiControlManager mHdmiManager;
+ // Set only when device is a set-top box.
+ private HdmiPlaybackClient mHdmiPlaybackClient;
+ // true if we are a set-top box, an HDMI sink is connected and it supports CEC.
+ private boolean mHdmiCecSink;
+
+ private MyDisplayStatusCallback mHdmiDisplayStatusCallback = new MyDisplayStatusCallback();
@Override
public int setHdmiSystemAudioSupported(boolean on) {
- if (mHdmiTvClient == null) {
- Log.w(TAG, "Only Hdmi-Cec enabled TV device supports system audio mode.");
- return AudioSystem.DEVICE_NONE;
- }
+ int device = AudioSystem.DEVICE_NONE;
+ if (mHdmiManager != null) {
+ synchronized (mHdmiManager) {
+ if (mHdmiTvClient == null) {
+ Log.w(TAG, "Only Hdmi-Cec enabled TV device supports system audio mode.");
+ return device;
+ }
- synchronized (mHdmiTvClient) {
- if (mHdmiSystemAudioSupported == on) {
- return AudioSystem.getDevicesForStream(AudioSystem.STREAM_MUSIC);
+ synchronized (mHdmiTvClient) {
+ if (mHdmiSystemAudioSupported != on) {
+ mHdmiSystemAudioSupported = on;
+ AudioSystem.setForceUse(AudioSystem.FOR_HDMI_SYSTEM_AUDIO,
+ on ? AudioSystem.FORCE_HDMI_SYSTEM_AUDIO_ENFORCED :
+ AudioSystem.FORCE_NONE);
+ }
+ device = AudioSystem.getDevicesForStream(AudioSystem.STREAM_MUSIC);
+ }
}
- mHdmiSystemAudioSupported = on;
- AudioSystem.setForceUse(AudioSystem.FOR_HDMI_SYSTEM_AUDIO,
- on ? AudioSystem.FORCE_HDMI_SYSTEM_AUDIO_ENFORCED : AudioSystem.FORCE_NONE);
}
- return AudioSystem.getDevicesForStream(AudioSystem.STREAM_MUSIC);
+ return device;
}
//==========================================================================================