Fields Summary |
---|
private static final String | TAG |
private static boolean | LOGD |
private static final int | PLAY_SOUND_DELAY |
public static final int | VIBRATE_DELAYThe delay before vibrating. This small period exists so if the user is
moving to silent mode, it will not emit a short vibrate (it normally
would since vibrate is between normal mode and silent mode using hardware
keys). |
private static final int | VIBRATE_DURATION |
private static final int | BEEP_DURATION |
private static final int | MAX_VOLUME |
private static final int | FREE_DELAY |
private static final int | TIMEOUT_DELAY |
private static final int | TIMEOUT_DELAY_SHORT |
private static final int | TIMEOUT_DELAY_COLLAPSED |
private static final int | TIMEOUT_DELAY_SAFETY_WARNING |
private static final int | TIMEOUT_DELAY_EXPANDED |
private static final int | MSG_VOLUME_CHANGED |
private static final int | MSG_FREE_RESOURCES |
private static final int | MSG_PLAY_SOUND |
private static final int | MSG_STOP_SOUNDS |
private static final int | MSG_VIBRATE |
private static final int | MSG_TIMEOUT |
private static final int | MSG_RINGER_MODE_CHANGED |
private static final int | MSG_MUTE_CHANGED |
private static final int | MSG_REMOTE_VOLUME_CHANGED |
private static final int | MSG_REMOTE_VOLUME_UPDATE_IF_SHOWN |
private static final int | MSG_SLIDER_VISIBILITY_CHANGED |
private static final int | MSG_DISPLAY_SAFE_VOLUME_WARNING |
private static final int | MSG_LAYOUT_DIRECTION |
private static final int | MSG_ZEN_MODE_AVAILABLE_CHANGED |
private static final int | MSG_USER_ACTIVITY |
private static final int | MSG_NOTIFICATION_EFFECTS_SUPPRESSOR_CHANGED |
private static final int | MSG_INTERNAL_RINGER_MODE_CHANGED |
private static final int | STREAM_MASTER |
private static final int | STREAM_REMOTE_MUSIC |
private static final android.media.AudioAttributes | VIBRATION_ATTRIBUTES |
private static final int | IC_AUDIO_VOL |
private static final int | IC_AUDIO_VOL_MUTE |
private static final int | IC_AUDIO_BT |
private static final int | IC_AUDIO_BT_MUTE |
private final String | mTag |
protected final android.content.Context | mContext |
private final android.media.AudioManager | mAudioManager |
private final com.android.systemui.statusbar.policy.ZenModeController | mZenController |
private boolean | mRingIsSilent |
private boolean | mVoiceCapable |
private boolean | mZenModeAvailable |
private boolean | mZenPanelExpanded |
private int | mTimeoutDelay |
private float | mDisabledAlpha |
private int | mLastRingerMode |
private int | mLastRingerProgress |
private int | mDemoIcon |
private final boolean | mPlayMasterStreamTones |
private final android.view.View | mViewVolume panel content view |
private final android.app.Dialog | mDialogDialog hosting the panel |
private final android.view.ViewGroup | mPanelThe visible portion of the volume overlay |
private final android.view.ViewGroup | mSliderPanelContains the slider and its touchable icons |
private ZenModePanel | mZenPanelThe zen mode configuration panel view |
private android.content.ComponentName | mNotificationEffectsSuppressorThe component currently suppressing notification stream effects |
private Callback | mCallback |
private int | mActiveStreamTypeCurrently active stream that shows up at the top of the list of sliders |
private android.util.SparseArray | mStreamControlsAll the slider controls mapped by stream type |
private final android.view.accessibility.AccessibilityManager | mAccessibilityManager |
private final SecondaryIconTransition | mSecondaryIconTransition |
private final IconPulser | mIconPulser |
private static final StreamResources[] | STREAMS |
private android.media.ToneGenerator[] | mToneGenerators |
private android.os.Vibrator | mVibrator |
private boolean | mHasVibrator |
private static android.app.AlertDialog | sSafetyWarning |
private static Object | sSafetyWarningLock |
private final android.widget.SeekBar.OnSeekBarChangeListener | mSeekListener |
private final ZenModeController.Callback | mZenCallback |
private final MediaController.Callback | mMediaControllerCb |
Methods Summary |
---|
private void | announceDialogShown()
mView.sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED);
|
private void | clearRemoteStreamController()Clear the current remote stream controller.
if (mStreamControls != null) {
StreamControl sc = mStreamControls.get(STREAM_REMOTE_MUSIC);
if (sc != null) {
if (sc.controller != null) {
sc.controller.unregisterCallback(mMediaControllerCb);
sc.controller = null;
}
}
}
|
private void | createSliders()
final Resources res = mContext.getResources();
final LayoutInflater inflater = (LayoutInflater) mContext.getSystemService(
Context.LAYOUT_INFLATER_SERVICE);
mStreamControls = new SparseArray<StreamControl>(STREAMS.length);
final StreamResources notificationStream = StreamResources.NotificationStream;
for (int i = 0; i < STREAMS.length; i++) {
StreamResources streamRes = STREAMS[i];
final int streamType = streamRes.streamType;
final boolean isNotification = isNotificationOrRing(streamType);
final StreamControl sc = new StreamControl();
sc.streamType = streamType;
sc.group = (ViewGroup) inflater.inflate(
com.android.systemui.R.layout.volume_panel_item, null);
sc.group.setTag(sc);
sc.icon = (ImageView) sc.group.findViewById(com.android.systemui.R.id.stream_icon);
sc.icon.setTag(sc);
sc.icon.setContentDescription(res.getString(streamRes.descRes));
sc.iconRes = streamRes.iconRes;
sc.iconMuteRes = streamRes.iconMuteRes;
sc.icon.setImageResource(sc.iconRes);
sc.icon.setClickable(isNotification && mHasVibrator);
if (isNotification) {
if (mHasVibrator) {
sc.icon.setSoundEffectsEnabled(false);
sc.iconMuteRes = com.android.systemui.R.drawable.ic_ringer_vibrate;
sc.icon.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
resetTimeout();
toggleRinger(sc);
}
});
}
sc.iconSuppressedRes = com.android.systemui.R.drawable.ic_ringer_mute;
}
sc.seekbarView = (SeekBar) sc.group.findViewById(com.android.systemui.R.id.seekbar);
sc.suppressorView =
(TextView) sc.group.findViewById(com.android.systemui.R.id.suppressor);
sc.suppressorView.setVisibility(View.GONE);
final boolean showSecondary = !isNotification && notificationStream.show;
sc.divider = sc.group.findViewById(com.android.systemui.R.id.divider);
sc.secondaryIcon = (ImageView) sc.group
.findViewById(com.android.systemui.R.id.secondary_icon);
sc.secondaryIcon.setImageResource(com.android.systemui.R.drawable.ic_ringer_audible);
sc.secondaryIcon.setContentDescription(res.getString(notificationStream.descRes));
sc.secondaryIcon.setClickable(showSecondary);
sc.divider.setVisibility(showSecondary ? View.VISIBLE : View.GONE);
sc.secondaryIcon.setVisibility(showSecondary ? View.VISIBLE : View.GONE);
if (showSecondary) {
sc.secondaryIcon.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
mSecondaryIconTransition.start(sc);
}
});
}
final int plusOne = (streamType == AudioSystem.STREAM_BLUETOOTH_SCO ||
streamType == AudioSystem.STREAM_VOICE_CALL) ? 1 : 0;
sc.seekbarView.setMax(getStreamMaxVolume(streamType) + plusOne);
sc.seekbarView.setOnSeekBarChangeListener(mSeekListener);
sc.seekbarView.setTag(sc);
mStreamControls.put(streamType, sc);
}
|
public void | dispatchDemoCommand(java.lang.String command, android.os.Bundle args)
if (!COMMAND_VOLUME.equals(command)) return;
String icon = args.getString("icon");
final String iconMute = args.getString("iconmute");
final boolean mute = iconMute != null;
icon = mute ? iconMute : icon;
icon = icon.endsWith("Stream") ? icon : (icon + "Stream");
final StreamResources sr = StreamResources.valueOf(icon);
mDemoIcon = mute ? sr.iconMuteRes : sr.iconRes;
final int forcedStreamType = StreamResources.MediaStream.streamType;
mAudioManager.forceVolumeControlStream(forcedStreamType);
mAudioManager.adjustStreamVolume(forcedStreamType, AudioManager.ADJUST_SAME,
AudioManager.FLAG_SHOW_UI);
|
public void | dump(java.io.FileDescriptor fd, java.io.PrintWriter pw, java.lang.String[] args)
pw.println("VolumePanel state:");
pw.print(" mTag="); pw.println(mTag);
pw.print(" mRingIsSilent="); pw.println(mRingIsSilent);
pw.print(" mVoiceCapable="); pw.println(mVoiceCapable);
pw.print(" mHasVibrator="); pw.println(mHasVibrator);
pw.print(" mZenModeAvailable="); pw.println(mZenModeAvailable);
pw.print(" mZenPanelExpanded="); pw.println(mZenPanelExpanded);
pw.print(" mNotificationEffectsSuppressor="); pw.println(mNotificationEffectsSuppressor);
pw.print(" mTimeoutDelay="); pw.println(mTimeoutDelay);
pw.print(" mDisabledAlpha="); pw.println(mDisabledAlpha);
pw.print(" mLastRingerMode="); pw.println(mLastRingerMode);
pw.print(" mLastRingerProgress="); pw.println(mLastRingerProgress);
pw.print(" mPlayMasterStreamTones="); pw.println(mPlayMasterStreamTones);
pw.print(" isShowing()="); pw.println(isShowing());
pw.print(" mCallback="); pw.println(mCallback);
pw.print(" sConfirmSafeVolumeDialog=");
pw.println(sSafetyWarning != null ? "<not null>" : null);
pw.print(" mActiveStreamType="); pw.println(mActiveStreamType);
pw.print(" mStreamControls=");
if (mStreamControls == null) {
pw.println("null");
} else {
final int N = mStreamControls.size();
pw.print("<size "); pw.print(N); pw.println('>");
for (int i = 0; i < N; i++) {
final StreamControl sc = mStreamControls.valueAt(i);
pw.print(" stream "); pw.print(sc.streamType); pw.print(":");
if (sc.seekbarView != null) {
pw.print(" progress="); pw.print(sc.seekbarView.getProgress());
pw.print(" of "); pw.print(sc.seekbarView.getMax());
if (!sc.seekbarView.isEnabled()) pw.print(" (disabled)");
}
if (sc.icon != null && sc.icon.isClickable()) pw.print(" (clickable)");
pw.println();
}
}
if (mZenPanel != null) {
mZenPanel.dump(fd, pw, args);
}
|
private static java.lang.String | flagsToString(int flags)
return flags == 0 ? "0" : (flags + "=" + AudioManager.flagsToString(flags));
|
private void | forceTimeout(long delay)
if (LOGD) Log.d(mTag, "forceTimeout delay=" + delay + " callers=" + Debug.getCallers(3));
removeMessages(MSG_TIMEOUT);
sendEmptyMessageDelayed(MSG_TIMEOUT, delay);
|
private android.media.ToneGenerator | getOrCreateToneGenerator(int streamType)Lock on this VolumePanel instance as long as you use the returned ToneGenerator.
if (streamType == STREAM_MASTER) {
// For devices that use the master volume setting only but still want to
// play a volume-changed tone, direct the master volume pseudostream to
// the system stream's tone generator.
if (mPlayMasterStreamTones) {
streamType = AudioManager.STREAM_SYSTEM;
} else {
return null;
}
}
synchronized (this) {
if (mToneGenerators[streamType] == null) {
try {
mToneGenerators[streamType] = new ToneGenerator(streamType, MAX_VOLUME);
} catch (RuntimeException e) {
if (LOGD) {
Log.d(mTag, "ToneGenerator constructor failed with "
+ "RuntimeException: " + e);
}
}
}
return mToneGenerators[streamType];
}
|
private int | getStreamMaxVolume(int streamType)
if (streamType == STREAM_MASTER) {
return mAudioManager.getMasterMaxVolume();
} else if (streamType == STREAM_REMOTE_MUSIC) {
if (mStreamControls != null) {
StreamControl sc = mStreamControls.get(streamType);
if (sc != null && sc.controller != null) {
PlaybackInfo ai = sc.controller.getPlaybackInfo();
return ai.getMaxVolume();
}
}
return -1;
} else {
return mAudioManager.getStreamMaxVolume(streamType);
}
|
private int | getStreamVolume(int streamType)
if (streamType == STREAM_MASTER) {
return mAudioManager.getMasterVolume();
} else if (streamType == STREAM_REMOTE_MUSIC) {
if (mStreamControls != null) {
StreamControl sc = mStreamControls.get(streamType);
if (sc != null && sc.controller != null) {
PlaybackInfo ai = sc.controller.getPlaybackInfo();
return ai.getCurrentVolume();
}
}
return -1;
} else {
return mAudioManager.getStreamVolume(streamType);
}
|
private java.lang.String | getSuppressorCaption(android.content.ComponentName suppressor)
final PackageManager pm = mContext.getPackageManager();
try {
final ServiceInfo info = pm.getServiceInfo(suppressor, 0);
if (info != null) {
final CharSequence seq = info.loadLabel(pm);
if (seq != null) {
final String str = seq.toString().trim();
if (str.length() > 0) {
return str;
}
}
}
} catch (Throwable e) {
Log.w(TAG, "Error loading suppressor caption", e);
}
return suppressor.getPackageName();
|
public com.android.systemui.statusbar.policy.ZenModeController | getZenController()
return mZenController;
|
public void | handleMessage(android.os.Message msg)
switch (msg.what) {
case MSG_VOLUME_CHANGED: {
onVolumeChanged(msg.arg1, msg.arg2);
break;
}
case MSG_MUTE_CHANGED: {
onMuteChanged(msg.arg1, msg.arg2);
break;
}
case MSG_FREE_RESOURCES: {
onFreeResources();
break;
}
case MSG_STOP_SOUNDS: {
onStopSounds();
break;
}
case MSG_PLAY_SOUND: {
onPlaySound(msg.arg1, msg.arg2);
break;
}
case MSG_VIBRATE: {
onVibrate();
break;
}
case MSG_TIMEOUT: {
if (isShowing()) {
mDialog.dismiss();
clearRemoteStreamController();
mActiveStreamType = -1;
if (mCallback != null) {
mCallback.onVisible(false);
}
}
synchronized (sSafetyWarningLock) {
if (sSafetyWarning != null) {
if (LOGD) Log.d(mTag, "SafetyWarning timeout");
sSafetyWarning.dismiss();
}
}
break;
}
case MSG_RINGER_MODE_CHANGED:
case MSG_INTERNAL_RINGER_MODE_CHANGED:
case MSG_NOTIFICATION_EFFECTS_SUPPRESSOR_CHANGED: {
if (isShowing()) {
updateActiveSlider();
}
break;
}
case MSG_REMOTE_VOLUME_CHANGED: {
onRemoteVolumeChanged((MediaController) msg.obj, msg.arg1);
break;
}
case MSG_REMOTE_VOLUME_UPDATE_IF_SHOWN:
onRemoteVolumeUpdateIfShown();
break;
case MSG_SLIDER_VISIBILITY_CHANGED:
onSliderVisibilityChanged(msg.arg1, msg.arg2);
break;
case MSG_DISPLAY_SAFE_VOLUME_WARNING:
onDisplaySafeVolumeWarning(msg.arg1);
break;
case MSG_LAYOUT_DIRECTION:
setLayoutDirection(msg.arg1);
break;
case MSG_ZEN_MODE_AVAILABLE_CHANGED:
mZenModeAvailable = msg.arg1 != 0;
updateZenPanelVisible();
break;
case MSG_USER_ACTIVITY:
if (mCallback != null) {
mCallback.onInteraction();
}
break;
}
|
private void | initZenModePanel()
mZenPanel.init(mZenController);
mZenPanel.setCallback(new ZenModePanel.Callback() {
@Override
public void onMoreSettings() {
if (mCallback != null) {
mCallback.onZenSettings();
}
}
@Override
public void onInteraction() {
resetTimeout();
}
@Override
public void onExpanded(boolean expanded) {
if (mZenPanelExpanded == expanded) return;
mZenPanelExpanded = expanded;
updateTimeoutDelay();
resetTimeout();
}
});
|
private boolean | isMuted(int streamType)
if (streamType == STREAM_MASTER) {
return mAudioManager.isMasterMute();
} else if (streamType == STREAM_REMOTE_MUSIC) {
// TODO do we need to support a distinct mute property for remote?
return false;
} else {
return mAudioManager.isStreamMute(streamType);
}
|
private static boolean | isNotificationOrRing(int streamType)
return streamType == AudioManager.STREAM_RING
|| streamType == AudioManager.STREAM_NOTIFICATION;
|
private boolean | isShowing()
return mDialog.isShowing();
|
private boolean | isZenPanelVisible()
return mZenPanel != null && mZenPanel.getVisibility() == View.VISIBLE;
|
public void | onConfigurationChanged(android.content.res.Configuration newConfig)
updateWidth();
if (mZenPanel != null) {
mZenPanel.updateLocale();
}
|
protected void | onDisplaySafeVolumeWarning(int flags)
if ((flags & (AudioManager.FLAG_SHOW_UI | AudioManager.FLAG_SHOW_UI_WARNINGS)) != 0
|| isShowing()) {
synchronized (sSafetyWarningLock) {
if (sSafetyWarning != null) {
return;
}
sSafetyWarning = new SafetyWarning(mContext, this, mAudioManager);
sSafetyWarning.show();
}
updateStates();
}
if (mAccessibilityManager.isTouchExplorationEnabled()) {
removeMessages(MSG_TIMEOUT);
} else {
updateTimeoutDelay();
resetTimeout();
}
|
protected void | onFreeResources()
synchronized (this) {
for (int i = mToneGenerators.length - 1; i >= 0; i--) {
if (mToneGenerators[i] != null) {
mToneGenerators[i].release();
}
mToneGenerators[i] = null;
}
}
|
protected void | onMuteChanged(int streamType, int flags)
if (LOGD) Log.d(mTag, "onMuteChanged(streamType: " + streamToString(streamType)
+ ", flags: " + flagsToString(flags) + ")");
StreamControl sc = mStreamControls.get(streamType);
if (sc != null) {
updateSliderIcon(sc, isMuted(sc.streamType));
}
onVolumeChanged(streamType, flags);
|
protected void | onPlaySound(int streamType, int flags)
if (hasMessages(MSG_STOP_SOUNDS)) {
removeMessages(MSG_STOP_SOUNDS);
// Force stop right now
onStopSounds();
}
synchronized (this) {
ToneGenerator toneGen = getOrCreateToneGenerator(streamType);
if (toneGen != null) {
toneGen.startTone(ToneGenerator.TONE_PROP_BEEP);
sendMessageDelayed(obtainMessage(MSG_STOP_SOUNDS), BEEP_DURATION);
}
}
|
protected void | onRemoteVolumeChanged(android.media.session.MediaController controller, int flags)
if (LOGD) Log.d(mTag, "onRemoteVolumeChanged(controller:" + controller + ", flags: "
+ flagsToString(flags) + ")");
if (((flags & AudioManager.FLAG_SHOW_UI) != 0) || isShowing()) {
synchronized (this) {
if (mActiveStreamType != STREAM_REMOTE_MUSIC) {
reorderSliders(STREAM_REMOTE_MUSIC);
}
onShowVolumeChanged(STREAM_REMOTE_MUSIC, flags, controller);
}
} else {
if (LOGD) Log.d(mTag, "not calling onShowVolumeChanged(), no FLAG_SHOW_UI or no UI");
}
removeMessages(MSG_FREE_RESOURCES);
sendMessageDelayed(obtainMessage(MSG_FREE_RESOURCES), FREE_DELAY);
resetTimeout();
|
protected void | onRemoteVolumeUpdateIfShown()
if (LOGD) Log.d(mTag, "onRemoteVolumeUpdateIfShown()");
if (isShowing()
&& (mActiveStreamType == STREAM_REMOTE_MUSIC)
&& (mStreamControls != null)) {
onShowVolumeChanged(STREAM_REMOTE_MUSIC, 0, null);
}
|
protected void | onShowVolumeChanged(int streamType, int flags, android.media.session.MediaController controller)
int index = getStreamVolume(streamType);
mRingIsSilent = false;
if (LOGD) {
Log.d(mTag, "onShowVolumeChanged(streamType: " + streamToString(streamType)
+ ", flags: " + flagsToString(flags) + "), index: " + index);
}
// get max volume for progress bar
int max = getStreamMaxVolume(streamType);
StreamControl sc = mStreamControls.get(streamType);
switch (streamType) {
case AudioManager.STREAM_RING: {
Uri ringuri = RingtoneManager.getActualDefaultRingtoneUri(
mContext, RingtoneManager.TYPE_RINGTONE);
if (ringuri == null) {
mRingIsSilent = true;
}
break;
}
case AudioManager.STREAM_MUSIC: {
// Special case for when Bluetooth is active for music
if ((mAudioManager.getDevicesForStream(AudioManager.STREAM_MUSIC) &
(AudioManager.DEVICE_OUT_BLUETOOTH_A2DP |
AudioManager.DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES |
AudioManager.DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER)) != 0) {
setMusicIcon(IC_AUDIO_BT, IC_AUDIO_BT_MUTE);
} else {
setMusicIcon(IC_AUDIO_VOL, IC_AUDIO_VOL_MUTE);
}
break;
}
case AudioManager.STREAM_VOICE_CALL: {
/*
* For in-call voice call volume, there is no inaudible volume.
* Rescale the UI control so the progress bar doesn't go all
* the way to zero and don't show the mute icon.
*/
index++;
max++;
break;
}
case AudioManager.STREAM_ALARM: {
break;
}
case AudioManager.STREAM_NOTIFICATION: {
Uri ringuri = RingtoneManager.getActualDefaultRingtoneUri(
mContext, RingtoneManager.TYPE_NOTIFICATION);
if (ringuri == null) {
mRingIsSilent = true;
}
break;
}
case AudioManager.STREAM_BLUETOOTH_SCO: {
/*
* For in-call voice call volume, there is no inaudible volume.
* Rescale the UI control so the progress bar doesn't go all
* the way to zero and don't show the mute icon.
*/
index++;
max++;
break;
}
case STREAM_REMOTE_MUSIC: {
if (controller == null && sc != null) {
// If we weren't passed one try using the last one set.
controller = sc.controller;
}
if (controller == null) {
// We still don't have one, ignore the command.
Log.w(mTag, "sent remote volume change without a controller!");
} else {
PlaybackInfo vi = controller.getPlaybackInfo();
index = vi.getCurrentVolume();
max = vi.getMaxVolume();
if ((vi.getVolumeControl() & VolumeProvider.VOLUME_CONTROL_FIXED) != 0) {
// if the remote volume is fixed add the flag for the UI
flags |= AudioManager.FLAG_FIXED_VOLUME;
}
}
if (LOGD) { Log.d(mTag, "showing remote volume "+index+" over "+ max); }
break;
}
}
if (sc != null) {
if (streamType == STREAM_REMOTE_MUSIC && controller != sc.controller) {
if (sc.controller != null) {
sc.controller.unregisterCallback(mMediaControllerCb);
}
sc.controller = controller;
if (controller != null) {
sc.controller.registerCallback(mMediaControllerCb);
}
}
if (sc.seekbarView.getMax() != max) {
sc.seekbarView.setMax(max);
}
updateSliderProgress(sc, index);
final boolean muted = isMuted(streamType);
updateSliderEnabled(sc, muted, (flags & AudioManager.FLAG_FIXED_VOLUME) != 0);
if (isNotificationOrRing(streamType)) {
// check for secondary-icon transition completion
if (mSecondaryIconTransition.isRunning()) {
mSecondaryIconTransition.cancel(); // safe to reset
sc.seekbarView.setAlpha(0); sc.seekbarView.animate().alpha(1);
mZenPanel.setAlpha(0); mZenPanel.animate().alpha(1);
}
updateSliderIcon(sc, muted);
}
}
if (!isShowing()) {
int stream = (streamType == STREAM_REMOTE_MUSIC) ? -1 : streamType;
// when the stream is for remote playback, use -1 to reset the stream type evaluation
if (stream != STREAM_MASTER) {
mAudioManager.forceVolumeControlStream(stream);
}
mDialog.show();
if (mCallback != null) {
mCallback.onVisible(true);
}
announceDialogShown();
}
// Do a little vibrate if applicable (only when going into vibrate mode)
if ((streamType != STREAM_REMOTE_MUSIC) &&
((flags & AudioManager.FLAG_VIBRATE) != 0) &&
isNotificationOrRing(streamType) &&
mAudioManager.getRingerModeInternal() == AudioManager.RINGER_MODE_VIBRATE) {
sendMessageDelayed(obtainMessage(MSG_VIBRATE), VIBRATE_DELAY);
}
// Pulse the zen icon if an adjustment was suppressed due to silent mode.
if ((flags & AudioManager.FLAG_SHOW_SILENT_HINT) != 0) {
showSilentHint();
}
// Pulse the slider icon & vibrate if an adjustment down was suppressed due to vibrate mode.
if ((flags & AudioManager.FLAG_SHOW_VIBRATE_HINT) != 0) {
showVibrateHint();
}
|
protected synchronized void | onSliderVisibilityChanged(int streamType, int visible)Handler for MSG_SLIDER_VISIBILITY_CHANGED Hide or show a slider
if (LOGD) Log.d(mTag, "onSliderVisibilityChanged(stream="+streamType+", visi="+visible+")");
boolean isVisible = (visible == 1);
for (int i = STREAMS.length - 1 ; i >= 0 ; i--) {
StreamResources streamRes = STREAMS[i];
if (streamRes.streamType == streamType) {
streamRes.show = isVisible;
if (!isVisible && (mActiveStreamType == streamType)) {
mActiveStreamType = -1;
}
break;
}
}
|
protected void | onStopSounds()
synchronized (this) {
int numStreamTypes = AudioSystem.getNumStreamTypes();
for (int i = numStreamTypes - 1; i >= 0; i--) {
ToneGenerator toneGen = mToneGenerators[i];
if (toneGen != null) {
toneGen.stopTone();
}
}
}
|
protected void | onVibrate()
// Make sure we ended up in vibrate ringer mode
if (mAudioManager.getRingerModeInternal() != AudioManager.RINGER_MODE_VIBRATE) {
return;
}
if (mVibrator != null) {
mVibrator.vibrate(VIBRATE_DURATION, VIBRATION_ATTRIBUTES);
}
|
protected void | onVolumeChanged(int streamType, int flags)Override this if you have other work to do when the volume changes (for
example, vibrating, playing a sound, etc.). Make sure to call through to
the superclass implementation.
if (LOGD) Log.d(mTag, "onVolumeChanged(streamType: " + streamToString(streamType)
+ ", flags: " + flagsToString(flags) + ")");
if ((flags & AudioManager.FLAG_SHOW_UI) != 0) {
synchronized (this) {
if (mActiveStreamType != streamType) {
reorderSliders(streamType);
}
onShowVolumeChanged(streamType, flags, null);
}
}
if ((flags & AudioManager.FLAG_PLAY_SOUND) != 0 && ! mRingIsSilent) {
removeMessages(MSG_PLAY_SOUND);
sendMessageDelayed(obtainMessage(MSG_PLAY_SOUND, streamType, flags), PLAY_SOUND_DELAY);
}
if ((flags & AudioManager.FLAG_REMOVE_SOUND_AND_VIBRATE) != 0) {
removeMessages(MSG_PLAY_SOUND);
removeMessages(MSG_VIBRATE);
onStopSounds();
}
removeMessages(MSG_FREE_RESOURCES);
sendMessageDelayed(obtainMessage(MSG_FREE_RESOURCES), FREE_DELAY);
resetTimeout();
|
public void | postDismiss(long delay)
forceTimeout(delay);
|
public void | postDisplaySafeVolumeWarning(int flags)
if (hasMessages(MSG_DISPLAY_SAFE_VOLUME_WARNING)) return;
obtainMessage(MSG_DISPLAY_SAFE_VOLUME_WARNING, flags, 0).sendToTarget();
|
public void | postHasNewRemotePlaybackInfo()Called by AudioService when it has received new remote playback information that
would affect the VolumePanel display (mainly volumes). The difference with
{@link #postRemoteVolumeChanged(int, int)} is that the handling of the posted message
(MSG_REMOTE_VOLUME_UPDATE_IF_SHOWN) will only update the volume slider if it is being
displayed.
This special code path is due to the fact that remote volume updates arrive to AudioService
asynchronously. So after AudioService has sent the volume update (which should be treated
as a request to update the volume), the application will likely set a new volume. If the UI
is still up, we need to refresh the display to show this new value.
if (hasMessages(MSG_REMOTE_VOLUME_UPDATE_IF_SHOWN)) return;
// don't create or prevent resources to be freed, if they disappear, this update came too
// late and shouldn't warrant the panel to be displayed longer
obtainMessage(MSG_REMOTE_VOLUME_UPDATE_IF_SHOWN).sendToTarget();
|
public void | postLayoutDirection(int layoutDirection)
removeMessages(MSG_LAYOUT_DIRECTION);
obtainMessage(MSG_LAYOUT_DIRECTION, layoutDirection, 0).sendToTarget();
|
public void | postMasterMuteChanged(int flags)
postMuteChanged(STREAM_MASTER, flags);
|
public void | postMasterVolumeChanged(int flags)
postVolumeChanged(STREAM_MASTER, flags);
|
public void | postMuteChanged(int streamType, int flags)
if (hasMessages(MSG_VOLUME_CHANGED)) return;
synchronized (this) {
if (mStreamControls == null) {
createSliders();
}
}
removeMessages(MSG_FREE_RESOURCES);
obtainMessage(MSG_MUTE_CHANGED, streamType, flags).sendToTarget();
|
public void | postRemoteSliderVisibility(boolean visible)
obtainMessage(MSG_SLIDER_VISIBILITY_CHANGED,
STREAM_REMOTE_MUSIC, visible ? 1 : 0).sendToTarget();
|
public void | postRemoteVolumeChanged(android.media.session.MediaController controller, int flags)
if (hasMessages(MSG_REMOTE_VOLUME_CHANGED)) return;
synchronized (this) {
if (mStreamControls == null) {
createSliders();
}
}
removeMessages(MSG_FREE_RESOURCES);
obtainMessage(MSG_REMOTE_VOLUME_CHANGED, flags, 0, controller).sendToTarget();
|
public void | postVolumeChanged(int streamType, int flags)
if (hasMessages(MSG_VOLUME_CHANGED)) return;
synchronized (this) {
if (mStreamControls == null) {
createSliders();
}
}
removeMessages(MSG_FREE_RESOURCES);
obtainMessage(MSG_VOLUME_CHANGED, streamType, flags).sendToTarget();
|
private void | registerReceiver()
final IntentFilter filter = new IntentFilter();
filter.addAction(AudioManager.RINGER_MODE_CHANGED_ACTION);
filter.addAction(AudioManager.INTERNAL_RINGER_MODE_CHANGED_ACTION);
filter.addAction(Intent.ACTION_SCREEN_OFF);
mContext.registerReceiver(new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
final String action = intent.getAction();
if (AudioManager.RINGER_MODE_CHANGED_ACTION.equals(action)) {
removeMessages(MSG_RINGER_MODE_CHANGED);
sendEmptyMessage(MSG_RINGER_MODE_CHANGED);
}
if (AudioManager.INTERNAL_RINGER_MODE_CHANGED_ACTION.equals(action)) {
removeMessages(MSG_INTERNAL_RINGER_MODE_CHANGED);
sendEmptyMessage(MSG_INTERNAL_RINGER_MODE_CHANGED);
}
if (Intent.ACTION_SCREEN_OFF.equals(action)) {
postDismiss(0);
}
}
}, filter);
|
private void | reorderSliders(int activeStreamType)
mSliderPanel.removeAllViews();
final StreamControl active = mStreamControls.get(activeStreamType);
if (active == null) {
Log.e(TAG, "Missing stream type! - " + activeStreamType);
mActiveStreamType = -1;
} else {
mSliderPanel.addView(active.group);
mActiveStreamType = activeStreamType;
active.group.setVisibility(View.VISIBLE);
updateSlider(active, true /*forceReloadIcon*/);
updateTimeoutDelay();
updateZenPanelVisible();
}
|
private void | resetTimeout()
final boolean touchExploration = mAccessibilityManager.isTouchExplorationEnabled();
if (LOGD) Log.d(mTag, "resetTimeout at " + System.currentTimeMillis()
+ " delay=" + mTimeoutDelay + " touchExploration=" + touchExploration);
if (sSafetyWarning == null || !touchExploration) {
removeMessages(MSG_TIMEOUT);
sendEmptyMessageDelayed(MSG_TIMEOUT, mTimeoutDelay);
removeMessages(MSG_USER_ACTIVITY);
sendEmptyMessage(MSG_USER_ACTIVITY);
}
|
public void | setCallback(com.android.systemui.volume.VolumePanel$Callback callback)
mCallback = callback;
|
private void | setLayoutDirection(int layoutDirection)
mPanel.setLayoutDirection(layoutDirection);
updateStates();
|
private void | setMusicIcon(int resId, int resMuteId)Switch between icons because Bluetooth music is same as music volume, but with
different icons.
StreamControl sc = mStreamControls.get(AudioManager.STREAM_MUSIC);
if (sc != null) {
sc.iconRes = resId;
sc.iconMuteRes = resMuteId;
updateSliderIcon(sc, isMuted(sc.streamType));
}
|
private void | setStreamVolume(com.android.systemui.volume.VolumePanel$StreamControl sc, int index, int flags)
if (sc.streamType == STREAM_REMOTE_MUSIC) {
if (sc.controller != null) {
sc.controller.setVolumeTo(index, flags);
} else {
Log.w(mTag, "Adjusting remote volume without a controller!");
}
} else if (getStreamVolume(sc.streamType) != index) {
if (sc.streamType == STREAM_MASTER) {
mAudioManager.setMasterVolume(index, flags);
} else {
mAudioManager.setStreamVolume(sc.streamType, index, flags);
}
}
|
private void | setZenPanelVisible(boolean visible)
if (LOGD) Log.d(mTag, "setZenPanelVisible " + visible + " mZenPanel=" + mZenPanel);
final boolean changing = visible != isZenPanelVisible();
if (visible) {
mZenPanel.setHidden(false);
resetTimeout();
} else {
mZenPanel.setHidden(true);
}
if (changing) {
updateTimeoutDelay();
resetTimeout();
}
|
private void | showSilentHint()
if (mZenPanel != null) {
mZenPanel.showSilentHint();
}
|
private void | showVibrateHint()
final StreamControl active = mStreamControls.get(mActiveStreamType);
if (active != null) {
mIconPulser.start(active.icon);
if (!hasMessages(MSG_VIBRATE)) {
sendEmptyMessageDelayed(MSG_VIBRATE, VIBRATE_DELAY);
}
}
|
private static java.lang.String | streamToString(int stream)
return AudioService.streamToString(stream);
|
private void | toggleRinger(com.android.systemui.volume.VolumePanel$StreamControl sc)
if (!mHasVibrator) return;
if (mAudioManager.getRingerModeInternal() == AudioManager.RINGER_MODE_NORMAL) {
mAudioManager.setRingerModeInternal(AudioManager.RINGER_MODE_VIBRATE);
postVolumeChanged(sc.streamType, AudioManager.FLAG_SHOW_UI | AudioManager.FLAG_VIBRATE);
} else {
mAudioManager.setRingerModeInternal(AudioManager.RINGER_MODE_NORMAL);
postVolumeChanged(sc.streamType, AudioManager.FLAG_PLAY_SOUND);
}
|
private void | updateActiveSlider()
final StreamControl active = mStreamControls.get(mActiveStreamType);
if (active != null) {
updateSlider(active, false /*forceReloadIcon*/);
}
|
private void | updateSlider(com.android.systemui.volume.VolumePanel$StreamControl sc, boolean forceReloadIcon)Update the mute and progress state of a slider
updateSliderProgress(sc, -1);
final boolean muted = isMuted(sc.streamType);
if (forceReloadIcon) {
sc.icon.setImageDrawable(null);
}
updateSliderIcon(sc, muted);
updateSliderEnabled(sc, muted, false);
updateSliderSuppressor(sc);
|
private void | updateSliderEnabled(com.android.systemui.volume.VolumePanel$StreamControl sc, boolean muted, boolean fixedVolume)
final boolean wasEnabled = sc.seekbarView.isEnabled();
final boolean isRinger = isNotificationOrRing(sc.streamType);
if (sc.streamType == STREAM_REMOTE_MUSIC) {
// never disable touch interactions for remote playback, the muting is not tied to
// the state of the phone.
sc.seekbarView.setEnabled(!fixedVolume);
} else if (isRinger && mNotificationEffectsSuppressor != null) {
sc.icon.setEnabled(true);
sc.icon.setAlpha(1f);
sc.icon.setClickable(false);
} else if (isRinger
&& mAudioManager.getRingerModeInternal() == AudioManager.RINGER_MODE_SILENT) {
sc.seekbarView.setEnabled(false);
sc.icon.setEnabled(false);
sc.icon.setAlpha(mDisabledAlpha);
sc.icon.setClickable(false);
} else if (fixedVolume ||
(sc.streamType != mAudioManager.getMasterStreamType() && !isRinger && muted) ||
(sSafetyWarning != null)) {
sc.seekbarView.setEnabled(false);
} else {
sc.seekbarView.setEnabled(true);
sc.icon.setEnabled(true);
sc.icon.setAlpha(1f);
}
// show the silent hint when the disabled slider is touched in silent mode
if (isRinger && wasEnabled != sc.seekbarView.isEnabled()) {
if (sc.seekbarView.isEnabled()) {
sc.group.setOnTouchListener(null);
sc.icon.setClickable(mHasVibrator);
} else {
final View.OnTouchListener showHintOnTouch = new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
resetTimeout();
showSilentHint();
return false;
}
};
sc.group.setOnTouchListener(showHintOnTouch);
}
}
|
private void | updateSliderIcon(com.android.systemui.volume.VolumePanel$StreamControl sc, boolean muted)
ComponentName suppressor = null;
if (isNotificationOrRing(sc.streamType)) {
suppressor = mNotificationEffectsSuppressor;
int ringerMode = mAudioManager.getRingerModeInternal();
if (ringerMode == AudioManager.RINGER_MODE_SILENT) {
ringerMode = mLastRingerMode;
} else {
mLastRingerMode = ringerMode;
}
if (mHasVibrator) {
muted = ringerMode == AudioManager.RINGER_MODE_VIBRATE;
} else {
muted = false;
}
}
sc.icon.setImageResource(mDemoIcon != 0 ? mDemoIcon
: suppressor != null ? sc.iconSuppressedRes
: muted ? sc.iconMuteRes
: sc.iconRes);
|
private void | updateSliderProgress(com.android.systemui.volume.VolumePanel$StreamControl sc, int progress)
final boolean isRinger = isNotificationOrRing(sc.streamType);
if (isRinger && mAudioManager.getRingerModeInternal() == AudioManager.RINGER_MODE_SILENT) {
progress = mLastRingerProgress;
}
if (progress < 0) {
progress = getStreamVolume(sc.streamType);
}
sc.seekbarView.setProgress(progress);
if (isRinger) {
mLastRingerProgress = progress;
}
|
private void | updateSliderSuppressor(com.android.systemui.volume.VolumePanel$StreamControl sc)
final ComponentName suppressor = isNotificationOrRing(sc.streamType)
? mNotificationEffectsSuppressor : null;
if (suppressor == null) {
sc.seekbarView.setVisibility(View.VISIBLE);
sc.suppressorView.setVisibility(View.GONE);
} else {
sc.seekbarView.setVisibility(View.GONE);
sc.suppressorView.setVisibility(View.VISIBLE);
sc.suppressorView.setText(mContext.getString(R.string.muted_by,
getSuppressorCaption(suppressor)));
}
|
private void | updateStates()
final int count = mSliderPanel.getChildCount();
for (int i = 0; i < count; i++) {
StreamControl sc = (StreamControl) mSliderPanel.getChildAt(i).getTag();
updateSlider(sc, true /*forceReloadIcon*/);
}
|
private void | updateTimeoutDelay()
mTimeoutDelay = mDemoIcon != 0 ? TIMEOUT_DELAY_EXPANDED
: sSafetyWarning != null ? TIMEOUT_DELAY_SAFETY_WARNING
: mActiveStreamType == AudioManager.STREAM_MUSIC ? TIMEOUT_DELAY_SHORT
: mZenPanelExpanded ? TIMEOUT_DELAY_EXPANDED
: isZenPanelVisible() ? TIMEOUT_DELAY_COLLAPSED
: TIMEOUT_DELAY;
|
private void | updateWidth()
final Resources res = mContext.getResources();
final LayoutParams lp = mDialog.getWindow().getAttributes();
lp.width = res.getDimensionPixelSize(com.android.systemui.R.dimen.notification_panel_width);
lp.gravity =
res.getInteger(com.android.systemui.R.integer.notification_panel_layout_gravity);
mDialog.getWindow().setAttributes(lp);
|
private void | updateZenPanelVisible()
setZenPanelVisible(mZenModeAvailable && isNotificationOrRing(mActiveStreamType));
|