summaryrefslogtreecommitdiffstats
path: root/media
diff options
context:
space:
mode:
Diffstat (limited to 'media')
-rw-r--r--media/java/android/media/AudioService.java237
-rw-r--r--media/java/android/media/AudioSystem.java6
-rw-r--r--media/java/android/media/IAudioService.aidl2
-rw-r--r--media/java/android/media/MediaRouter.java23
-rw-r--r--media/jni/android_media_MediaPlayer.cpp5
5 files changed, 224 insertions, 49 deletions
diff --git a/media/java/android/media/AudioService.java b/media/java/android/media/AudioService.java
index 61418fb..f26d322 100644
--- a/media/java/android/media/AudioService.java
+++ b/media/java/android/media/AudioService.java
@@ -462,7 +462,21 @@ public class AudioService extends IAudioService.Stub implements OnFinished {
mVolumePanel = new VolumePanel(context, this);
mMode = AudioSystem.MODE_NORMAL;
mForcedUseForComm = AudioSystem.FORCE_NONE;
+
createAudioSystemThread();
+
+ boolean cameraSoundForced = mContext.getResources().getBoolean(
+ com.android.internal.R.bool.config_camera_sound_forced);
+ mCameraSoundForced = new Boolean(cameraSoundForced);
+ sendMsg(mAudioHandler,
+ MSG_SET_FORCE_USE,
+ SENDMSG_QUEUE,
+ AudioSystem.FOR_SYSTEM,
+ cameraSoundForced ?
+ AudioSystem.FORCE_SYSTEM_ENFORCED : AudioSystem.FORCE_NONE,
+ null,
+ 0);
+
readPersistedSettings();
mSettingsObserver = new SettingsObserver();
updateStreamVolumeAlias(false /*updateVolumes*/);
@@ -585,6 +599,8 @@ public class AudioService extends IAudioService.Stub implements OnFinished {
mStreamStates[i].dump(pw);
pw.println("");
}
+ pw.print("\n- mute affected streams = 0x");
+ pw.println(Integer.toHexString(mMuteAffectedStreams));
}
@@ -634,35 +650,44 @@ public class AudioService extends IAudioService.Stub implements OnFinished {
}
synchronized(mSettingsLock) {
mRingerMode = ringerMode;
- }
- // System.VIBRATE_ON is not used any more but defaults for mVibrateSetting
- // are still needed while setVibrateSetting() and getVibrateSetting() are being deprecated.
- mVibrateSetting = getValueForVibrateSetting(0,
- AudioManager.VIBRATE_TYPE_NOTIFICATION,
- mHasVibrator ? AudioManager.VIBRATE_SETTING_ONLY_SILENT
- : AudioManager.VIBRATE_SETTING_OFF);
- mVibrateSetting = getValueForVibrateSetting(mVibrateSetting,
- AudioManager.VIBRATE_TYPE_RINGER,
- mHasVibrator ? AudioManager.VIBRATE_SETTING_ONLY_SILENT
- : AudioManager.VIBRATE_SETTING_OFF);
-
- // make sure settings for ringer mode are consistent with device type: non voice capable
- // devices (tablets) include media stream in silent mode whereas phones don't.
- mRingerModeAffectedStreams = Settings.System.getIntForUser(cr,
- Settings.System.MODE_RINGER_STREAMS_AFFECTED,
- ((1 << AudioSystem.STREAM_RING)|(1 << AudioSystem.STREAM_NOTIFICATION)|
- (1 << AudioSystem.STREAM_SYSTEM)|(1 << AudioSystem.STREAM_SYSTEM_ENFORCED)),
- UserHandle.USER_CURRENT);
- if (mVoiceCapable) {
- mRingerModeAffectedStreams &= ~(1 << AudioSystem.STREAM_MUSIC);
- } else {
- mRingerModeAffectedStreams |= (1 << AudioSystem.STREAM_MUSIC);
+ // System.VIBRATE_ON is not used any more but defaults for mVibrateSetting
+ // are still needed while setVibrateSetting() and getVibrateSetting() are being
+ // deprecated.
+ mVibrateSetting = getValueForVibrateSetting(0,
+ AudioManager.VIBRATE_TYPE_NOTIFICATION,
+ mHasVibrator ? AudioManager.VIBRATE_SETTING_ONLY_SILENT
+ : AudioManager.VIBRATE_SETTING_OFF);
+ mVibrateSetting = getValueForVibrateSetting(mVibrateSetting,
+ AudioManager.VIBRATE_TYPE_RINGER,
+ mHasVibrator ? AudioManager.VIBRATE_SETTING_ONLY_SILENT
+ : AudioManager.VIBRATE_SETTING_OFF);
+
+ // make sure settings for ringer mode are consistent with device type: non voice capable
+ // devices (tablets) include media stream in silent mode whereas phones don't.
+ mRingerModeAffectedStreams = Settings.System.getIntForUser(cr,
+ Settings.System.MODE_RINGER_STREAMS_AFFECTED,
+ ((1 << AudioSystem.STREAM_RING)|(1 << AudioSystem.STREAM_NOTIFICATION)|
+ (1 << AudioSystem.STREAM_SYSTEM)|(1 << AudioSystem.STREAM_SYSTEM_ENFORCED)),
+ UserHandle.USER_CURRENT);
+ if (mVoiceCapable) {
+ mRingerModeAffectedStreams &= ~(1 << AudioSystem.STREAM_MUSIC);
+ } else {
+ mRingerModeAffectedStreams |= (1 << AudioSystem.STREAM_MUSIC);
+ }
+ synchronized (mCameraSoundForced) {
+ if (mCameraSoundForced) {
+ mRingerModeAffectedStreams &= ~(1 << AudioSystem.STREAM_SYSTEM_ENFORCED);
+ } else {
+ mRingerModeAffectedStreams |= (1 << AudioSystem.STREAM_SYSTEM_ENFORCED);
+ }
+ }
+
+ Settings.System.putIntForUser(cr,
+ Settings.System.MODE_RINGER_STREAMS_AFFECTED,
+ mRingerModeAffectedStreams,
+ UserHandle.USER_CURRENT);
}
- Settings.System.putIntForUser(cr,
- Settings.System.MODE_RINGER_STREAMS_AFFECTED,
- mRingerModeAffectedStreams,
- UserHandle.USER_CURRENT);
mMuteAffectedStreams = System.getIntForUser(cr,
System.MUTE_STREAMS_AFFECTED,
@@ -733,7 +758,7 @@ public class AudioService extends IAudioService.Stub implements OnFinished {
if (streamType == STREAM_REMOTE_MUSIC) {
// don't play sounds for remote
- flags &= ~AudioManager.FLAG_PLAY_SOUND;
+ flags &= ~(AudioManager.FLAG_PLAY_SOUND|AudioManager.FLAG_FIXED_VOLUME);
//if (DEBUG_VOL) Log.i(TAG, "Need to adjust remote volume: calling adjustRemoteVolume()");
adjustRemoteVolume(AudioSystem.STREAM_MUSIC, direction, flags);
} else {
@@ -771,6 +796,7 @@ public class AudioService extends IAudioService.Stub implements OnFinished {
int index;
int oldIndex;
+ flags &= ~AudioManager.FLAG_FIXED_VOLUME;
if ((streamTypeAlias == AudioSystem.STREAM_MUSIC) &&
((device & mFixedVolumeDevices) != 0)) {
flags |= AudioManager.FLAG_FIXED_VOLUME;
@@ -855,6 +881,7 @@ public class AudioService extends IAudioService.Stub implements OnFinished {
final int device = getDeviceForStream(streamType);
int oldIndex;
+ flags &= ~AudioManager.FLAG_FIXED_VOLUME;
if ((mStreamVolumeAlias[streamType] == AudioSystem.STREAM_MUSIC) &&
((device & mFixedVolumeDevices) != 0)) {
flags |= AudioManager.FLAG_FIXED_VOLUME;
@@ -1748,6 +1775,10 @@ public class AudioService extends IAudioService.Stub implements OnFinished {
}
}
+ // apply new ringer mode before checking volume for alias streams so that streams
+ // muted by ringer mode have the correct volume
+ setRingerModeInt(getRingerMode(), false);
+
checkAllAliasStreamVolumes();
synchronized (mSafeMediaVolumeState) {
@@ -1755,9 +1786,6 @@ public class AudioService extends IAudioService.Stub implements OnFinished {
enforceSafeMediaVolume();
}
}
-
- // apply new ringer mode
- setRingerModeInt(getRingerMode(), false);
}
/** @see AudioManager#setSpeakerphoneOn() */
@@ -2573,9 +2601,10 @@ public class AudioService extends IAudioService.Stub implements OnFinished {
AudioSystem.initStreamVolume(streamType, 0, mIndexMax);
mIndexMax *= 10;
- readSettings();
-
+ // mDeathHandlers must be created before calling readSettings()
mDeathHandlers = new ArrayList<VolumeDeathHandler>();
+
+ readSettings();
}
public String getSettingNameForDevice(boolean lastAudible, int device) {
@@ -2595,12 +2624,20 @@ public class AudioService extends IAudioService.Stub implements OnFinished {
// do not read system stream volume from settings: this stream is always aliased
// to another stream type and its volume is never persisted. Values in settings can
// only be stale values
+ // on first call to readSettings() at init time, muteCount() is always 0 so we will
+ // always create entries for default device
if ((mStreamType == AudioSystem.STREAM_SYSTEM) ||
(mStreamType == AudioSystem.STREAM_SYSTEM_ENFORCED)) {
- mLastAudibleIndex.put(AudioSystem.DEVICE_OUT_DEFAULT,
- 10 * AudioManager.DEFAULT_STREAM_VOLUME[mStreamType]);
- mIndex.put(AudioSystem.DEVICE_OUT_DEFAULT,
- 10 * AudioManager.DEFAULT_STREAM_VOLUME[mStreamType]);
+ int index = 10 * AudioManager.DEFAULT_STREAM_VOLUME[mStreamType];
+ synchronized (mCameraSoundForced) {
+ if (mCameraSoundForced) {
+ index = mIndexMax;
+ }
+ }
+ if (muteCount() == 0) {
+ mIndex.put(AudioSystem.DEVICE_OUT_DEFAULT, index);
+ }
+ mLastAudibleIndex.put(AudioSystem.DEVICE_OUT_DEFAULT, index);
return;
}
@@ -2611,6 +2648,15 @@ public class AudioService extends IAudioService.Stub implements OnFinished {
}
remainingDevices &= ~device;
+ // ignore settings for fixed volume devices: volume should always be at max
+ if ((mStreamVolumeAlias[mStreamType] == AudioSystem.STREAM_MUSIC) &&
+ ((device & mFixedVolumeDevices) != 0)) {
+ if (muteCount() == 0) {
+ mIndex.put(device, mIndexMax);
+ }
+ mLastAudibleIndex.put(device, mIndexMax);
+ continue;
+ }
// retrieve current volume for device
String name = getSettingNameForDevice(false /* lastAudible */, device);
// if no volume stored for current stream and device, use default volume if default
@@ -2662,7 +2708,9 @@ public class AudioService extends IAudioService.Stub implements OnFinished {
this,
PERSIST_DELAY);
}
- mIndex.put(device, getValidIndex(10 * index));
+ if (muteCount() == 0) {
+ mIndex.put(device, getValidIndex(10 * index));
+ }
}
}
@@ -2702,6 +2750,11 @@ public class AudioService extends IAudioService.Stub implements OnFinished {
public synchronized boolean setIndex(int index, int device, boolean lastAudible) {
int oldIndex = getIndex(device, false /* lastAudible */);
index = getValidIndex(index);
+ synchronized (mCameraSoundForced) {
+ if ((mStreamType == AudioSystem.STREAM_SYSTEM_ENFORCED) && mCameraSoundForced) {
+ index = mIndexMax;
+ }
+ }
mIndex.put(device, getValidIndex(index));
if (oldIndex != index) {
@@ -2796,7 +2849,27 @@ public class AudioService extends IAudioService.Stub implements OnFinished {
int device = ((Integer)entry.getKey()).intValue();
int index = ((Integer)entry.getValue()).intValue();
index = rescaleIndex(index, srcStream.getStreamType(), mStreamType);
- setIndex(index, device, lastAudible);
+
+ if (lastAudible) {
+ setLastAudibleIndex(index, device);
+ } else {
+ setIndex(index, device, false /* lastAudible */);
+ }
+ }
+ }
+
+ public synchronized void setAllIndexesToMax() {
+ Set set = mIndex.entrySet();
+ Iterator i = set.iterator();
+ while (i.hasNext()) {
+ Map.Entry entry = (Map.Entry)i.next();
+ entry.setValue(mIndexMax);
+ }
+ set = mLastAudibleIndex.entrySet();
+ i = set.iterator();
+ while (i.hasNext()) {
+ Map.Entry entry = (Map.Entry)i.next();
+ entry.setValue(mIndexMax);
}
}
@@ -2948,6 +3021,8 @@ public class AudioService extends IAudioService.Stub implements OnFinished {
}
private void dump(PrintWriter pw) {
+ pw.print(" Mute count: ");
+ pw.println(muteCount());
pw.print(" Current: ");
Set set = mIndex.entrySet();
Iterator i = set.iterator();
@@ -3196,6 +3271,8 @@ public class AudioService extends IAudioService.Stub implements OnFinished {
// Restore forced usage for communcations and record
AudioSystem.setForceUse(AudioSystem.FOR_COMMUNICATION, mForcedUseForComm);
AudioSystem.setForceUse(AudioSystem.FOR_RECORD, mForcedUseForComm);
+ AudioSystem.setForceUse(AudioSystem.FOR_SYSTEM, mCameraSoundForced ?
+ AudioSystem.FORCE_SYSTEM_ENFORCED : AudioSystem.FORCE_NONE);
// Restore stream volumes
int numStreamTypes = AudioSystem.getNumStreamTypes();
@@ -3353,6 +3430,13 @@ public class AudioService extends IAudioService.Stub implements OnFinished {
} else {
ringerModeAffectedStreams |= (1 << AudioSystem.STREAM_MUSIC);
}
+ synchronized (mCameraSoundForced) {
+ if (mCameraSoundForced) {
+ ringerModeAffectedStreams &= ~(1 << AudioSystem.STREAM_SYSTEM_ENFORCED);
+ } else {
+ ringerModeAffectedStreams |= (1 << AudioSystem.STREAM_SYSTEM_ENFORCED);
+ }
+ }
if (ringerModeAffectedStreams != mRingerModeAffectedStreams) {
/*
* Ensure all stream types that should be affected by ringer mode
@@ -5568,6 +5652,48 @@ public class AudioService extends IAudioService.Stub implements OnFinished {
0,
null,
0);
+
+ boolean cameraSoundForced = mContext.getResources().getBoolean(
+ com.android.internal.R.bool.config_camera_sound_forced);
+ synchronized (mSettingsLock) {
+ synchronized (mCameraSoundForced) {
+ 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],
+ false /*lastAudible*/);
+ s.setAllIndexes(mStreamStates[AudioSystem.STREAM_SYSTEM],
+ true /*lastAudible*/);
+ mRingerModeAffectedStreams |=
+ (1 << AudioSystem.STREAM_SYSTEM_ENFORCED);
+ }
+ // take new state into account for streams muted by ringer mode
+ setRingerModeInt(getRingerMode(), false);
+
+ sendMsg(mAudioHandler,
+ MSG_SET_FORCE_USE,
+ SENDMSG_QUEUE,
+ AudioSystem.FOR_SYSTEM,
+ cameraSoundForced ?
+ AudioSystem.FORCE_SYSTEM_ENFORCED : AudioSystem.FORCE_NONE,
+ null,
+ 0);
+
+ sendMsg(mAudioHandler,
+ MSG_SET_ALL_VOLUMES,
+ SENDMSG_QUEUE,
+ 0,
+ 0,
+ mStreamStates[AudioSystem.STREAM_SYSTEM_ENFORCED], 0);
+ }
+ }
+ }
} catch (Exception e) {
Log.e(TAG, "Error retrieving device orientation: " + e);
}
@@ -5743,6 +5869,38 @@ public class AudioService extends IAudioService.Stub implements OnFinished {
}
+ //==========================================================================================
+ // Camera shutter sound policy.
+ // config_camera_sound_forced configuration option in config.xml defines if the camera shutter
+ // sound is forced (sound even if the device is in silent mode) or not. This option is false by
+ // default and can be overridden by country specific overlay in values-mccXXX/config.xml.
+ //==========================================================================================
+
+ // cached value of com.android.internal.R.bool.config_camera_sound_forced
+ private Boolean mCameraSoundForced;
+
+ // called by android.hardware.Camera to populate CameraInfo.canDisableShutterSound
+ public boolean isCameraSoundForced() {
+ synchronized (mCameraSoundForced) {
+ return mCameraSoundForced;
+ }
+ }
+
+ private static final String[] RINGER_MODE_NAMES = new String[] {
+ "SILENT",
+ "VIBRATE",
+ "NORMAL"
+ };
+
+ private void dumpRingerMode(PrintWriter pw) {
+ pw.println("\nRinger mode: ");
+ pw.println("- mode: "+RINGER_MODE_NAMES[mRingerMode]);
+ pw.print("- ringer mode affected streams = 0x");
+ pw.println(Integer.toHexString(mRingerModeAffectedStreams));
+ pw.print("- ringer mode muted streams = 0x");
+ pw.println(Integer.toHexString(mRingerModeMutedStreams));
+ }
+
@Override
protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DUMP, TAG);
@@ -5751,6 +5909,7 @@ public class AudioService extends IAudioService.Stub implements OnFinished {
dumpRCStack(pw);
dumpRCCStack(pw);
dumpStreamStates(pw);
+ dumpRingerMode(pw);
pw.println("\nAudio routes:");
pw.print(" mMainType=0x"); pw.println(Integer.toHexString(mCurAudioRoutes.mMainType));
pw.print(" mBluetoothName="); pw.println(mCurAudioRoutes.mBluetoothName);
diff --git a/media/java/android/media/AudioSystem.java b/media/java/android/media/AudioSystem.java
index 2cff4ff..103e817 100644
--- a/media/java/android/media/AudioSystem.java
+++ b/media/java/android/media/AudioSystem.java
@@ -354,7 +354,8 @@ public class AudioSystem
public static final int FORCE_DIGITAL_DOCK = 9;
public static final int FORCE_NO_BT_A2DP = 10;
public static final int FORCE_REMOTE_SUBMIX = 11;
- private static final int NUM_FORCE_CONFIG = 12;
+ public static final int FORCE_SYSTEM_ENFORCED = 12;
+ private static final int NUM_FORCE_CONFIG = 13;
public static final int FORCE_DEFAULT = FORCE_NONE;
// usage for setForceUse, must match AudioSystem::force_use
@@ -362,7 +363,8 @@ public class AudioSystem
public static final int FOR_MEDIA = 1;
public static final int FOR_RECORD = 2;
public static final int FOR_DOCK = 3;
- private static final int NUM_FORCE_USE = 4;
+ public static final int FOR_SYSTEM = 4;
+ private static final int NUM_FORCE_USE = 5;
// usage for AudioRecord.startRecordingSync(), must match AudioSystem::sync_event_t
public static final int SYNC_EVENT_NONE = 0;
diff --git a/media/java/android/media/IAudioService.aidl b/media/java/android/media/IAudioService.aidl
index 7ae61cd..ea99069 100644
--- a/media/java/android/media/IAudioService.aidl
+++ b/media/java/android/media/IAudioService.aidl
@@ -153,4 +153,6 @@ interface IAudioService {
int setBluetoothA2dpDeviceConnectionState(in BluetoothDevice device, int state);
AudioRoutesInfo startWatchingRoutes(in IAudioRoutesObserver observer);
+
+ boolean isCameraSoundForced();
}
diff --git a/media/java/android/media/MediaRouter.java b/media/java/android/media/MediaRouter.java
index e5b9637..16ad74f 100644
--- a/media/java/android/media/MediaRouter.java
+++ b/media/java/android/media/MediaRouter.java
@@ -693,7 +693,8 @@ public class MediaRouter {
final WifiDisplayStatus oldStatus = sStatic.mLastKnownWifiDisplayStatus;
// TODO Naive implementation. Make this smarter later.
- boolean needScan = false;
+ boolean wantScan = false;
+ boolean blockScan = false;
WifiDisplay[] oldDisplays = oldStatus != null ?
oldStatus.getRememberedDisplays() : new WifiDisplay[0];
WifiDisplay[] newDisplays = newStatus.getRememberedDisplays();
@@ -704,8 +705,9 @@ public class MediaRouter {
final WifiDisplay d = newDisplays[i];
final WifiDisplay oldRemembered = findMatchingDisplay(d, oldDisplays);
if (oldRemembered == null) {
- addRouteStatic(makeWifiDisplayRoute(d));
- needScan = true;
+ addRouteStatic(makeWifiDisplayRoute(d,
+ findMatchingDisplay(d, availableDisplays) != null));
+ wantScan = true;
} else {
final boolean available = findMatchingDisplay(d, availableDisplays) != null;
final RouteInfo route = findWifiDisplayRoute(d);
@@ -715,6 +717,10 @@ public class MediaRouter {
final RouteInfo activeRoute = findWifiDisplayRoute(d);
if (activeRoute != null) {
selectRouteStatic(activeRoute.getSupportedTypes(), activeRoute);
+
+ // Don't scan if we're already connected to a wifi display,
+ // the scanning process can cause a hiccup with some configurations.
+ blockScan = true;
}
}
}
@@ -726,22 +732,23 @@ public class MediaRouter {
}
}
- if (needScan) {
+ if (wantScan && !blockScan) {
sStatic.mDisplayService.scanWifiDisplays();
}
sStatic.mLastKnownWifiDisplayStatus = newStatus;
}
- static RouteInfo makeWifiDisplayRoute(WifiDisplay display) {
+ static RouteInfo makeWifiDisplayRoute(WifiDisplay display, boolean available) {
final RouteInfo newRoute = new RouteInfo(sStatic.mSystemCategory);
newRoute.mDeviceAddress = display.getDeviceAddress();
newRoute.mSupportedTypes = ROUTE_TYPE_LIVE_AUDIO | ROUTE_TYPE_LIVE_VIDEO;
newRoute.mVolumeHandling = RouteInfo.PLAYBACK_VOLUME_FIXED;
newRoute.mPlaybackType = RouteInfo.PLAYBACK_TYPE_REMOTE;
- newRoute.mStatus = sStatic.mResources.getText(
- com.android.internal.R.string.media_route_status_connecting);
- newRoute.mEnabled = false;
+
+ newRoute.setStatusCode(available ?
+ RouteInfo.STATUS_AVAILABLE : RouteInfo.STATUS_CONNECTING);
+ newRoute.mEnabled = available;
newRoute.mName = makeWifiDisplayName(display);
return newRoute;
diff --git a/media/jni/android_media_MediaPlayer.cpp b/media/jni/android_media_MediaPlayer.cpp
index 04ba348..ad536f2 100644
--- a/media/jni/android_media_MediaPlayer.cpp
+++ b/media/jni/android_media_MediaPlayer.cpp
@@ -274,6 +274,11 @@ setVideoSurface(JNIEnv *env, jobject thiz, jobject jsurface, jboolean mediaPlaye
sp<Surface> surface(android_view_Surface_getSurface(env, jsurface));
if (surface != NULL) {
new_st = surface->getSurfaceTexture();
+ if (new_st == NULL) {
+ jniThrowException(env, "java/lang/IllegalArgumentException",
+ "The surface does not have a binding SurfaceTexture!");
+ return;
+ }
new_st->incStrong(thiz);
} else {
jniThrowException(env, "java/lang/IllegalArgumentException",