summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Amith Yamasani <yamasani@google.com> 2011-02-02 18:54:13 -0800
committer Amith Yamasani <yamasani@google.com> 2011-02-03 15:49:12 -0800
commit2bbdd77ab20788e901a410f299edef028b66bb6e (patch)
tree13ae7c318511c333f97ee8ae03981e00d46ed165
parentcc84ea17680e566f79fdfc1f3c1d7169c37dd1c2 (diff)
Expanded volume panel with sliders and mute buttons.
Bug: 3395734 Volume panel that can be expanded and can be used to control different streams' volume and toggle silent mode. Shows the active stream's slider on top and the remaining below. Touching outside dismisses the dialog as well as a 3 second timeout. Dialog fades out after timeout. Change-Id: Ief258cc904bfd3d62f1291adba4a9cf442bcb006
-rw-r--r--core/java/android/view/VolumePanel.java504
-rw-r--r--core/res/res/drawable-hdpi/ic_sysbar_quicksettings.pngbin0 -> 773 bytes
-rw-r--r--core/res/res/drawable-mdpi/ic_sysbar_quicksettings.pngbin0 -> 653 bytes
-rw-r--r--core/res/res/layout/volume_adjust.xml68
-rw-r--r--core/res/res/layout/volume_adjust_item.xml45
-rw-r--r--core/res/res/values/styles.xml5
-rw-r--r--core/res/res/values/themes.xml5
7 files changed, 478 insertions, 149 deletions
diff --git a/core/java/android/view/VolumePanel.java b/core/java/android/view/VolumePanel.java
index e447dbb8a5f2..bb5774f31417 100644
--- a/core/java/android/view/VolumePanel.java
+++ b/core/java/android/view/VolumePanel.java
@@ -16,10 +16,17 @@
package android.view;
-import android.bluetooth.HeadsetBase;
+import com.android.internal.R;
+
+import android.app.Dialog;
+import android.content.DialogInterface.OnDismissListener;
+import android.content.BroadcastReceiver;
import android.content.Context;
+import android.content.DialogInterface;
import android.content.Intent;
+import android.content.IntentFilter;
import android.content.res.Resources;
+import android.graphics.drawable.Drawable;
import android.media.AudioManager;
import android.media.AudioService;
import android.media.AudioSystem;
@@ -29,12 +36,16 @@ import android.net.Uri;
import android.os.Handler;
import android.os.Message;
import android.os.Vibrator;
-import android.util.Config;
+import android.telephony.TelephonyManager;
import android.util.Log;
import android.widget.ImageView;
import android.widget.ProgressBar;
+import android.widget.SeekBar;
import android.widget.TextView;
import android.widget.Toast;
+import android.widget.SeekBar.OnSeekBarChangeListener;
+
+import java.util.HashMap;
/**
* Handle the volume up and down keys.
@@ -43,7 +54,7 @@ import android.widget.Toast;
*
* @hide
*/
-public class VolumePanel extends Handler
+public class VolumePanel extends Handler implements OnSeekBarChangeListener, View.OnClickListener
{
private static final String TAG = "VolumePanel";
private static boolean LOGD = false;
@@ -68,62 +79,255 @@ public class VolumePanel extends Handler
private static final int BEEP_DURATION = 150;
private static final int MAX_VOLUME = 100;
private static final int FREE_DELAY = 10000;
+ private static final int TIMEOUT_DELAY = 3000;
private static final int MSG_VOLUME_CHANGED = 0;
private static final int MSG_FREE_RESOURCES = 1;
private static final int MSG_PLAY_SOUND = 2;
private static final int MSG_STOP_SOUNDS = 3;
private static final int MSG_VIBRATE = 4;
-
- private static final int RINGTONE_VOLUME_TEXT = com.android.internal.R.string.volume_ringtone;
- private static final int MUSIC_VOLUME_TEXT = com.android.internal.R.string.volume_music;
- private static final int INCALL_VOLUME_TEXT = com.android.internal.R.string.volume_call;
- private static final int ALARM_VOLUME_TEXT = com.android.internal.R.string.volume_alarm;
- private static final int UNKNOWN_VOLUME_TEXT = com.android.internal.R.string.volume_unknown;
- private static final int NOTIFICATION_VOLUME_TEXT =
- com.android.internal.R.string.volume_notification;
- private static final int BLUETOOTH_INCALL_VOLUME_TEXT =
- com.android.internal.R.string.volume_bluetooth_call;
+ private static final int MSG_TIMEOUT = 5;
+ private static final int MSG_RINGER_MODE_CHANGED = 6;
+
+// private static final int RINGTONE_VOLUME_TEXT = com.android.internal.R.string.volume_ringtone;
+// private static final int MUSIC_VOLUME_TEXT = com.android.internal.R.string.volume_music;
+// private static final int INCALL_VOLUME_TEXT = com.android.internal.R.string.volume_call;
+// private static final int ALARM_VOLUME_TEXT = com.android.internal.R.string.volume_alarm;
+// private static final int UNKNOWN_VOLUME_TEXT = com.android.internal.R.string.volume_unknown;
+// private static final int NOTIFICATION_VOLUME_TEXT =
+// com.android.internal.R.string.volume_notification;
+// private static final int BLUETOOTH_INCALL_VOLUME_TEXT =
+// com.android.internal.R.string.volume_bluetooth_call;
protected Context mContext;
private AudioManager mAudioManager;
protected AudioService mAudioService;
private boolean mRingIsSilent;
- private final Toast mToast;
+ /** Dialog containing all the sliders */
+ private final Dialog mDialog;
+ /** Dialog's content view */
private final View mView;
- private final TextView mMessage;
- private final TextView mAdditionalMessage;
- private final ImageView mSmallStreamIcon;
- private final ImageView mLargeStreamIcon;
- private final ProgressBar mLevel;
+// private final TextView mMessage;
+// private final TextView mAdditionalMessage;
+// private final ImageView mSmallStreamIcon;
+// private final ImageView mLargeStreamIcon;
+// private final ProgressBar mLevel;
+
+ /** Contains the sliders and their touchable icons */
+ private final ViewGroup mSliderGroup;
+ /** The button that expands the dialog to show all sliders */
+ private final View mMoreButton;
+ /** Dummy divider icon that needs to vanish with the more button */
+ private final View mDivider;
+
+ /** Currently active stream that shows up at the top of the list of sliders */
+ private int mActiveStreamType = -1;
+ /** All the slider controls mapped by stream type */
+ private HashMap<Integer,StreamControl> mStreamControls;
+
+ // List of stream types and their order
+ // RING and VOICE_CALL are hidden unless explicitly requested
+ private static final int [] STREAM_TYPES = {
+ AudioManager.STREAM_RING,
+ AudioManager.STREAM_VOICE_CALL,
+ AudioManager.STREAM_MUSIC,
+ AudioManager.STREAM_NOTIFICATION
+ };
+
+ // These icons need to correspond to the ones above.
+ private static final int [] STREAM_ICONS_NORMAL = {
+ R.drawable.ic_audio_phone,
+ R.drawable.ic_audio_phone,
+ R.drawable.ic_audio_vol,
+ R.drawable.ic_audio_notification,
+ };
+
+ // These icons need to correspond to the ones above.
+ private static final int [] STREAM_ICONS_MUTED = {
+ R.drawable.ic_audio_phone,
+ R.drawable.ic_audio_phone,
+ R.drawable.ic_audio_vol_mute,
+ R.drawable.ic_audio_notification_mute,
+ };
+
+ /** Object that contains data for each slider */
+ private class StreamControl {
+ int streamType;
+ ViewGroup group;
+ ImageView icon;
+ SeekBar seekbarView;
+ int iconRes;
+ int iconMuteRes;
+ }
// Synchronize when accessing this
private ToneGenerator mToneGenerators[];
private Vibrator mVibrator;
- public VolumePanel(Context context, AudioService volumeService) {
+ public VolumePanel(final Context context, AudioService volumeService) {
mContext = context;
mAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
mAudioService = volumeService;
- mToast = new Toast(context);
LayoutInflater inflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
- View view = mView = inflater.inflate(com.android.internal.R.layout.volume_adjust, null);
- mMessage = (TextView) view.findViewById(com.android.internal.R.id.message);
- mAdditionalMessage =
- (TextView) view.findViewById(com.android.internal.R.id.additional_message);
- mSmallStreamIcon = (ImageView) view.findViewById(com.android.internal.R.id.other_stream_icon);
- mLargeStreamIcon = (ImageView) view.findViewById(com.android.internal.R.id.ringer_stream_icon);
- mLevel = (ProgressBar) view.findViewById(com.android.internal.R.id.level);
+ View view = mView = inflater.inflate(R.layout.volume_adjust, null);
+ mView.setOnTouchListener(new View.OnTouchListener() {
+ public boolean onTouch(View v, MotionEvent event) {
+ resetTimeout();
+ return true;
+ }
+ });
+ mSliderGroup = (ViewGroup) mView.findViewById(R.id.slider_group);
+ mMoreButton = (ImageView) mView.findViewById(R.id.expand_button);
+ mMoreButton.setOnClickListener(this);
+ mDivider = (ImageView) mView.findViewById(R.id.expand_button_divider);
+
+ mDialog = new Dialog(context, R.style.Theme_Panel_Volume);
+ mDialog.setTitle("Volume control"); // No need to localize
+ mDialog.setContentView(mView);
+ mDialog.setOnDismissListener(new OnDismissListener() {
+ public void onDismiss(DialogInterface dialog) {
+ mActiveStreamType = -1;
+ }
+ });
+ // Change some window properties
+ Window window = mDialog.getWindow();
+ window.setGravity(Gravity.TOP);
+ WindowManager.LayoutParams lp = window.getAttributes();
+ lp.token = null;
+ lp.type = WindowManager.LayoutParams.TYPE_SYSTEM_ALERT;
+ window.setAttributes(lp);
+ window.addFlags(WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM);
+
+// mMessage = (TextView) view.findViewById(com.android.internal.R.id.message);
+// mAdditionalMessage =
+// (TextView) view.findViewById(com.android.internal.R.id.additional_message);
+// mSmallStreamIcon = (ImageView) view.findViewById(com.android.internal.R.id.other_stream_icon);
+// mLargeStreamIcon = (ImageView) view.findViewById(com.android.internal.R.id.ringer_stream_icon);
+// mLevel = (ProgressBar) view.findViewById(com.android.internal.R.id.level);
mToneGenerators = new ToneGenerator[AudioSystem.getNumStreamTypes()];
mVibrator = new Vibrator();
+
+ listenToRingerMode();
+ }
+
+ private void listenToRingerMode() {
+ final IntentFilter filter = new IntentFilter();
+ filter.addAction(AudioManager.RINGER_MODE_CHANGED_ACTION);
+ mContext.registerReceiver(new BroadcastReceiver() {
+
+ 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);
+ sendMessage(obtainMessage(MSG_RINGER_MODE_CHANGED));
+ }
+ }
+ }, filter);
+ }
+
+ private boolean isMuted(int streamType) {
+ return mAudioManager.isStreamMute(streamType);
+ }
+
+ private void createSliders() {
+ LayoutInflater inflater = (LayoutInflater) mContext
+ .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+ mStreamControls = new HashMap<Integer,StreamControl>(STREAM_TYPES.length);
+ for (int i = 0; i < STREAM_TYPES.length; i++) {
+ StreamControl sc = new StreamControl();
+ sc.streamType = STREAM_TYPES[i];
+ sc.group = (ViewGroup) inflater.inflate(R.layout.volume_adjust_item, null);
+ sc.group.setTag(sc);
+ sc.icon = (ImageView) sc.group.findViewById(R.id.stream_icon);
+ sc.icon.setOnClickListener(this);
+ sc.icon.setTag(sc);
+ sc.iconRes = STREAM_ICONS_NORMAL[i];
+ sc.iconMuteRes = STREAM_ICONS_MUTED[i];
+ sc.icon.setImageResource(sc.iconRes);
+ sc.seekbarView = (SeekBar) sc.group.findViewById(R.id.seekbar);
+ sc.seekbarView.setMax(mAudioManager.getStreamMaxVolume(STREAM_TYPES[i]));
+ sc.seekbarView.setOnSeekBarChangeListener(this);
+ sc.seekbarView.setTag(sc);
+ mStreamControls.put(STREAM_TYPES[i], sc);
+ }
+ }
+
+ private void reorderSliders(int activeStreamType) {
+ mSliderGroup.removeAllViews();
+
+ StreamControl active = mStreamControls.get(activeStreamType);
+ if (active == null) {
+ Log.e("VolumePanel", "Missing stream type! - " + activeStreamType);
+ mActiveStreamType = -1;
+ } else {
+ mSliderGroup.addView(active.group);
+ mActiveStreamType = activeStreamType;
+ active.group.setVisibility(View.VISIBLE);
+ updateSlider(active);
+ }
+
+ for (int i = 0; i < STREAM_TYPES.length; i++) {
+ // Skip the phone specific ones and the active one
+ final int streamType = STREAM_TYPES[i];
+ if (streamType == AudioManager.STREAM_RING
+ || streamType == AudioManager.STREAM_VOICE_CALL
+ || streamType == activeStreamType) {
+ continue;
+ }
+ StreamControl sc = mStreamControls.get(streamType);
+ mSliderGroup.addView(sc.group);
+ updateSlider(sc);
+ }
+ }
+
+ /** Update the mute and progress state of a slider */
+ private void updateSlider(StreamControl sc) {
+ sc.seekbarView.setProgress(mAudioManager.getLastAudibleStreamVolume(sc.streamType));
+ final boolean muted = isMuted(sc.streamType);
+ sc.icon.setImageResource(muted ? sc.iconMuteRes : sc.iconRes);
+ sc.seekbarView.setEnabled(!muted);
+ }
+
+ private boolean isExpanded() {
+ return mMoreButton.getVisibility() != View.VISIBLE;
+ }
+
+ private void expand() {
+ final int count = mSliderGroup.getChildCount();
+ for (int i = 0; i < count; i++) {
+ mSliderGroup.getChildAt(i).setVisibility(View.VISIBLE);
+ }
+ mMoreButton.setVisibility(View.INVISIBLE);
+ mDivider.setVisibility(View.INVISIBLE);
+ }
+
+ private void collapse() {
+ mMoreButton.setVisibility(View.VISIBLE);
+ mDivider.setVisibility(View.VISIBLE);
+ final int count = mSliderGroup.getChildCount();
+ for (int i = 1; i < count; i++) {
+ mSliderGroup.getChildAt(i).setVisibility(View.GONE);
+ }
+ }
+
+ private void updateStates() {
+ final int count = mSliderGroup.getChildCount();
+ for (int i = 0; i < count; i++) {
+ StreamControl sc = (StreamControl) mSliderGroup.getChildAt(i).getTag();
+ updateSlider(sc);
+ }
}
public void postVolumeChanged(int streamType, int flags) {
if (hasMessages(MSG_VOLUME_CHANGED)) return;
+ if (mStreamControls == null) {
+ createSliders();
+ }
removeMessages(MSG_FREE_RESOURCES);
obtainMessage(MSG_VOLUME_CHANGED, streamType, flags).sendToTarget();
}
@@ -137,6 +341,10 @@ public class VolumePanel extends Handler
if (LOGD) Log.d(TAG, "onVolumeChanged(streamType: " + streamType + ", flags: " + flags + ")");
+ if (mActiveStreamType == -1) {
+ reorderSliders(streamType);
+ }
+
if ((flags & AudioManager.FLAG_SHOW_UI) != 0) {
onShowVolumeChanged(streamType, flags);
}
@@ -154,12 +362,14 @@ public class VolumePanel extends Handler
removeMessages(MSG_FREE_RESOURCES);
sendMessageDelayed(obtainMessage(MSG_FREE_RESOURCES), FREE_DELAY);
+
+ resetTimeout();
}
protected void onShowVolumeChanged(int streamType, int flags) {
int index = mAudioService.getStreamVolume(streamType);
- int message = UNKNOWN_VOLUME_TEXT;
- int additionalMessage = 0;
+// int message = UNKNOWN_VOLUME_TEXT;
+// int additionalMessage = 0;
mRingIsSilent = false;
if (LOGD) {
@@ -168,31 +378,35 @@ public class VolumePanel extends Handler
}
// get max volume for progress bar
+
int max = mAudioService.getStreamMaxVolume(streamType);
switch (streamType) {
case AudioManager.STREAM_RING: {
- setRingerIcon();
- message = RINGTONE_VOLUME_TEXT;
+// setRingerIcon();
+// message = RINGTONE_VOLUME_TEXT;
Uri ringuri = RingtoneManager.getActualDefaultRingtoneUri(
mContext, RingtoneManager.TYPE_RINGTONE);
if (ringuri == null) {
- additionalMessage =
- com.android.internal.R.string.volume_music_hint_silent_ringtone_selected;
+// additionalMessage =
+// com.android.internal.R.string.volume_music_hint_silent_ringtone_selected;
mRingIsSilent = true;
}
break;
}
case AudioManager.STREAM_MUSIC: {
- message = MUSIC_VOLUME_TEXT;
+// message = MUSIC_VOLUME_TEXT;
+ // Special case for when Bluetooth is active for music
if (mAudioManager.isBluetoothA2dpOn()) {
- additionalMessage =
- com.android.internal.R.string.volume_music_hint_playing_through_bluetooth;
- setLargeIcon(com.android.internal.R.drawable.ic_volume_bluetooth_ad2p);
+// additionalMessage =
+// com.android.internal.R.string.volume_music_hint_playing_through_bluetooth;
+// setLargeIcon(com.android.internal.R.drawable.ic_volume_bluetooth_ad2p);
+ setMusicIcon(R.drawable.ic_audio_bt, R.drawable.ic_audio_bt_mute);
} else {
- setSmallIcon(index);
+ setMusicIcon(R.drawable.ic_audio_vol, R.drawable.ic_audio_vol_mute);
+// setSmallIcon(index);
}
break;
}
@@ -205,25 +419,25 @@ public class VolumePanel extends Handler
*/
index++;
max++;
- message = INCALL_VOLUME_TEXT;
- setSmallIcon(index);
+// message = INCALL_VOLUME_TEXT;
+// setSmallIcon(index);
break;
}
case AudioManager.STREAM_ALARM: {
- message = ALARM_VOLUME_TEXT;
- setSmallIcon(index);
+// message = ALARM_VOLUME_TEXT;
+// setSmallIcon(index);
break;
}
case AudioManager.STREAM_NOTIFICATION: {
- message = NOTIFICATION_VOLUME_TEXT;
- setSmallIcon(index);
+// message = NOTIFICATION_VOLUME_TEXT;
+// setSmallIcon(index);
Uri ringuri = RingtoneManager.getActualDefaultRingtoneUri(
mContext, RingtoneManager.TYPE_NOTIFICATION);
if (ringuri == null) {
- additionalMessage =
- com.android.internal.R.string.volume_music_hint_silent_ringtone_selected;
+// additionalMessage =
+// com.android.internal.R.string.volume_music_hint_silent_ringtone_selected;
mRingIsSilent = true;
}
break;
@@ -237,33 +451,40 @@ public class VolumePanel extends Handler
*/
index++;
max++;
- message = BLUETOOTH_INCALL_VOLUME_TEXT;
- setLargeIcon(com.android.internal.R.drawable.ic_volume_bluetooth_in_call);
+// message = BLUETOOTH_INCALL_VOLUME_TEXT;
+// setLargeIcon(com.android.internal.R.drawable.ic_volume_bluetooth_in_call);
break;
}
}
- String messageString = Resources.getSystem().getString(message);
- if (!mMessage.getText().equals(messageString)) {
- mMessage.setText(messageString);
+// String messageString = Resources.getSystem().getString(message);
+// if (!mMessage.getText().equals(messageString)) {
+// mMessage.setText(messageString);
+// }
+//
+// if (additionalMessage == 0) {
+// mAdditionalMessage.setVisibility(View.GONE);
+// } else {
+// mAdditionalMessage.setVisibility(View.VISIBLE);
+// mAdditionalMessage.setText(Resources.getSystem().getString(additionalMessage));
+// }
+
+// if (max != mLevel.getMax()) {
+// mLevel.setMax(max);
+// }
+// mLevel.setProgress(index);
+
+ StreamControl sc = mStreamControls.get(streamType);
+ if (sc != null) {
+ sc.seekbarView.setProgress(index);
}
- if (additionalMessage == 0) {
- mAdditionalMessage.setVisibility(View.GONE);
- } else {
- mAdditionalMessage.setVisibility(View.VISIBLE);
- mAdditionalMessage.setText(Resources.getSystem().getString(additionalMessage));
- }
-
- if (max != mLevel.getMax()) {
- mLevel.setMax(max);
+ if (!mDialog.isShowing()) {
+ mDialog.setContentView(mView);
+ // Showing dialog - use collapsed state
+ collapse();
+ mDialog.show();
}
- mLevel.setProgress(index);
-
- mToast.setView(mView);
- mToast.setDuration(Toast.LENGTH_SHORT);
- mToast.setGravity(Gravity.TOP, 0, 0);
- mToast.show();
// Do a little vibrate if applicable (only when going into vibrate mode)
if ((flags & AudioManager.FLAG_VIBRATE) != 0 &&
@@ -333,59 +554,72 @@ public class VolumePanel extends Handler
}
}
- /**
- * Makes the small icon visible, and hides the large icon.
- *
- * @param index The volume index, where 0 means muted.
- */
- private void setSmallIcon(int index) {
- mLargeStreamIcon.setVisibility(View.GONE);
- mSmallStreamIcon.setVisibility(View.VISIBLE);
-
- mSmallStreamIcon.setImageResource(index == 0
- ? com.android.internal.R.drawable.ic_volume_off_small
- : com.android.internal.R.drawable.ic_volume_small);
- }
-
- /**
- * Makes the large image view visible with the given icon.
- *
- * @param resId The icon to display.
- */
- private void setLargeIcon(int resId) {
- mSmallStreamIcon.setVisibility(View.GONE);
- mLargeStreamIcon.setVisibility(View.VISIBLE);
- mLargeStreamIcon.setImageResource(resId);
- }
+// /**
+// * Makes the small icon visible, and hides the large icon.
+// *
+// * @param index The volume index, where 0 means muted.
+// */
+// private void setSmallIcon(int index) {
+// mLargeStreamIcon.setVisibility(View.GONE);
+// mSmallStreamIcon.setVisibility(View.VISIBLE);
+//
+// mSmallStreamIcon.setImageResource(index == 0
+// ? com.android.internal.R.drawable.ic_volume_off_small
+// : com.android.internal.R.drawable.ic_volume_small);
+// }
+//
+// /**
+// * Makes the large image view visible with the given icon.
+// *
+// * @param resId The icon to display.
+// */
+// private void setLargeIcon(int resId) {
+// mSmallStreamIcon.setVisibility(View.GONE);
+// mLargeStreamIcon.setVisibility(View.VISIBLE);
+// mLargeStreamIcon.setImageResource(resId);
+// }
+//
+// /**
+// * Makes the ringer icon visible with an icon that is chosen
+// * based on the current ringer mode.
+// */
+// private void setRingerIcon() {
+// mSmallStreamIcon.setVisibility(View.GONE);
+// mLargeStreamIcon.setVisibility(View.VISIBLE);
+//
+// int ringerMode = mAudioService.getRingerMode();
+// int icon;
+//
+// if (LOGD) Log.d(TAG, "setRingerIcon(), ringerMode: " + ringerMode);
+//
+// if (ringerMode == AudioManager.RINGER_MODE_SILENT) {
+// icon = com.android.internal.R.drawable.ic_volume_off;
+// } else if (ringerMode == AudioManager.RINGER_MODE_VIBRATE) {
+// icon = com.android.internal.R.drawable.ic_vibrate;
+// } else {
+// icon = com.android.internal.R.drawable.ic_volume;
+// }
+// mLargeStreamIcon.setImageResource(icon);
+// }
/**
- * Makes the ringer icon visible with an icon that is chosen
- * based on the current ringer mode.
+ * Switch between icons because Bluetooth music is same as music volume, but with
+ * different icons.
*/
- private void setRingerIcon() {
- mSmallStreamIcon.setVisibility(View.GONE);
- mLargeStreamIcon.setVisibility(View.VISIBLE);
-
- int ringerMode = mAudioService.getRingerMode();
- int icon;
-
- if (LOGD) Log.d(TAG, "setRingerIcon(), ringerMode: " + ringerMode);
-
- if (ringerMode == AudioManager.RINGER_MODE_SILENT) {
- icon = com.android.internal.R.drawable.ic_volume_off;
- } else if (ringerMode == AudioManager.RINGER_MODE_VIBRATE) {
- icon = com.android.internal.R.drawable.ic_vibrate;
- } else {
- icon = com.android.internal.R.drawable.ic_volume;
+ private void setMusicIcon(int resId, int resMuteId) {
+ StreamControl sc = mStreamControls.get(AudioManager.STREAM_MUSIC);
+ if (sc != null) {
+ sc.iconRes = resId;
+ sc.iconMuteRes = resMuteId;
+ sc.icon.setImageResource(isMuted(sc.streamType) ? sc.iconMuteRes : sc.iconRes);
}
- mLargeStreamIcon.setImageResource(icon);
}
protected void onFreeResources() {
// We'll keep the views, just ditch the cached drawable and hence
// bitmaps
- mSmallStreamIcon.setImageDrawable(null);
- mLargeStreamIcon.setImageDrawable(null);
+// mSmallStreamIcon.setImageDrawable(null);
+// mLargeStreamIcon.setImageDrawable(null);
synchronized (this) {
for (int i = mToneGenerators.length - 1; i >= 0; i--) {
@@ -426,7 +660,55 @@ public class VolumePanel extends Handler
break;
}
+ case MSG_TIMEOUT: {
+ if (mDialog.isShowing()) {
+ mDialog.dismiss();
+ mActiveStreamType = -1;
+ }
+ break;
+ }
+ case MSG_RINGER_MODE_CHANGED: {
+ if (mDialog.isShowing()) {
+ updateStates();
+ }
+ break;
+ }
}
}
+ private void resetTimeout() {
+ removeMessages(MSG_TIMEOUT);
+ sendMessageDelayed(obtainMessage(MSG_TIMEOUT), TIMEOUT_DELAY);
+ }
+
+ public void onProgressChanged(SeekBar seekBar, int progress,
+ boolean fromUser) {
+ final Object tag = seekBar.getTag();
+ if (fromUser && tag instanceof StreamControl) {
+ StreamControl sc = (StreamControl) tag;
+ if (mAudioManager.getStreamVolume(sc.streamType) != progress) {
+ mAudioManager.setStreamVolume(sc.streamType, progress, 0);
+ }
+ }
+ resetTimeout();
+ }
+
+ public void onStartTrackingTouch(SeekBar seekBar) {
+ }
+
+ public void onStopTrackingTouch(SeekBar seekBar) {
+ }
+
+ public void onClick(View v) {
+ if (v == mMoreButton) {
+ expand();
+ } else if (v.getTag() instanceof StreamControl) {
+ StreamControl sc = (StreamControl) v.getTag();
+ mAudioManager.setRingerMode(mAudioManager.isSilentMode()
+ ? AudioManager.RINGER_MODE_NORMAL : AudioManager.RINGER_MODE_SILENT);
+ // Expand the dialog if it hasn't been expanded yet.
+ if (!isExpanded()) expand();
+ }
+ resetTimeout();
+ }
}
diff --git a/core/res/res/drawable-hdpi/ic_sysbar_quicksettings.png b/core/res/res/drawable-hdpi/ic_sysbar_quicksettings.png
new file mode 100644
index 000000000000..47b4ba23f7a5
--- /dev/null
+++ b/core/res/res/drawable-hdpi/ic_sysbar_quicksettings.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_sysbar_quicksettings.png b/core/res/res/drawable-mdpi/ic_sysbar_quicksettings.png
new file mode 100644
index 000000000000..792810427f92
--- /dev/null
+++ b/core/res/res/drawable-mdpi/ic_sysbar_quicksettings.png
Binary files differ
diff --git a/core/res/res/layout/volume_adjust.xml b/core/res/res/layout/volume_adjust.xml
index 18da85f93d9a..b0ca3e8e71ff 100644
--- a/core/res/res/layout/volume_adjust.xml
+++ b/core/res/res/layout/volume_adjust.xml
@@ -17,56 +17,48 @@
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:background="@android:drawable/dialog_full_holo_dark"
android:gravity="left">
<LinearLayout
- android:layout_width="416dip"
- android:layout_height="wrap_content"
- android:paddingLeft="16dip"
- android:paddingTop="16dip"
- android:paddingRight="16dip"
- android:paddingBottom="8dip"
- android:orientation="vertical">
-
- <LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:layout_marginBottom="8dip"
- android:gravity="left">
-
- <ImageView
- android:id="@+id/other_stream_icon"
+ android:layout_marginTop="80dip"
+ android:background="@android:drawable/dialog_full_holo_dark"
+ android:orientation="horizontal"
+ >
+
+ <LinearLayout
+ android:id="@+id/slider_group"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:layout_marginRight="16dip" />
+ android:orientation="vertical"
+ >
+ <!-- Sliders go here -->
+ </LinearLayout>
- <TextView
+ <ImageView
+ android:id="@+id/expand_button_divider"
+ android:src="?attr/dividerVertical"
android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:id="@+id/message"
- android:textAppearance="?android:attr/textAppearanceMedium" />
+ android:layout_height="32dip"
+ android:scaleType="fitXY"
+ android:layout_gravity="top"
+ android:layout_marginTop="16dip"
+ android:layout_marginBottom="16dip"
+ />
+ <ImageView
+ android:id="@+id/expand_button"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="top"
+ android:padding="16dip"
+ android:background="?attr/selectableItemBackground"
+ android:src="@drawable/ic_sysbar_quicksettings"
+ />
+
</LinearLayout>
- <TextView
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:id="@+id/additional_message"
- android:textAppearance="?android:attr/textAppearanceSmall" />
-
- <ImageView
- android:id="@+id/ringer_stream_icon"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginTop="14dip" />
-
- <ProgressBar
- style="?android:attr/progressBarStyleHorizontal"
- android:id="@+id/level"
- android:layout_width="match_parent"
- android:layout_height="wrap_content" />
- </LinearLayout>
</FrameLayout>
diff --git a/core/res/res/layout/volume_adjust_item.xml b/core/res/res/layout/volume_adjust_item.xml
new file mode 100644
index 000000000000..e841d878af0c
--- /dev/null
+++ b/core/res/res/layout/volume_adjust_item.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2011 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.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="wrap_content"
+ android:layout_height="80dip"
+ android:orientation="horizontal"
+ android:layout_marginTop="8dip"
+ android:layout_marginBottom="8dip"
+ android:gravity="left|center_vertical">
+
+ <ImageView
+ android:id="@+id/stream_icon"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:padding="16dip"
+ android:layout_marginLeft="8dip"
+ android:background="?attr/selectableItemBackground"
+ />
+
+ <SeekBar
+ style="?android:attr/seekBarStyle"
+ android:id="@+id/seekbar"
+ android:layout_width="300dip"
+ android:layout_height="wrap_content"
+ android:padding="16dip"
+ android:layout_marginLeft="8dip"
+ android:layout_marginRight="8dip" />
+
+</LinearLayout>
+
+
diff --git a/core/res/res/values/styles.xml b/core/res/res/values/styles.xml
index e2751bd59029..5700641f3986 100644
--- a/core/res/res/values/styles.xml
+++ b/core/res/res/values/styles.xml
@@ -208,6 +208,11 @@
<item name="windowExitAnimation">@anim/fade_out</item>
</style>
+ <!-- Window animations used for volume panel. -->
+ <style name="Animation.VolumePanel">
+ <item name="windowEnterAnimation">@null</item>
+ <item name="windowExitAnimation">@anim/fade_out</item>
+ </style>
<!-- Status Bar Styles -->
<style name="TextAppearance.StatusBar">
diff --git a/core/res/res/values/themes.xml b/core/res/res/values/themes.xml
index 38b068e25c95..6d5b4822b1dc 100644
--- a/core/res/res/values/themes.xml
+++ b/core/res/res/values/themes.xml
@@ -730,6 +730,11 @@
<item name="android:windowCloseOnTouchOutside">false</item>
</style>
+ <style name="Theme.Panel.Volume">
+ <item name="android:windowAnimationStyle">@android:style/Animation.VolumePanel</item>
+ <item name="android:windowCloseOnTouchOutside">true</item>
+ </style>
+
<!-- Default theme with an Action Bar. -->
<style name="Theme.WithActionBar">
<item name="android:windowActionBar">true</item>