Merge "Volume policy updates."
diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java
index 85aaf4c..4fdcfa4 100644
--- a/media/java/android/media/AudioManager.java
+++ b/media/java/android/media/AudioManager.java
@@ -3217,6 +3217,18 @@
}
/**
+ * Only useful for volume controllers.
+ * @hide
+ */
+ public void setVolumePolicy(VolumePolicy policy) {
+ try {
+ getService().setVolumePolicy(policy);
+ } catch (RemoteException e) {
+ Log.w(TAG, "Error calling setVolumePolicy", e);
+ }
+ }
+
+ /**
* Set Hdmi Cec system audio mode.
*
* @param on whether to be on system audio mode
diff --git a/media/java/android/media/AudioManagerInternal.java b/media/java/android/media/AudioManagerInternal.java
index d456b7e..abb4257 100644
--- a/media/java/android/media/AudioManagerInternal.java
+++ b/media/java/android/media/AudioManagerInternal.java
@@ -46,10 +46,10 @@
public interface RingerModeDelegate {
/** Called when external ringer mode is evaluated, returns the new internal ringer mode */
int onSetRingerModeExternal(int ringerModeOld, int ringerModeNew, String caller,
- int ringerModeInternal);
+ int ringerModeInternal, VolumePolicy policy);
/** Called when internal ringer mode is evaluated, returns the new external ringer mode */
int onSetRingerModeInternal(int ringerModeOld, int ringerModeNew, String caller,
- int ringerModeExternal);
+ int ringerModeExternal, VolumePolicy policy);
}
}
diff --git a/media/java/android/media/IAudioService.aidl b/media/java/android/media/IAudioService.aidl
index 2e8e017..827cb13 100644
--- a/media/java/android/media/IAudioService.aidl
+++ b/media/java/android/media/IAudioService.aidl
@@ -29,6 +29,7 @@
import android.media.IRingtonePlayer;
import android.media.IVolumeController;
import android.media.Rating;
+import android.media.VolumePolicy;
import android.media.audiopolicy.AudioPolicyConfig;
import android.media.audiopolicy.IAudioPolicyCallback;
import android.net.Uri;
@@ -204,9 +205,12 @@
boolean isHdmiSystemAudioSupported();
- String registerAudioPolicy(in AudioPolicyConfig policyConfig,
- in IAudioPolicyCallback pcb, boolean hasFocusListener);
+ String registerAudioPolicy(in AudioPolicyConfig policyConfig,
+ in IAudioPolicyCallback pcb, boolean hasFocusListener);
+
oneway void unregisterAudioPolicyAsync(in IAudioPolicyCallback pcb);
- int setFocusPropertiesForPolicy(int duckingBehavior, in IAudioPolicyCallback pcb);
+ int setFocusPropertiesForPolicy(int duckingBehavior, in IAudioPolicyCallback pcb);
+
+ void setVolumePolicy(in VolumePolicy policy);
}
diff --git a/media/java/android/media/VolumePolicy.aidl b/media/java/android/media/VolumePolicy.aidl
new file mode 100644
index 0000000..371f798
--- /dev/null
+++ b/media/java/android/media/VolumePolicy.aidl
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) 2015 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;
+
+parcelable VolumePolicy;
diff --git a/media/java/android/media/VolumePolicy.java b/media/java/android/media/VolumePolicy.java
new file mode 100644
index 0000000..677a0ef
--- /dev/null
+++ b/media/java/android/media/VolumePolicy.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.media;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/** @hide */
+public final class VolumePolicy implements Parcelable {
+ public static final VolumePolicy DEFAULT = new VolumePolicy(false, false, true);
+
+ public final boolean volumeDownToEnterSilent;
+ public final boolean volumeUpToExitSilent;
+ public final boolean doNotDisturbWhenSilent;
+
+ public VolumePolicy(boolean volumeDownToEnterSilent, boolean volumeUpToExitSilent,
+ boolean doNotDisturbWhenSilent) {
+ this.volumeDownToEnterSilent = volumeDownToEnterSilent;
+ this.volumeUpToExitSilent = volumeUpToExitSilent;
+ this.doNotDisturbWhenSilent = doNotDisturbWhenSilent;
+ }
+
+ @Override
+ public String toString() {
+ return "VolumePolicy[volumeDownToEnterSilent=" + volumeDownToEnterSilent
+ + ",volumeUpToExitSilent=" + volumeUpToExitSilent
+ + ",doNotDisturbWhenSilent=" + doNotDisturbWhenSilent + "]";
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeInt(volumeDownToEnterSilent ? 1 : 0);
+ dest.writeInt(volumeUpToExitSilent ? 1 : 0);
+ dest.writeInt(doNotDisturbWhenSilent ? 1 : 0);
+ }
+
+ public static final Parcelable.Creator<VolumePolicy> CREATOR
+ = new Parcelable.Creator<VolumePolicy>() {
+ @Override
+ public VolumePolicy createFromParcel(Parcel p) {
+ return new VolumePolicy(p.readInt() != 0, p.readInt() != 0, p.readInt() != 0);
+ }
+
+ @Override
+ public VolumePolicy[] newArray(int size) {
+ return new VolumePolicy[size];
+ }
+ };
+}
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/stat_sys_ringer_silent.xml b/packages/SystemUI/res/drawable/stat_sys_ringer_silent.xml
new file mode 100644
index 0000000..36e6cef
--- /dev/null
+++ b/packages/SystemUI/res/drawable/stat_sys_ringer_silent.xml
@@ -0,0 +1,27 @@
+<!--
+Copyright (C) 2015 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.
+-->
+<inset xmlns:android="http://schemas.android.com/apk/res/android"
+ android:insetLeft="3dp"
+ android:insetRight="3dp">
+ <vector android:width="18dp"
+ android:height="18dp"
+ android:viewportWidth="48.0"
+ android:viewportHeight="48.0">
+ <path
+ android:fillColor="#FFFFFFFF"
+ android:pathData="M23.000000,44.000000c2.200000,0.000000 4.000000,-1.800000 4.000000,-4.000000l-8.000000,0.000000C19.000000,42.200001 20.799999,44.000000 23.000000,44.000000zM36.000000,21.000000c0.000000,-6.100000 -4.300000,-11.300000 -10.000000,-12.600000L26.000000,7.000000c0.000000,-1.700000 -1.300000,-3.000000 -3.000000,-3.000000c-1.700000,0.000000 -3.000000,1.300000 -3.000000,3.000000l0.000000,1.400000c-1.000000,0.200000 -2.000000,0.600000 -2.900000,1.100000L36.000000,28.400000L36.000000,21.000000zM35.500000,38.000000l4.000000,4.000000l2.500000,-2.500000L8.500000,6.000000L6.000000,8.500000l5.800000,5.800000C10.700000,16.299999 10.000000,18.600000 10.000000,21.000000l0.000000,11.000000l-4.000000,4.000000l0.000000,2.000000L35.500000,38.000000z"/>
+ </vector>
+</inset>
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
index 5da8457..2236aae 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
@@ -213,7 +213,12 @@
zenDescription = mContext.getString(R.string.zen_important_interruptions);
}
- if (mZen != Global.ZEN_MODE_NO_INTERRUPTIONS &&
+ if (DndTile.isVisible(mContext)
+ && audioManager.getRingerModeInternal() == AudioManager.RINGER_MODE_SILENT) {
+ volumeVisible = true;
+ volumeIconId = R.drawable.stat_sys_ringer_silent;
+ volumeDescription = mContext.getString(R.string.accessibility_ringer_silent);
+ } else if (mZen != Global.ZEN_MODE_NO_INTERRUPTIONS &&
audioManager.getRingerModeInternal() == AudioManager.RINGER_MODE_VIBRATE) {
volumeVisible = true;
volumeIconId = R.drawable.stat_sys_ringer_vibrate;
diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeUI.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeUI.java
index 7603c7d..687452d 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/VolumeUI.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeUI.java
@@ -31,6 +31,7 @@
import android.media.AudioManager;
import android.media.IRemoteVolumeController;
import android.media.IVolumeController;
+import android.media.VolumePolicy;
import android.media.session.ISessionController;
import android.media.session.MediaController;
import android.media.session.MediaSessionManager;
@@ -114,6 +115,7 @@
if (register) {
if (LOGD) Log.d(TAG, "Registering default volume controller");
mAudioManager.setVolumeController(mVolumeController);
+ mAudioManager.setVolumePolicy(VolumePolicy.DEFAULT);
mMediaSessionManager.setRemoteVolumeController(mRemoteVolumeController);
DndTile.setVisible(mContext, false);
} else {
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index 1208c04..bd3175f 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -62,6 +62,7 @@
import android.media.IVolumeController;
import android.media.MediaPlayer;
import android.media.SoundPool;
+import android.media.VolumePolicy;
import android.media.MediaPlayer.OnCompletionListener;
import android.media.MediaPlayer.OnErrorListener;
import android.media.audiopolicy.AudioPolicy;
@@ -145,12 +146,6 @@
/** debug calls to devices APIs */
protected static final boolean DEBUG_DEVICES = Log.isLoggable(TAG + ".DEVICES", Log.DEBUG);
- /** Allow volume changes to set ringer mode to silent? */
- private static final boolean VOLUME_SETS_RINGER_MODE_SILENT = false;
-
- /** In silent mode, are volume adjustments (raises) prevented? */
- private static final boolean PREVENT_VOLUME_ADJUSTMENT_IF_SILENT = true;
-
/** How long to delay before persisting a change in volume/ringer mode. */
private static final int PERSIST_DELAY = 500;
@@ -534,6 +529,7 @@
private static Long mLastDeviceConnectMsgTime = new Long(0);
private AudioManagerInternal.RingerModeDelegate mRingerModeDelegate;
+ private VolumePolicy mVolumePolicy = VolumePolicy.DEFAULT;
// Intent "extra" data keys.
public static final String CONNECT_INTENT_KEY_PORT_NAME = "portName";
@@ -1133,8 +1129,10 @@
// unmute immediately for volume up
streamState.mute(false);
} else if (direction == AudioManager.ADJUST_LOWER) {
- sendMsg(mAudioHandler, MSG_UNMUTE_STREAM, SENDMSG_QUEUE,
- streamTypeAlias, flags, null, UNMUTE_STREAM_DELAY);
+ if (mPlatformType == AudioSystem.PLATFORM_TELEVISION) {
+ sendMsg(mAudioHandler, MSG_UNMUTE_STREAM, SENDMSG_QUEUE,
+ streamTypeAlias, flags, null, UNMUTE_STREAM_DELAY);
+ }
}
}
sendMsg(mAudioHandler,
@@ -1234,7 +1232,7 @@
int newRingerMode;
if (index == 0) {
newRingerMode = mHasVibrator ? AudioManager.RINGER_MODE_VIBRATE
- : VOLUME_SETS_RINGER_MODE_SILENT ? AudioManager.RINGER_MODE_SILENT
+ : mVolumePolicy.volumeDownToEnterSilent ? AudioManager.RINGER_MODE_SILENT
: AudioManager.RINGER_MODE_NORMAL;
} else {
newRingerMode = AudioManager.RINGER_MODE_NORMAL;
@@ -1730,7 +1728,7 @@
setRingerModeExt(ringerMode);
if (mRingerModeDelegate != null) {
ringerMode = mRingerModeDelegate.onSetRingerModeExternal(ringerModeExternal,
- ringerMode, caller, ringerModeInternal);
+ ringerMode, caller, ringerModeInternal, mVolumePolicy);
}
if (ringerMode != ringerModeInternal) {
setRingerModeInt(ringerMode, true /*persist*/);
@@ -1741,7 +1739,7 @@
}
if (mRingerModeDelegate != null) {
ringerMode = mRingerModeDelegate.onSetRingerModeInternal(ringerModeInternal,
- ringerMode, caller, ringerModeExternal);
+ ringerMode, caller, ringerModeExternal, mVolumePolicy);
}
setRingerModeExt(ringerMode);
}
@@ -1785,12 +1783,12 @@
if ((isPlatformVoice() || mHasVibrator) &&
mStreamVolumeAlias[streamType] == AudioSystem.STREAM_RING) {
synchronized (VolumeStreamState.class) {
- SparseIntArray indexMap = mStreamStates[streamType].mIndexMap;
- for (int i = 0; i < indexMap.size(); i++) {
- int device = indexMap.keyAt(i);
- int value = indexMap.valueAt(i);
+ final VolumeStreamState vss = mStreamStates[streamType];
+ for (int i = 0; i < vss.mIndexMap.size(); i++) {
+ int device = vss.mIndexMap.keyAt(i);
+ int value = vss.mIndexMap.valueAt(i);
if (value == 0) {
- indexMap.put(device, 10);
+ vss.setIndex(10, device, TAG);
}
}
// Persist volume for stream ring when it is changed here
@@ -2933,7 +2931,8 @@
* adjusting volume. If so, this will set the proper ringer mode and volume
* indices on the stream states.
*/
- private int checkForRingerModeChange(int oldIndex, int direction, int step, boolean isMuted) {
+ private int checkForRingerModeChange(int oldIndex, int direction, int step, boolean isMuted) {
+ final boolean isTv = mPlatformType == AudioSystem.PLATFORM_TELEVISION;
int result = FLAG_ADJUST_VOLUME;
int ringerMode = getRingerModeInternal();
@@ -2952,13 +2951,13 @@
} else {
// (oldIndex < step) is equivalent to (old UI index == 0)
if ((oldIndex < step)
- && VOLUME_SETS_RINGER_MODE_SILENT
+ && mVolumePolicy.volumeDownToEnterSilent
&& mPrevVolDirection != AudioManager.ADJUST_LOWER) {
ringerMode = RINGER_MODE_SILENT;
}
}
- } else if (direction == AudioManager.ADJUST_TOGGLE_MUTE
- || direction == AudioManager.ADJUST_MUTE) {
+ } else if (isTv && (direction == AudioManager.ADJUST_TOGGLE_MUTE
+ || direction == AudioManager.ADJUST_MUTE)) {
if (mHasVibrator) {
ringerMode = RINGER_MODE_VIBRATE;
} else {
@@ -2976,10 +2975,10 @@
}
if ((direction == AudioManager.ADJUST_LOWER)) {
// This is the case we were muted with the volume turned up
- if (oldIndex >= 2 * step && isMuted) {
+ if (isTv && oldIndex >= 2 * step && isMuted) {
ringerMode = RINGER_MODE_NORMAL;
} else if (mPrevVolDirection != AudioManager.ADJUST_LOWER) {
- if (VOLUME_SETS_RINGER_MODE_SILENT) {
+ if (mVolumePolicy.volumeDownToEnterSilent) {
ringerMode = RINGER_MODE_SILENT;
} else {
result |= AudioManager.FLAG_SHOW_VIBRATE_HINT;
@@ -2993,13 +2992,13 @@
result &= ~FLAG_ADJUST_VOLUME;
break;
case RINGER_MODE_SILENT:
- if (direction == AudioManager.ADJUST_LOWER && oldIndex >= 2 * step && isMuted) {
+ if (isTv && direction == AudioManager.ADJUST_LOWER && oldIndex >= 2 * step && isMuted) {
// This is the case we were muted with the volume turned up
ringerMode = RINGER_MODE_NORMAL;
} else if (direction == AudioManager.ADJUST_RAISE
|| direction == AudioManager.ADJUST_TOGGLE_MUTE
|| direction == AudioManager.ADJUST_UNMUTE) {
- if (PREVENT_VOLUME_ADJUSTMENT_IF_SILENT) {
+ if (!mVolumePolicy.volumeUpToExitSilent) {
result |= AudioManager.FLAG_SHOW_SILENT_HINT;
} else {
if (mHasVibrator && direction == AudioManager.ADJUST_RAISE) {
@@ -5418,6 +5417,7 @@
pw.print(" mCameraSoundForced="); pw.println(mCameraSoundForced);
pw.print(" mHasVibrator="); pw.println(mHasVibrator);
pw.print(" mControllerService="); pw.println(mControllerService);
+ pw.print(" mVolumePolicy="); pw.println(mVolumePolicy);
dumpAudioPolicies(pw);
}
@@ -5493,6 +5493,14 @@
if (DEBUG_VOL) Log.d(TAG, "Volume controller visible: " + visible);
}
+ @Override
+ public void setVolumePolicy(VolumePolicy policy) {
+ enforceVolumeController("set volume policy");
+ if (policy != null) {
+ mVolumePolicy = policy;
+ }
+ }
+
public static class VolumeController {
private static final String TAG = "VolumeController";
diff --git a/services/core/java/com/android/server/notification/ZenModeHelper.java b/services/core/java/com/android/server/notification/ZenModeHelper.java
index 841fc21..a985b01 100644
--- a/services/core/java/com/android/server/notification/ZenModeHelper.java
+++ b/services/core/java/com/android/server/notification/ZenModeHelper.java
@@ -31,6 +31,7 @@
import android.media.AudioAttributes;
import android.media.AudioManager;
import android.media.AudioManagerInternal;
+import android.media.VolumePolicy;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
@@ -334,7 +335,7 @@
@Override // RingerModeDelegate
public int onSetRingerModeInternal(int ringerModeOld, int ringerModeNew, String caller,
- int ringerModeExternal) {
+ int ringerModeExternal, VolumePolicy policy) {
final boolean isChange = ringerModeOld != ringerModeNew;
int ringerModeExternalOut = ringerModeNew;
@@ -342,7 +343,7 @@
int newZen = -1;
switch (ringerModeNew) {
case AudioManager.RINGER_MODE_SILENT:
- if (isChange) {
+ if (isChange && policy.doNotDisturbWhenSilent) {
if (mZenMode != Global.ZEN_MODE_NO_INTERRUPTIONS) {
newZen = Global.ZEN_MODE_NO_INTERRUPTIONS;
}
@@ -371,7 +372,7 @@
@Override // RingerModeDelegate
public int onSetRingerModeExternal(int ringerModeOld, int ringerModeNew, String caller,
- int ringerModeInternal) {
+ int ringerModeInternal, VolumePolicy policy) {
int ringerModeInternalOut = ringerModeNew;
final boolean isChange = ringerModeOld != ringerModeNew;
final boolean isVibrate = ringerModeInternal == AudioManager.RINGER_MODE_VIBRATE;