diff options
10 files changed, 179 insertions, 33 deletions
diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java index db67fbf..3fc3646 100644 --- a/media/java/android/media/AudioManager.java +++ b/media/java/android/media/AudioManager.java @@ -3214,6 +3214,18 @@ public class AudioManager { } /** + * 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 abstract class AudioManagerInternal { 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.IRemoteVolumeObserver; 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 @@ interface IAudioService { 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 @@ public class PhoneStatusBarPolicy { 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.content.res.Configuration; 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 @@ public class VolumeUI extends SystemUI { 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.IRingtonePlayer; 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 @@ public class AudioService extends IAudioService.Stub { /** 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 @@ public class AudioService extends IAudioService.Stub { 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 @@ public class AudioService extends IAudioService.Stub { // 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 @@ public class AudioService extends IAudioService.Stub { 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 @@ public class AudioService extends IAudioService.Stub { 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 @@ public class AudioService extends IAudioService.Stub { } if (mRingerModeDelegate != null) { ringerMode = mRingerModeDelegate.onSetRingerModeInternal(ringerModeInternal, - ringerMode, caller, ringerModeExternal); + ringerMode, caller, ringerModeExternal, mVolumePolicy); } setRingerModeExt(ringerMode); } @@ -1785,12 +1783,12 @@ public class AudioService extends IAudioService.Stub { 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 @@ public class AudioService extends IAudioService.Stub { * 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 @@ public class AudioService extends IAudioService.Stub { } 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 @@ public class AudioService extends IAudioService.Stub { } 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 @@ public class AudioService extends IAudioService.Stub { 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 @@ public class AudioService extends IAudioService.Stub { 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 @@ public class AudioService extends IAudioService.Stub { 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.database.ContentObserver; 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 @@ public class ZenModeHelper implements AudioManagerInternal.RingerModeDelegate { @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 @@ public class ZenModeHelper implements AudioManagerInternal.RingerModeDelegate { 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 @@ public class ZenModeHelper implements AudioManagerInternal.RingerModeDelegate { @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; |