19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/* 29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Copyright (C) 2007 The Android Open Source Project 39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 49066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License"); 59066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * you may not use this file except in compliance with the License. 69066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * You may obtain a copy of the License at 79066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 89066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0 99066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Unless required by applicable law or agreed to in writing, software 119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS, 129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * See the License for the specific language governing permissions and 149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * limitations under the License. 159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpackage android.view; 189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 192bbdd77ab20788e901a410f299edef028b66bb6eAmith Yamasaniimport com.android.internal.R; 202bbdd77ab20788e901a410f299edef028b66bb6eAmith Yamasani 21c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurentimport android.app.AlertDialog; 222bbdd77ab20788e901a410f299edef028b66bb6eAmith Yamasaniimport android.app.Dialog; 232bbdd77ab20788e901a410f299edef028b66bb6eAmith Yamasaniimport android.content.DialogInterface.OnDismissListener; 242bbdd77ab20788e901a410f299edef028b66bb6eAmith Yamasaniimport android.content.BroadcastReceiver; 259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.Context; 262bbdd77ab20788e901a410f299edef028b66bb6eAmith Yamasaniimport android.content.DialogInterface; 279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.Intent; 282bbdd77ab20788e901a410f299edef028b66bb6eAmith Yamasaniimport android.content.IntentFilter; 299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.res.Resources; 309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.media.AudioManager; 319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.media.AudioService; 329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.media.AudioSystem; 3369f593ccb7414ee98991b1da1a4bfbd9951e3570Marco Nelissenimport android.media.RingtoneManager; 349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.media.ToneGenerator; 3569f593ccb7414ee98991b1da1a4bfbd9951e3570Marco Nelissenimport android.net.Uri; 369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Handler; 379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Message; 389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Vibrator; 399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.Log; 40284e630a9b7f126ffb83cee4a1c4fe5134190cabAmith Yamasaniimport android.view.WindowManager.LayoutParams; 419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.widget.ImageView; 422bbdd77ab20788e901a410f299edef028b66bb6eAmith Yamasaniimport android.widget.SeekBar; 432bbdd77ab20788e901a410f299edef028b66bb6eAmith Yamasaniimport android.widget.SeekBar.OnSeekBarChangeListener; 442bbdd77ab20788e901a410f299edef028b66bb6eAmith Yamasani 452bbdd77ab20788e901a410f299edef028b66bb6eAmith Yamasaniimport java.util.HashMap; 469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/** 489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Handle the volume up and down keys. 499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * This code really should be moved elsewhere. 519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 52e8ecde10b33b1d050d2b63b3f4cd20e8bb7c96d4Dianne Hackborn * Seriously, it really really should be moved elsewhere. This is used by 53e8ecde10b33b1d050d2b63b3f4cd20e8bb7c96d4Dianne Hackborn * android.media.AudioService, which actually runs in the system process, to 54e8ecde10b33b1d050d2b63b3f4cd20e8bb7c96d4Dianne Hackborn * show the volume dialog when the user changes the volume. What a mess. 55e8ecde10b33b1d050d2b63b3f4cd20e8bb7c96d4Dianne Hackborn * 569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @hide 579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 582bbdd77ab20788e901a410f299edef028b66bb6eAmith Yamasanipublic class VolumePanel extends Handler implements OnSeekBarChangeListener, View.OnClickListener 599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final String TAG = "VolumePanel"; 6169f593ccb7414ee98991b1da1a4bfbd9951e3570Marco Nelissen private static boolean LOGD = false; 629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * The delay before playing a sound. This small period exists so the user 659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * can press another key (non-volume keys, too) to have it NOT be audible. 669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p> 679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * PhoneWindow will implement this part. 689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static final int PLAY_SOUND_DELAY = 300; 709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * The delay before vibrating. This small period exists so if the user is 739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * moving to silent mode, it will not emit a short vibrate (it normally 749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * would since vibrate is between normal mode and silent mode using hardware 759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * keys). 769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static final int VIBRATE_DELAY = 300; 789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final int VIBRATE_DURATION = 300; 809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final int BEEP_DURATION = 150; 819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final int MAX_VOLUME = 100; 829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final int FREE_DELAY = 10000; 832bbdd77ab20788e901a410f299edef028b66bb6eAmith Yamasani private static final int TIMEOUT_DELAY = 3000; 849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final int MSG_VOLUME_CHANGED = 0; 869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final int MSG_FREE_RESOURCES = 1; 879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final int MSG_PLAY_SOUND = 2; 889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final int MSG_STOP_SOUNDS = 3; 899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final int MSG_VIBRATE = 4; 902bbdd77ab20788e901a410f299edef028b66bb6eAmith Yamasani private static final int MSG_TIMEOUT = 5; 912bbdd77ab20788e901a410f299edef028b66bb6eAmith Yamasani private static final int MSG_RINGER_MODE_CHANGED = 6; 92ce952c8e13c535bedde77bcdb94dfcc7508475aaMike Lockwood private static final int MSG_MUTE_CHANGED = 7; 933114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi private static final int MSG_REMOTE_VOLUME_CHANGED = 8; 943114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi private static final int MSG_REMOTE_VOLUME_UPDATE_IF_SHOWN = 9; 953114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi private static final int MSG_SLIDER_VISIBILITY_CHANGED = 10; 96c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent private static final int MSG_DISPLAY_SAFE_VOLUME_WARNING = 11; 972bbdd77ab20788e901a410f299edef028b66bb6eAmith Yamasani 988dc1dabd254249b7ddb8743e88fdb96580ffc585Mike Lockwood // Pseudo stream type for master volume 994767690f09ea3447b8c5c32fb28d27650aa18e00Mike Lockwood private static final int STREAM_MASTER = -100; 1003114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi // Pseudo stream type for remote volume is defined in AudioService.STREAM_REMOTE_MUSIC 1018dc1dabd254249b7ddb8743e88fdb96580ffc585Mike Lockwood 1029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project protected Context mContext; 1039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private AudioManager mAudioManager; 1049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project protected AudioService mAudioService; 10569f593ccb7414ee98991b1da1a4bfbd9951e3570Marco Nelissen private boolean mRingIsSilent; 10642722bfa136f5616872a2c4e199813e804621c81Amith Yamasani private boolean mShowCombinedVolumes; 10771def77a2811ce99ee50f09bc933ff380ce85055Amith Yamasani private boolean mVoiceCapable; 1089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 109c4b78d206ffcdccac01e3436a4a3462bef9672edChristopher Tate // True if we want to play tones on the system stream when the master stream is specified. 110c4b78d206ffcdccac01e3436a4a3462bef9672edChristopher Tate private final boolean mPlayMasterStreamTones; 111c4b78d206ffcdccac01e3436a4a3462bef9672edChristopher Tate 1122bbdd77ab20788e901a410f299edef028b66bb6eAmith Yamasani /** Dialog containing all the sliders */ 1132bbdd77ab20788e901a410f299edef028b66bb6eAmith Yamasani private final Dialog mDialog; 1142bbdd77ab20788e901a410f299edef028b66bb6eAmith Yamasani /** Dialog's content view */ 1159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private final View mView; 1162bbdd77ab20788e901a410f299edef028b66bb6eAmith Yamasani 117baf6dbfa9340f3266e41841ebd51f21effc583eeAmith Yamasani /** The visible portion of the volume overlay */ 118baf6dbfa9340f3266e41841ebd51f21effc583eeAmith Yamasani private final ViewGroup mPanel; 1192bbdd77ab20788e901a410f299edef028b66bb6eAmith Yamasani /** Contains the sliders and their touchable icons */ 1202bbdd77ab20788e901a410f299edef028b66bb6eAmith Yamasani private final ViewGroup mSliderGroup; 1212bbdd77ab20788e901a410f299edef028b66bb6eAmith Yamasani /** The button that expands the dialog to show all sliders */ 1222bbdd77ab20788e901a410f299edef028b66bb6eAmith Yamasani private final View mMoreButton; 1232bbdd77ab20788e901a410f299edef028b66bb6eAmith Yamasani /** Dummy divider icon that needs to vanish with the more button */ 1242bbdd77ab20788e901a410f299edef028b66bb6eAmith Yamasani private final View mDivider; 1252bbdd77ab20788e901a410f299edef028b66bb6eAmith Yamasani 1262bbdd77ab20788e901a410f299edef028b66bb6eAmith Yamasani /** Currently active stream that shows up at the top of the list of sliders */ 1272bbdd77ab20788e901a410f299edef028b66bb6eAmith Yamasani private int mActiveStreamType = -1; 1282bbdd77ab20788e901a410f299edef028b66bb6eAmith Yamasani /** All the slider controls mapped by stream type */ 1292bbdd77ab20788e901a410f299edef028b66bb6eAmith Yamasani private HashMap<Integer,StreamControl> mStreamControls; 1302bbdd77ab20788e901a410f299edef028b66bb6eAmith Yamasani 13171def77a2811ce99ee50f09bc933ff380ce85055Amith Yamasani private enum StreamResources { 13271def77a2811ce99ee50f09bc933ff380ce85055Amith Yamasani BluetoothSCOStream(AudioManager.STREAM_BLUETOOTH_SCO, 13371def77a2811ce99ee50f09bc933ff380ce85055Amith Yamasani R.string.volume_icon_description_bluetooth, 13471def77a2811ce99ee50f09bc933ff380ce85055Amith Yamasani R.drawable.ic_audio_bt, 13571def77a2811ce99ee50f09bc933ff380ce85055Amith Yamasani R.drawable.ic_audio_bt, 13671def77a2811ce99ee50f09bc933ff380ce85055Amith Yamasani false), 13771def77a2811ce99ee50f09bc933ff380ce85055Amith Yamasani RingerStream(AudioManager.STREAM_RING, 13871def77a2811ce99ee50f09bc933ff380ce85055Amith Yamasani R.string.volume_icon_description_ringer, 13971def77a2811ce99ee50f09bc933ff380ce85055Amith Yamasani R.drawable.ic_audio_ring_notif, 14071def77a2811ce99ee50f09bc933ff380ce85055Amith Yamasani R.drawable.ic_audio_ring_notif_mute, 14171def77a2811ce99ee50f09bc933ff380ce85055Amith Yamasani false), 14271def77a2811ce99ee50f09bc933ff380ce85055Amith Yamasani VoiceStream(AudioManager.STREAM_VOICE_CALL, 14371def77a2811ce99ee50f09bc933ff380ce85055Amith Yamasani R.string.volume_icon_description_incall, 14471def77a2811ce99ee50f09bc933ff380ce85055Amith Yamasani R.drawable.ic_audio_phone, 14571def77a2811ce99ee50f09bc933ff380ce85055Amith Yamasani R.drawable.ic_audio_phone, 14671def77a2811ce99ee50f09bc933ff380ce85055Amith Yamasani false), 14792e1b2d37be8d3d76a55d0242b3cfab7fd8e449aAmith Yamasani AlarmStream(AudioManager.STREAM_ALARM, 14892e1b2d37be8d3d76a55d0242b3cfab7fd8e449aAmith Yamasani R.string.volume_alarm, 14992e1b2d37be8d3d76a55d0242b3cfab7fd8e449aAmith Yamasani R.drawable.ic_audio_alarm, 15092e1b2d37be8d3d76a55d0242b3cfab7fd8e449aAmith Yamasani R.drawable.ic_audio_alarm_mute, 15192e1b2d37be8d3d76a55d0242b3cfab7fd8e449aAmith Yamasani false), 15271def77a2811ce99ee50f09bc933ff380ce85055Amith Yamasani MediaStream(AudioManager.STREAM_MUSIC, 15371def77a2811ce99ee50f09bc933ff380ce85055Amith Yamasani R.string.volume_icon_description_media, 15471def77a2811ce99ee50f09bc933ff380ce85055Amith Yamasani R.drawable.ic_audio_vol, 15571def77a2811ce99ee50f09bc933ff380ce85055Amith Yamasani R.drawable.ic_audio_vol_mute, 15671def77a2811ce99ee50f09bc933ff380ce85055Amith Yamasani true), 15771def77a2811ce99ee50f09bc933ff380ce85055Amith Yamasani NotificationStream(AudioManager.STREAM_NOTIFICATION, 15871def77a2811ce99ee50f09bc933ff380ce85055Amith Yamasani R.string.volume_icon_description_notification, 15971def77a2811ce99ee50f09bc933ff380ce85055Amith Yamasani R.drawable.ic_audio_notification, 16071def77a2811ce99ee50f09bc933ff380ce85055Amith Yamasani R.drawable.ic_audio_notification_mute, 1618dc1dabd254249b7ddb8743e88fdb96580ffc585Mike Lockwood true), 1628dc1dabd254249b7ddb8743e88fdb96580ffc585Mike Lockwood // for now, use media resources for master volume 1638dc1dabd254249b7ddb8743e88fdb96580ffc585Mike Lockwood MasterStream(STREAM_MASTER, 1643114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi R.string.volume_icon_description_media, //FIXME should have its own description 1658dc1dabd254249b7ddb8743e88fdb96580ffc585Mike Lockwood R.drawable.ic_audio_vol, 1668dc1dabd254249b7ddb8743e88fdb96580ffc585Mike Lockwood R.drawable.ic_audio_vol_mute, 1673114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi false), 1683114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi RemoteStream(AudioService.STREAM_REMOTE_MUSIC, 1693114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi R.string.volume_icon_description_media, //FIXME should have its own description 1703114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi R.drawable.ic_media_route_on_holo_dark, 1713114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi R.drawable.ic_media_route_disabled_holo_dark, 1723114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi false);// will be dynamically updated 1732bbdd77ab20788e901a410f299edef028b66bb6eAmith Yamasani 17471def77a2811ce99ee50f09bc933ff380ce85055Amith Yamasani int streamType; 17571def77a2811ce99ee50f09bc933ff380ce85055Amith Yamasani int descRes; 17671def77a2811ce99ee50f09bc933ff380ce85055Amith Yamasani int iconRes; 17771def77a2811ce99ee50f09bc933ff380ce85055Amith Yamasani int iconMuteRes; 17871def77a2811ce99ee50f09bc933ff380ce85055Amith Yamasani // RING, VOICE_CALL & BLUETOOTH_SCO are hidden unless explicitly requested 17971def77a2811ce99ee50f09bc933ff380ce85055Amith Yamasani boolean show; 18071def77a2811ce99ee50f09bc933ff380ce85055Amith Yamasani 18171def77a2811ce99ee50f09bc933ff380ce85055Amith Yamasani StreamResources(int streamType, int descRes, int iconRes, int iconMuteRes, boolean show) { 18271def77a2811ce99ee50f09bc933ff380ce85055Amith Yamasani this.streamType = streamType; 18371def77a2811ce99ee50f09bc933ff380ce85055Amith Yamasani this.descRes = descRes; 18471def77a2811ce99ee50f09bc933ff380ce85055Amith Yamasani this.iconRes = iconRes; 18571def77a2811ce99ee50f09bc933ff380ce85055Amith Yamasani this.iconMuteRes = iconMuteRes; 18671def77a2811ce99ee50f09bc933ff380ce85055Amith Yamasani this.show = show; 18771def77a2811ce99ee50f09bc933ff380ce85055Amith Yamasani } 1882bbdd77ab20788e901a410f299edef028b66bb6eAmith Yamasani }; 1892bbdd77ab20788e901a410f299edef028b66bb6eAmith Yamasani 19071def77a2811ce99ee50f09bc933ff380ce85055Amith Yamasani // List of stream types and their order 19171def77a2811ce99ee50f09bc933ff380ce85055Amith Yamasani private static final StreamResources[] STREAMS = { 19271def77a2811ce99ee50f09bc933ff380ce85055Amith Yamasani StreamResources.BluetoothSCOStream, 19371def77a2811ce99ee50f09bc933ff380ce85055Amith Yamasani StreamResources.RingerStream, 19471def77a2811ce99ee50f09bc933ff380ce85055Amith Yamasani StreamResources.VoiceStream, 19571def77a2811ce99ee50f09bc933ff380ce85055Amith Yamasani StreamResources.MediaStream, 19692e1b2d37be8d3d76a55d0242b3cfab7fd8e449aAmith Yamasani StreamResources.NotificationStream, 1978dc1dabd254249b7ddb8743e88fdb96580ffc585Mike Lockwood StreamResources.AlarmStream, 1983114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi StreamResources.MasterStream, 1993114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi StreamResources.RemoteStream 2002bbdd77ab20788e901a410f299edef028b66bb6eAmith Yamasani }; 2012bbdd77ab20788e901a410f299edef028b66bb6eAmith Yamasani 2022bbdd77ab20788e901a410f299edef028b66bb6eAmith Yamasani /** Object that contains data for each slider */ 2032bbdd77ab20788e901a410f299edef028b66bb6eAmith Yamasani private class StreamControl { 2042bbdd77ab20788e901a410f299edef028b66bb6eAmith Yamasani int streamType; 2052bbdd77ab20788e901a410f299edef028b66bb6eAmith Yamasani ViewGroup group; 2062bbdd77ab20788e901a410f299edef028b66bb6eAmith Yamasani ImageView icon; 2072bbdd77ab20788e901a410f299edef028b66bb6eAmith Yamasani SeekBar seekbarView; 2082bbdd77ab20788e901a410f299edef028b66bb6eAmith Yamasani int iconRes; 2092bbdd77ab20788e901a410f299edef028b66bb6eAmith Yamasani int iconMuteRes; 2102bbdd77ab20788e901a410f299edef028b66bb6eAmith Yamasani } 2119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Synchronize when accessing this 2139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private ToneGenerator mToneGenerators[]; 2149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private Vibrator mVibrator; 2159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 216c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent private static AlertDialog sConfirmSafeVolumeDialog; 2170516a9ecb0d4d76acd2f1c4c2521f44c696789a8Eric Laurent private static Object sConfirmSafeVolumeLock = new Object(); 218c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent 219c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent private static class WarningDialogReceiver extends BroadcastReceiver 220c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent implements DialogInterface.OnDismissListener { 221c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent private Context mContext; 222c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent private Dialog mDialog; 223c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent 224c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent WarningDialogReceiver(Context context, Dialog dialog) { 225c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent mContext = context; 226c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent mDialog = dialog; 227c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent IntentFilter filter = new IntentFilter(Intent.ACTION_CLOSE_SYSTEM_DIALOGS); 228c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent context.registerReceiver(this, filter); 229c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent } 230c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent 231c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent @Override 232c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent public void onReceive(Context context, Intent intent) { 233c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent mDialog.cancel(); 2340516a9ecb0d4d76acd2f1c4c2521f44c696789a8Eric Laurent synchronized (sConfirmSafeVolumeLock) { 2350516a9ecb0d4d76acd2f1c4c2521f44c696789a8Eric Laurent sConfirmSafeVolumeDialog = null; 2360516a9ecb0d4d76acd2f1c4c2521f44c696789a8Eric Laurent } 237c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent } 238c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent 239c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent public void onDismiss(DialogInterface unused) { 240c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent mContext.unregisterReceiver(this); 2410516a9ecb0d4d76acd2f1c4c2521f44c696789a8Eric Laurent synchronized (sConfirmSafeVolumeLock) { 2420516a9ecb0d4d76acd2f1c4c2521f44c696789a8Eric Laurent sConfirmSafeVolumeDialog = null; 2430516a9ecb0d4d76acd2f1c4c2521f44c696789a8Eric Laurent } 244c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent } 245c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent } 246c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent 247c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent 2482bbdd77ab20788e901a410f299edef028b66bb6eAmith Yamasani public VolumePanel(final Context context, AudioService volumeService) { 2499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext = context; 2509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE); 2519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mAudioService = volumeService; 2529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2538dc1dabd254249b7ddb8743e88fdb96580ffc585Mike Lockwood // For now, only show master volume if master volume is supported 2548dc1dabd254249b7ddb8743e88fdb96580ffc585Mike Lockwood boolean useMasterVolume = context.getResources().getBoolean( 2558dc1dabd254249b7ddb8743e88fdb96580ffc585Mike Lockwood com.android.internal.R.bool.config_useMasterVolume); 2568dc1dabd254249b7ddb8743e88fdb96580ffc585Mike Lockwood if (useMasterVolume) { 2578dc1dabd254249b7ddb8743e88fdb96580ffc585Mike Lockwood for (int i = 0; i < STREAMS.length; i++) { 2588dc1dabd254249b7ddb8743e88fdb96580ffc585Mike Lockwood StreamResources streamRes = STREAMS[i]; 2598dc1dabd254249b7ddb8743e88fdb96580ffc585Mike Lockwood streamRes.show = (streamRes.streamType == STREAM_MASTER); 2608dc1dabd254249b7ddb8743e88fdb96580ffc585Mike Lockwood } 2618dc1dabd254249b7ddb8743e88fdb96580ffc585Mike Lockwood } 2628dc1dabd254249b7ddb8743e88fdb96580ffc585Mike Lockwood 2639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project LayoutInflater inflater = (LayoutInflater) context 2649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project .getSystemService(Context.LAYOUT_INFLATER_SERVICE); 2652bbdd77ab20788e901a410f299edef028b66bb6eAmith Yamasani View view = mView = inflater.inflate(R.layout.volume_adjust, null); 2662bbdd77ab20788e901a410f299edef028b66bb6eAmith Yamasani mView.setOnTouchListener(new View.OnTouchListener() { 2672bbdd77ab20788e901a410f299edef028b66bb6eAmith Yamasani public boolean onTouch(View v, MotionEvent event) { 2682bbdd77ab20788e901a410f299edef028b66bb6eAmith Yamasani resetTimeout(); 269284e630a9b7f126ffb83cee4a1c4fe5134190cabAmith Yamasani return false; 2702bbdd77ab20788e901a410f299edef028b66bb6eAmith Yamasani } 2712bbdd77ab20788e901a410f299edef028b66bb6eAmith Yamasani }); 272baf6dbfa9340f3266e41841ebd51f21effc583eeAmith Yamasani mPanel = (ViewGroup) mView.findViewById(R.id.visible_panel); 2732bbdd77ab20788e901a410f299edef028b66bb6eAmith Yamasani mSliderGroup = (ViewGroup) mView.findViewById(R.id.slider_group); 2742bbdd77ab20788e901a410f299edef028b66bb6eAmith Yamasani mMoreButton = (ImageView) mView.findViewById(R.id.expand_button); 2752bbdd77ab20788e901a410f299edef028b66bb6eAmith Yamasani mDivider = (ImageView) mView.findViewById(R.id.expand_button_divider); 2762bbdd77ab20788e901a410f299edef028b66bb6eAmith Yamasani 277284e630a9b7f126ffb83cee4a1c4fe5134190cabAmith Yamasani mDialog = new Dialog(context, R.style.Theme_Panel_Volume) { 278284e630a9b7f126ffb83cee4a1c4fe5134190cabAmith Yamasani public boolean onTouchEvent(MotionEvent event) { 279284e630a9b7f126ffb83cee4a1c4fe5134190cabAmith Yamasani if (isShowing() && event.getAction() == MotionEvent.ACTION_OUTSIDE) { 280284e630a9b7f126ffb83cee4a1c4fe5134190cabAmith Yamasani forceTimeout(); 281284e630a9b7f126ffb83cee4a1c4fe5134190cabAmith Yamasani return true; 282284e630a9b7f126ffb83cee4a1c4fe5134190cabAmith Yamasani } 283284e630a9b7f126ffb83cee4a1c4fe5134190cabAmith Yamasani return false; 284284e630a9b7f126ffb83cee4a1c4fe5134190cabAmith Yamasani } 285284e630a9b7f126ffb83cee4a1c4fe5134190cabAmith Yamasani }; 2862bbdd77ab20788e901a410f299edef028b66bb6eAmith Yamasani mDialog.setTitle("Volume control"); // No need to localize 2872bbdd77ab20788e901a410f299edef028b66bb6eAmith Yamasani mDialog.setContentView(mView); 2882bbdd77ab20788e901a410f299edef028b66bb6eAmith Yamasani mDialog.setOnDismissListener(new OnDismissListener() { 2892bbdd77ab20788e901a410f299edef028b66bb6eAmith Yamasani public void onDismiss(DialogInterface dialog) { 2902bbdd77ab20788e901a410f299edef028b66bb6eAmith Yamasani mActiveStreamType = -1; 291402f7f29634a9f68e7929be828a927a3e2f5efe9Eric Laurent mAudioManager.forceVolumeControlStream(mActiveStreamType); 2922bbdd77ab20788e901a410f299edef028b66bb6eAmith Yamasani } 2932bbdd77ab20788e901a410f299edef028b66bb6eAmith Yamasani }); 2942bbdd77ab20788e901a410f299edef028b66bb6eAmith Yamasani // Change some window properties 2952bbdd77ab20788e901a410f299edef028b66bb6eAmith Yamasani Window window = mDialog.getWindow(); 2962bbdd77ab20788e901a410f299edef028b66bb6eAmith Yamasani window.setGravity(Gravity.TOP); 297284e630a9b7f126ffb83cee4a1c4fe5134190cabAmith Yamasani LayoutParams lp = window.getAttributes(); 2982bbdd77ab20788e901a410f299edef028b66bb6eAmith Yamasani lp.token = null; 299284e630a9b7f126ffb83cee4a1c4fe5134190cabAmith Yamasani // Offset from the top 300284e630a9b7f126ffb83cee4a1c4fe5134190cabAmith Yamasani lp.y = mContext.getResources().getDimensionPixelOffset( 301284e630a9b7f126ffb83cee4a1c4fe5134190cabAmith Yamasani com.android.internal.R.dimen.volume_panel_top); 302284e630a9b7f126ffb83cee4a1c4fe5134190cabAmith Yamasani lp.type = LayoutParams.TYPE_VOLUME_OVERLAY; 303284e630a9b7f126ffb83cee4a1c4fe5134190cabAmith Yamasani lp.width = LayoutParams.WRAP_CONTENT; 304284e630a9b7f126ffb83cee4a1c4fe5134190cabAmith Yamasani lp.height = LayoutParams.WRAP_CONTENT; 3052bbdd77ab20788e901a410f299edef028b66bb6eAmith Yamasani window.setAttributes(lp); 306284e630a9b7f126ffb83cee4a1c4fe5134190cabAmith Yamasani window.addFlags(LayoutParams.FLAG_NOT_FOCUSABLE | LayoutParams.FLAG_NOT_TOUCH_MODAL 307284e630a9b7f126ffb83cee4a1c4fe5134190cabAmith Yamasani | LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH); 3082bbdd77ab20788e901a410f299edef028b66bb6eAmith Yamasani 3099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mToneGenerators = new ToneGenerator[AudioSystem.getNumStreamTypes()]; 310c2346134bb519a54d50655cbef940fc3fdec60a9Jeff Brown mVibrator = (Vibrator)context.getSystemService(Context.VIBRATOR_SERVICE); 3112bbdd77ab20788e901a410f299edef028b66bb6eAmith Yamasani 31271def77a2811ce99ee50f09bc933ff380ce85055Amith Yamasani mVoiceCapable = context.getResources().getBoolean(R.bool.config_voice_capable); 3138dc1dabd254249b7ddb8743e88fdb96580ffc585Mike Lockwood mShowCombinedVolumes = !mVoiceCapable && !useMasterVolume; 31442722bfa136f5616872a2c4e199813e804621c81Amith Yamasani // If we don't want to show multiple volumes, hide the settings button and divider 31542722bfa136f5616872a2c4e199813e804621c81Amith Yamasani if (!mShowCombinedVolumes) { 31642722bfa136f5616872a2c4e199813e804621c81Amith Yamasani mMoreButton.setVisibility(View.GONE); 31742722bfa136f5616872a2c4e199813e804621c81Amith Yamasani mDivider.setVisibility(View.GONE); 31842722bfa136f5616872a2c4e199813e804621c81Amith Yamasani } else { 31942722bfa136f5616872a2c4e199813e804621c81Amith Yamasani mMoreButton.setOnClickListener(this); 32042722bfa136f5616872a2c4e199813e804621c81Amith Yamasani } 32142722bfa136f5616872a2c4e199813e804621c81Amith Yamasani 322c4b78d206ffcdccac01e3436a4a3462bef9672edChristopher Tate boolean masterVolumeOnly = context.getResources().getBoolean( 323c4b78d206ffcdccac01e3436a4a3462bef9672edChristopher Tate com.android.internal.R.bool.config_useMasterVolume); 324c4b78d206ffcdccac01e3436a4a3462bef9672edChristopher Tate boolean masterVolumeKeySounds = mContext.getResources().getBoolean( 325c4b78d206ffcdccac01e3436a4a3462bef9672edChristopher Tate com.android.internal.R.bool.config_useVolumeKeySounds); 326c4b78d206ffcdccac01e3436a4a3462bef9672edChristopher Tate 327c4b78d206ffcdccac01e3436a4a3462bef9672edChristopher Tate mPlayMasterStreamTones = masterVolumeOnly && masterVolumeKeySounds; 328c4b78d206ffcdccac01e3436a4a3462bef9672edChristopher Tate 3292bbdd77ab20788e901a410f299edef028b66bb6eAmith Yamasani listenToRingerMode(); 3302bbdd77ab20788e901a410f299edef028b66bb6eAmith Yamasani } 3312bbdd77ab20788e901a410f299edef028b66bb6eAmith Yamasani 3322bbdd77ab20788e901a410f299edef028b66bb6eAmith Yamasani private void listenToRingerMode() { 3332bbdd77ab20788e901a410f299edef028b66bb6eAmith Yamasani final IntentFilter filter = new IntentFilter(); 3342bbdd77ab20788e901a410f299edef028b66bb6eAmith Yamasani filter.addAction(AudioManager.RINGER_MODE_CHANGED_ACTION); 3352bbdd77ab20788e901a410f299edef028b66bb6eAmith Yamasani mContext.registerReceiver(new BroadcastReceiver() { 3362bbdd77ab20788e901a410f299edef028b66bb6eAmith Yamasani 3372bbdd77ab20788e901a410f299edef028b66bb6eAmith Yamasani public void onReceive(Context context, Intent intent) { 3382bbdd77ab20788e901a410f299edef028b66bb6eAmith Yamasani final String action = intent.getAction(); 3392bbdd77ab20788e901a410f299edef028b66bb6eAmith Yamasani 3402bbdd77ab20788e901a410f299edef028b66bb6eAmith Yamasani if (AudioManager.RINGER_MODE_CHANGED_ACTION.equals(action)) { 3412bbdd77ab20788e901a410f299edef028b66bb6eAmith Yamasani removeMessages(MSG_RINGER_MODE_CHANGED); 3422bbdd77ab20788e901a410f299edef028b66bb6eAmith Yamasani sendMessage(obtainMessage(MSG_RINGER_MODE_CHANGED)); 3432bbdd77ab20788e901a410f299edef028b66bb6eAmith Yamasani } 3442bbdd77ab20788e901a410f299edef028b66bb6eAmith Yamasani } 3452bbdd77ab20788e901a410f299edef028b66bb6eAmith Yamasani }, filter); 3462bbdd77ab20788e901a410f299edef028b66bb6eAmith Yamasani } 3472bbdd77ab20788e901a410f299edef028b66bb6eAmith Yamasani 3482bbdd77ab20788e901a410f299edef028b66bb6eAmith Yamasani private boolean isMuted(int streamType) { 3498dc1dabd254249b7ddb8743e88fdb96580ffc585Mike Lockwood if (streamType == STREAM_MASTER) { 3508c78752f2bf786ca3e6f45b9dc6955d3b4bba59cEric Laurent return mAudioManager.isMasterMute(); 3513114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi } else if (streamType == AudioService.STREAM_REMOTE_MUSIC) { 3523114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi return (mAudioService.getRemoteStreamVolume() <= 0); 3538dc1dabd254249b7ddb8743e88fdb96580ffc585Mike Lockwood } else { 3548c78752f2bf786ca3e6f45b9dc6955d3b4bba59cEric Laurent return mAudioManager.isStreamMute(streamType); 3558dc1dabd254249b7ddb8743e88fdb96580ffc585Mike Lockwood } 3568dc1dabd254249b7ddb8743e88fdb96580ffc585Mike Lockwood } 3578dc1dabd254249b7ddb8743e88fdb96580ffc585Mike Lockwood 3588dc1dabd254249b7ddb8743e88fdb96580ffc585Mike Lockwood private int getStreamMaxVolume(int streamType) { 3598dc1dabd254249b7ddb8743e88fdb96580ffc585Mike Lockwood if (streamType == STREAM_MASTER) { 3608c78752f2bf786ca3e6f45b9dc6955d3b4bba59cEric Laurent return mAudioManager.getMasterMaxVolume(); 3613114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi } else if (streamType == AudioService.STREAM_REMOTE_MUSIC) { 3623114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi return mAudioService.getRemoteStreamMaxVolume(); 3638dc1dabd254249b7ddb8743e88fdb96580ffc585Mike Lockwood } else { 3648c78752f2bf786ca3e6f45b9dc6955d3b4bba59cEric Laurent return mAudioManager.getStreamMaxVolume(streamType); 3658dc1dabd254249b7ddb8743e88fdb96580ffc585Mike Lockwood } 3668dc1dabd254249b7ddb8743e88fdb96580ffc585Mike Lockwood } 3678dc1dabd254249b7ddb8743e88fdb96580ffc585Mike Lockwood 3688dc1dabd254249b7ddb8743e88fdb96580ffc585Mike Lockwood private int getStreamVolume(int streamType) { 3698dc1dabd254249b7ddb8743e88fdb96580ffc585Mike Lockwood if (streamType == STREAM_MASTER) { 3708c78752f2bf786ca3e6f45b9dc6955d3b4bba59cEric Laurent return mAudioManager.getMasterVolume(); 3713114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi } else if (streamType == AudioService.STREAM_REMOTE_MUSIC) { 3723114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi return mAudioService.getRemoteStreamVolume(); 3738dc1dabd254249b7ddb8743e88fdb96580ffc585Mike Lockwood } else { 3748c78752f2bf786ca3e6f45b9dc6955d3b4bba59cEric Laurent return mAudioManager.getStreamVolume(streamType); 3758dc1dabd254249b7ddb8743e88fdb96580ffc585Mike Lockwood } 3768dc1dabd254249b7ddb8743e88fdb96580ffc585Mike Lockwood } 3778dc1dabd254249b7ddb8743e88fdb96580ffc585Mike Lockwood 3788dc1dabd254249b7ddb8743e88fdb96580ffc585Mike Lockwood private void setStreamVolume(int streamType, int index, int flags) { 3798dc1dabd254249b7ddb8743e88fdb96580ffc585Mike Lockwood if (streamType == STREAM_MASTER) { 3808c78752f2bf786ca3e6f45b9dc6955d3b4bba59cEric Laurent mAudioManager.setMasterVolume(index, flags); 3813114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi } else if (streamType == AudioService.STREAM_REMOTE_MUSIC) { 3823114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi mAudioService.setRemoteStreamVolume(index); 3838dc1dabd254249b7ddb8743e88fdb96580ffc585Mike Lockwood } else { 3848c78752f2bf786ca3e6f45b9dc6955d3b4bba59cEric Laurent mAudioManager.setStreamVolume(streamType, index, flags); 3858dc1dabd254249b7ddb8743e88fdb96580ffc585Mike Lockwood } 3862bbdd77ab20788e901a410f299edef028b66bb6eAmith Yamasani } 3872bbdd77ab20788e901a410f299edef028b66bb6eAmith Yamasani 3882bbdd77ab20788e901a410f299edef028b66bb6eAmith Yamasani private void createSliders() { 3892bbdd77ab20788e901a410f299edef028b66bb6eAmith Yamasani LayoutInflater inflater = (LayoutInflater) mContext 3902bbdd77ab20788e901a410f299edef028b66bb6eAmith Yamasani .getSystemService(Context.LAYOUT_INFLATER_SERVICE); 39171def77a2811ce99ee50f09bc933ff380ce85055Amith Yamasani mStreamControls = new HashMap<Integer, StreamControl>(STREAMS.length); 39242722bfa136f5616872a2c4e199813e804621c81Amith Yamasani Resources res = mContext.getResources(); 39371def77a2811ce99ee50f09bc933ff380ce85055Amith Yamasani for (int i = 0; i < STREAMS.length; i++) { 39471def77a2811ce99ee50f09bc933ff380ce85055Amith Yamasani StreamResources streamRes = STREAMS[i]; 39571def77a2811ce99ee50f09bc933ff380ce85055Amith Yamasani int streamType = streamRes.streamType; 39671def77a2811ce99ee50f09bc933ff380ce85055Amith Yamasani if (mVoiceCapable && streamRes == StreamResources.NotificationStream) { 39771def77a2811ce99ee50f09bc933ff380ce85055Amith Yamasani streamRes = StreamResources.RingerStream; 39871def77a2811ce99ee50f09bc933ff380ce85055Amith Yamasani } 3992bbdd77ab20788e901a410f299edef028b66bb6eAmith Yamasani StreamControl sc = new StreamControl(); 400d47a3aee7ad7d8ef66ee279ab64b64a0f7918e90Amith Yamasani sc.streamType = streamType; 4012bbdd77ab20788e901a410f299edef028b66bb6eAmith Yamasani sc.group = (ViewGroup) inflater.inflate(R.layout.volume_adjust_item, null); 4022bbdd77ab20788e901a410f299edef028b66bb6eAmith Yamasani sc.group.setTag(sc); 4032bbdd77ab20788e901a410f299edef028b66bb6eAmith Yamasani sc.icon = (ImageView) sc.group.findViewById(R.id.stream_icon); 4042bbdd77ab20788e901a410f299edef028b66bb6eAmith Yamasani sc.icon.setTag(sc); 40571def77a2811ce99ee50f09bc933ff380ce85055Amith Yamasani sc.icon.setContentDescription(res.getString(streamRes.descRes)); 40671def77a2811ce99ee50f09bc933ff380ce85055Amith Yamasani sc.iconRes = streamRes.iconRes; 40771def77a2811ce99ee50f09bc933ff380ce85055Amith Yamasani sc.iconMuteRes = streamRes.iconMuteRes; 4082bbdd77ab20788e901a410f299edef028b66bb6eAmith Yamasani sc.icon.setImageResource(sc.iconRes); 4092bbdd77ab20788e901a410f299edef028b66bb6eAmith Yamasani sc.seekbarView = (SeekBar) sc.group.findViewById(R.id.seekbar); 410d47a3aee7ad7d8ef66ee279ab64b64a0f7918e90Amith Yamasani int plusOne = (streamType == AudioSystem.STREAM_BLUETOOTH_SCO || 411d47a3aee7ad7d8ef66ee279ab64b64a0f7918e90Amith Yamasani streamType == AudioSystem.STREAM_VOICE_CALL) ? 1 : 0; 4128dc1dabd254249b7ddb8743e88fdb96580ffc585Mike Lockwood sc.seekbarView.setMax(getStreamMaxVolume(streamType) + plusOne); 4132bbdd77ab20788e901a410f299edef028b66bb6eAmith Yamasani sc.seekbarView.setOnSeekBarChangeListener(this); 4142bbdd77ab20788e901a410f299edef028b66bb6eAmith Yamasani sc.seekbarView.setTag(sc); 415d47a3aee7ad7d8ef66ee279ab64b64a0f7918e90Amith Yamasani mStreamControls.put(streamType, sc); 4162bbdd77ab20788e901a410f299edef028b66bb6eAmith Yamasani } 4172bbdd77ab20788e901a410f299edef028b66bb6eAmith Yamasani } 4182bbdd77ab20788e901a410f299edef028b66bb6eAmith Yamasani 4192bbdd77ab20788e901a410f299edef028b66bb6eAmith Yamasani private void reorderSliders(int activeStreamType) { 4202bbdd77ab20788e901a410f299edef028b66bb6eAmith Yamasani mSliderGroup.removeAllViews(); 4212bbdd77ab20788e901a410f299edef028b66bb6eAmith Yamasani 4222bbdd77ab20788e901a410f299edef028b66bb6eAmith Yamasani StreamControl active = mStreamControls.get(activeStreamType); 4232bbdd77ab20788e901a410f299edef028b66bb6eAmith Yamasani if (active == null) { 4242bbdd77ab20788e901a410f299edef028b66bb6eAmith Yamasani Log.e("VolumePanel", "Missing stream type! - " + activeStreamType); 4252bbdd77ab20788e901a410f299edef028b66bb6eAmith Yamasani mActiveStreamType = -1; 4262bbdd77ab20788e901a410f299edef028b66bb6eAmith Yamasani } else { 4272bbdd77ab20788e901a410f299edef028b66bb6eAmith Yamasani mSliderGroup.addView(active.group); 4282bbdd77ab20788e901a410f299edef028b66bb6eAmith Yamasani mActiveStreamType = activeStreamType; 4292bbdd77ab20788e901a410f299edef028b66bb6eAmith Yamasani active.group.setVisibility(View.VISIBLE); 4302bbdd77ab20788e901a410f299edef028b66bb6eAmith Yamasani updateSlider(active); 4312bbdd77ab20788e901a410f299edef028b66bb6eAmith Yamasani } 4322bbdd77ab20788e901a410f299edef028b66bb6eAmith Yamasani 43342722bfa136f5616872a2c4e199813e804621c81Amith Yamasani addOtherVolumes(); 43442722bfa136f5616872a2c4e199813e804621c81Amith Yamasani } 43542722bfa136f5616872a2c4e199813e804621c81Amith Yamasani 43642722bfa136f5616872a2c4e199813e804621c81Amith Yamasani private void addOtherVolumes() { 43742722bfa136f5616872a2c4e199813e804621c81Amith Yamasani if (!mShowCombinedVolumes) return; 43842722bfa136f5616872a2c4e199813e804621c81Amith Yamasani 43971def77a2811ce99ee50f09bc933ff380ce85055Amith Yamasani for (int i = 0; i < STREAMS.length; i++) { 4402bbdd77ab20788e901a410f299edef028b66bb6eAmith Yamasani // Skip the phone specific ones and the active one 44171def77a2811ce99ee50f09bc933ff380ce85055Amith Yamasani final int streamType = STREAMS[i].streamType; 44271def77a2811ce99ee50f09bc933ff380ce85055Amith Yamasani if (!STREAMS[i].show || streamType == mActiveStreamType) { 4432bbdd77ab20788e901a410f299edef028b66bb6eAmith Yamasani continue; 4442bbdd77ab20788e901a410f299edef028b66bb6eAmith Yamasani } 4452bbdd77ab20788e901a410f299edef028b66bb6eAmith Yamasani StreamControl sc = mStreamControls.get(streamType); 4462bbdd77ab20788e901a410f299edef028b66bb6eAmith Yamasani mSliderGroup.addView(sc.group); 4472bbdd77ab20788e901a410f299edef028b66bb6eAmith Yamasani updateSlider(sc); 4482bbdd77ab20788e901a410f299edef028b66bb6eAmith Yamasani } 4492bbdd77ab20788e901a410f299edef028b66bb6eAmith Yamasani } 4502bbdd77ab20788e901a410f299edef028b66bb6eAmith Yamasani 4512bbdd77ab20788e901a410f299edef028b66bb6eAmith Yamasani /** Update the mute and progress state of a slider */ 4522bbdd77ab20788e901a410f299edef028b66bb6eAmith Yamasani private void updateSlider(StreamControl sc) { 4538c78752f2bf786ca3e6f45b9dc6955d3b4bba59cEric Laurent sc.seekbarView.setProgress(getStreamVolume(sc.streamType)); 4542bbdd77ab20788e901a410f299edef028b66bb6eAmith Yamasani final boolean muted = isMuted(sc.streamType); 4552bbdd77ab20788e901a410f299edef028b66bb6eAmith Yamasani sc.icon.setImageResource(muted ? sc.iconMuteRes : sc.iconRes); 4568c78752f2bf786ca3e6f45b9dc6955d3b4bba59cEric Laurent if (sc.streamType == AudioManager.STREAM_RING && 4578c78752f2bf786ca3e6f45b9dc6955d3b4bba59cEric Laurent mAudioManager.getRingerMode() == AudioManager.RINGER_MODE_VIBRATE) { 458c696a53d1fe4d61373c5dc64dd057d322da90c8fAmith Yamasani sc.icon.setImageResource(R.drawable.ic_audio_ring_notif_vibrate); 459c696a53d1fe4d61373c5dc64dd057d322da90c8fAmith Yamasani } 4603114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi if (sc.streamType == AudioService.STREAM_REMOTE_MUSIC) { 4613114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi // never disable touch interactions for remote playback, the muting is not tied to 4623114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi // the state of the phone. 4633114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi sc.seekbarView.setEnabled(true); 4643114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi } else if (sc.streamType != mAudioManager.getMasterStreamType() && muted) { 4658c78752f2bf786ca3e6f45b9dc6955d3b4bba59cEric Laurent sc.seekbarView.setEnabled(false); 4668c78752f2bf786ca3e6f45b9dc6955d3b4bba59cEric Laurent } else { 4678c78752f2bf786ca3e6f45b9dc6955d3b4bba59cEric Laurent sc.seekbarView.setEnabled(true); 4688c78752f2bf786ca3e6f45b9dc6955d3b4bba59cEric Laurent } 4692bbdd77ab20788e901a410f299edef028b66bb6eAmith Yamasani } 4702bbdd77ab20788e901a410f299edef028b66bb6eAmith Yamasani 4712bbdd77ab20788e901a410f299edef028b66bb6eAmith Yamasani private boolean isExpanded() { 4722bbdd77ab20788e901a410f299edef028b66bb6eAmith Yamasani return mMoreButton.getVisibility() != View.VISIBLE; 4732bbdd77ab20788e901a410f299edef028b66bb6eAmith Yamasani } 4742bbdd77ab20788e901a410f299edef028b66bb6eAmith Yamasani 4752bbdd77ab20788e901a410f299edef028b66bb6eAmith Yamasani private void expand() { 4762bbdd77ab20788e901a410f299edef028b66bb6eAmith Yamasani final int count = mSliderGroup.getChildCount(); 4772bbdd77ab20788e901a410f299edef028b66bb6eAmith Yamasani for (int i = 0; i < count; i++) { 4782bbdd77ab20788e901a410f299edef028b66bb6eAmith Yamasani mSliderGroup.getChildAt(i).setVisibility(View.VISIBLE); 4792bbdd77ab20788e901a410f299edef028b66bb6eAmith Yamasani } 4802bbdd77ab20788e901a410f299edef028b66bb6eAmith Yamasani mMoreButton.setVisibility(View.INVISIBLE); 4812bbdd77ab20788e901a410f299edef028b66bb6eAmith Yamasani mDivider.setVisibility(View.INVISIBLE); 4822bbdd77ab20788e901a410f299edef028b66bb6eAmith Yamasani } 4832bbdd77ab20788e901a410f299edef028b66bb6eAmith Yamasani 4842bbdd77ab20788e901a410f299edef028b66bb6eAmith Yamasani private void collapse() { 4852bbdd77ab20788e901a410f299edef028b66bb6eAmith Yamasani mMoreButton.setVisibility(View.VISIBLE); 4862bbdd77ab20788e901a410f299edef028b66bb6eAmith Yamasani mDivider.setVisibility(View.VISIBLE); 4872bbdd77ab20788e901a410f299edef028b66bb6eAmith Yamasani final int count = mSliderGroup.getChildCount(); 4882bbdd77ab20788e901a410f299edef028b66bb6eAmith Yamasani for (int i = 1; i < count; i++) { 4892bbdd77ab20788e901a410f299edef028b66bb6eAmith Yamasani mSliderGroup.getChildAt(i).setVisibility(View.GONE); 4902bbdd77ab20788e901a410f299edef028b66bb6eAmith Yamasani } 4912bbdd77ab20788e901a410f299edef028b66bb6eAmith Yamasani } 4922bbdd77ab20788e901a410f299edef028b66bb6eAmith Yamasani 4932bbdd77ab20788e901a410f299edef028b66bb6eAmith Yamasani private void updateStates() { 4942bbdd77ab20788e901a410f299edef028b66bb6eAmith Yamasani final int count = mSliderGroup.getChildCount(); 4952bbdd77ab20788e901a410f299edef028b66bb6eAmith Yamasani for (int i = 0; i < count; i++) { 4962bbdd77ab20788e901a410f299edef028b66bb6eAmith Yamasani StreamControl sc = (StreamControl) mSliderGroup.getChildAt(i).getTag(); 4972bbdd77ab20788e901a410f299edef028b66bb6eAmith Yamasani updateSlider(sc); 4982bbdd77ab20788e901a410f299edef028b66bb6eAmith Yamasani } 4999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void postVolumeChanged(int streamType, int flags) { 5029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (hasMessages(MSG_VOLUME_CHANGED)) return; 503a654986978c870ed33af2ad696cd6e61d9fed489Amith Yamasani synchronized (this) { 504a654986978c870ed33af2ad696cd6e61d9fed489Amith Yamasani if (mStreamControls == null) { 505a654986978c870ed33af2ad696cd6e61d9fed489Amith Yamasani createSliders(); 506a654986978c870ed33af2ad696cd6e61d9fed489Amith Yamasani } 5072bbdd77ab20788e901a410f299edef028b66bb6eAmith Yamasani } 5089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project removeMessages(MSG_FREE_RESOURCES); 5099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project obtainMessage(MSG_VOLUME_CHANGED, streamType, flags).sendToTarget(); 5109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5123114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi public void postRemoteVolumeChanged(int streamType, int flags) { 5133114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi if (hasMessages(MSG_REMOTE_VOLUME_CHANGED)) return; 5143114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi synchronized (this) { 5153114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi if (mStreamControls == null) { 5163114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi createSliders(); 5173114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi } 5183114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi } 5193114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi removeMessages(MSG_FREE_RESOURCES); 5203114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi obtainMessage(MSG_REMOTE_VOLUME_CHANGED, streamType, flags).sendToTarget(); 5213114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi } 5223114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi 5233114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi public void postRemoteSliderVisibility(boolean visible) { 5243114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi obtainMessage(MSG_SLIDER_VISIBILITY_CHANGED, 5253114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi AudioService.STREAM_REMOTE_MUSIC, visible ? 1 : 0).sendToTarget(); 5263114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi } 5273114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi 5283114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi /** 5293114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi * Called by AudioService when it has received new remote playback information that 5303114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi * would affect the VolumePanel display (mainly volumes). The difference with 5313114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi * {@link #postRemoteVolumeChanged(int, int)} is that the handling of the posted message 5323114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi * (MSG_REMOTE_VOLUME_UPDATE_IF_SHOWN) will only update the volume slider if it is being 5333114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi * displayed. 5343114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi * This special code path is due to the fact that remote volume updates arrive to AudioService 5353114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi * asynchronously. So after AudioService has sent the volume update (which should be treated 5363114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi * as a request to update the volume), the application will likely set a new volume. If the UI 5373114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi * is still up, we need to refresh the display to show this new value. 5383114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi */ 5393114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi public void postHasNewRemotePlaybackInfo() { 5403114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi if (hasMessages(MSG_REMOTE_VOLUME_UPDATE_IF_SHOWN)) return; 5413114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi // don't create or prevent resources to be freed, if they disappear, this update came too 5423114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi // late and shouldn't warrant the panel to be displayed longer 5433114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi obtainMessage(MSG_REMOTE_VOLUME_UPDATE_IF_SHOWN).sendToTarget(); 5443114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi } 5453114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi 5468dc1dabd254249b7ddb8743e88fdb96580ffc585Mike Lockwood public void postMasterVolumeChanged(int flags) { 5478dc1dabd254249b7ddb8743e88fdb96580ffc585Mike Lockwood postVolumeChanged(STREAM_MASTER, flags); 5488dc1dabd254249b7ddb8743e88fdb96580ffc585Mike Lockwood } 5498dc1dabd254249b7ddb8743e88fdb96580ffc585Mike Lockwood 550ce952c8e13c535bedde77bcdb94dfcc7508475aaMike Lockwood public void postMuteChanged(int streamType, int flags) { 551ce952c8e13c535bedde77bcdb94dfcc7508475aaMike Lockwood if (hasMessages(MSG_VOLUME_CHANGED)) return; 552a654986978c870ed33af2ad696cd6e61d9fed489Amith Yamasani synchronized (this) { 553a654986978c870ed33af2ad696cd6e61d9fed489Amith Yamasani if (mStreamControls == null) { 554a654986978c870ed33af2ad696cd6e61d9fed489Amith Yamasani createSliders(); 555a654986978c870ed33af2ad696cd6e61d9fed489Amith Yamasani } 556ce952c8e13c535bedde77bcdb94dfcc7508475aaMike Lockwood } 557ce952c8e13c535bedde77bcdb94dfcc7508475aaMike Lockwood removeMessages(MSG_FREE_RESOURCES); 558ce952c8e13c535bedde77bcdb94dfcc7508475aaMike Lockwood obtainMessage(MSG_MUTE_CHANGED, streamType, flags).sendToTarget(); 559ce952c8e13c535bedde77bcdb94dfcc7508475aaMike Lockwood } 560ce952c8e13c535bedde77bcdb94dfcc7508475aaMike Lockwood 561ce952c8e13c535bedde77bcdb94dfcc7508475aaMike Lockwood public void postMasterMuteChanged(int flags) { 562ce952c8e13c535bedde77bcdb94dfcc7508475aaMike Lockwood postMuteChanged(STREAM_MASTER, flags); 563ce952c8e13c535bedde77bcdb94dfcc7508475aaMike Lockwood } 564ce952c8e13c535bedde77bcdb94dfcc7508475aaMike Lockwood 565c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent public void postDisplaySafeVolumeWarning() { 5660516a9ecb0d4d76acd2f1c4c2521f44c696789a8Eric Laurent if (hasMessages(MSG_DISPLAY_SAFE_VOLUME_WARNING)) return; 567c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent obtainMessage(MSG_DISPLAY_SAFE_VOLUME_WARNING, 0, 0).sendToTarget(); 568c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent } 569c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent 5709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 5719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Override this if you have other work to do when the volume changes (for 5729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * example, vibrating, playing a sound, etc.). Make sure to call through to 5739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * the superclass implementation. 5749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 5759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project protected void onVolumeChanged(int streamType, int flags) { 5769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (LOGD) Log.d(TAG, "onVolumeChanged(streamType: " + streamType + ", flags: " + flags + ")"); 5789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if ((flags & AudioManager.FLAG_SHOW_UI) != 0) { 580a654986978c870ed33af2ad696cd6e61d9fed489Amith Yamasani synchronized (this) { 581a654986978c870ed33af2ad696cd6e61d9fed489Amith Yamasani if (mActiveStreamType != streamType) { 582a654986978c870ed33af2ad696cd6e61d9fed489Amith Yamasani reorderSliders(streamType); 583a654986978c870ed33af2ad696cd6e61d9fed489Amith Yamasani } 584a654986978c870ed33af2ad696cd6e61d9fed489Amith Yamasani onShowVolumeChanged(streamType, flags); 585e3361b8d0889de6489eb61c6d9ca05885cf4bf31Amith Yamasani } 5869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 58869f593ccb7414ee98991b1da1a4bfbd9951e3570Marco Nelissen if ((flags & AudioManager.FLAG_PLAY_SOUND) != 0 && ! mRingIsSilent) { 5899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project removeMessages(MSG_PLAY_SOUND); 5909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sendMessageDelayed(obtainMessage(MSG_PLAY_SOUND, streamType, flags), PLAY_SOUND_DELAY); 5919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if ((flags & AudioManager.FLAG_REMOVE_SOUND_AND_VIBRATE) != 0) { 5949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project removeMessages(MSG_PLAY_SOUND); 5959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project removeMessages(MSG_VIBRATE); 5969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project onStopSounds(); 5979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project removeMessages(MSG_FREE_RESOURCES); 6009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sendMessageDelayed(obtainMessage(MSG_FREE_RESOURCES), FREE_DELAY); 6012bbdd77ab20788e901a410f299edef028b66bb6eAmith Yamasani 6022bbdd77ab20788e901a410f299edef028b66bb6eAmith Yamasani resetTimeout(); 6039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 605ce952c8e13c535bedde77bcdb94dfcc7508475aaMike Lockwood protected void onMuteChanged(int streamType, int flags) { 606ce952c8e13c535bedde77bcdb94dfcc7508475aaMike Lockwood 607ce952c8e13c535bedde77bcdb94dfcc7508475aaMike Lockwood if (LOGD) Log.d(TAG, "onMuteChanged(streamType: " + streamType + ", flags: " + flags + ")"); 608ce952c8e13c535bedde77bcdb94dfcc7508475aaMike Lockwood 609ce952c8e13c535bedde77bcdb94dfcc7508475aaMike Lockwood StreamControl sc = mStreamControls.get(streamType); 610ce952c8e13c535bedde77bcdb94dfcc7508475aaMike Lockwood if (sc != null) { 611ce952c8e13c535bedde77bcdb94dfcc7508475aaMike Lockwood sc.icon.setImageResource(isMuted(sc.streamType) ? sc.iconMuteRes : sc.iconRes); 612ce952c8e13c535bedde77bcdb94dfcc7508475aaMike Lockwood } 613ce952c8e13c535bedde77bcdb94dfcc7508475aaMike Lockwood 614ce952c8e13c535bedde77bcdb94dfcc7508475aaMike Lockwood onVolumeChanged(streamType, flags); 615ce952c8e13c535bedde77bcdb94dfcc7508475aaMike Lockwood } 616ce952c8e13c535bedde77bcdb94dfcc7508475aaMike Lockwood 6179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project protected void onShowVolumeChanged(int streamType, int flags) { 6188c78752f2bf786ca3e6f45b9dc6955d3b4bba59cEric Laurent int index = getStreamVolume(streamType); 619d72d51c77a43d75c098afb55c3939210739510f9Eric Laurent 62069f593ccb7414ee98991b1da1a4bfbd9951e3570Marco Nelissen mRingIsSilent = false; 6219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (LOGD) { 6239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Log.d(TAG, "onShowVolumeChanged(streamType: " + streamType 6249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project + ", flags: " + flags + "), index: " + index); 6259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // get max volume for progress bar 6282bbdd77ab20788e901a410f299edef028b66bb6eAmith Yamasani 6298dc1dabd254249b7ddb8743e88fdb96580ffc585Mike Lockwood int max = getStreamMaxVolume(streamType); 6309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project switch (streamType) { 6329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case AudioManager.STREAM_RING: { 6342bbdd77ab20788e901a410f299edef028b66bb6eAmith Yamasani// setRingerIcon(); 63569f593ccb7414ee98991b1da1a4bfbd9951e3570Marco Nelissen Uri ringuri = RingtoneManager.getActualDefaultRingtoneUri( 63669f593ccb7414ee98991b1da1a4bfbd9951e3570Marco Nelissen mContext, RingtoneManager.TYPE_RINGTONE); 63769f593ccb7414ee98991b1da1a4bfbd9951e3570Marco Nelissen if (ringuri == null) { 63869f593ccb7414ee98991b1da1a4bfbd9951e3570Marco Nelissen mRingIsSilent = true; 63969f593ccb7414ee98991b1da1a4bfbd9951e3570Marco Nelissen } 6409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 6419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case AudioManager.STREAM_MUSIC: { 6442bbdd77ab20788e901a410f299edef028b66bb6eAmith Yamasani // Special case for when Bluetooth is active for music 6458b4b97a14ad9b5b982d8fe92755efabec8ad0076Glenn Kasten if ((mAudioManager.getDevicesForStream(AudioManager.STREAM_MUSIC) & 6468b4b97a14ad9b5b982d8fe92755efabec8ad0076Glenn Kasten (AudioManager.DEVICE_OUT_BLUETOOTH_A2DP | 6478b4b97a14ad9b5b982d8fe92755efabec8ad0076Glenn Kasten AudioManager.DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES | 6488b4b97a14ad9b5b982d8fe92755efabec8ad0076Glenn Kasten AudioManager.DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER)) != 0) { 6492bbdd77ab20788e901a410f299edef028b66bb6eAmith Yamasani setMusicIcon(R.drawable.ic_audio_bt, R.drawable.ic_audio_bt_mute); 6509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 6512bbdd77ab20788e901a410f299edef028b66bb6eAmith Yamasani setMusicIcon(R.drawable.ic_audio_vol, R.drawable.ic_audio_vol_mute); 6529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 6549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case AudioManager.STREAM_VOICE_CALL: { 6579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* 6589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * For in-call voice call volume, there is no inaudible volume. 6599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Rescale the UI control so the progress bar doesn't go all 6609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * the way to zero and don't show the mute icon. 6619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 6629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project index++; 6639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project max++; 6649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 6659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case AudioManager.STREAM_ALARM: { 6689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 6699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case AudioManager.STREAM_NOTIFICATION: { 67269f593ccb7414ee98991b1da1a4bfbd9951e3570Marco Nelissen Uri ringuri = RingtoneManager.getActualDefaultRingtoneUri( 67369f593ccb7414ee98991b1da1a4bfbd9951e3570Marco Nelissen mContext, RingtoneManager.TYPE_NOTIFICATION); 67469f593ccb7414ee98991b1da1a4bfbd9951e3570Marco Nelissen if (ringuri == null) { 67569f593ccb7414ee98991b1da1a4bfbd9951e3570Marco Nelissen mRingIsSilent = true; 67669f593ccb7414ee98991b1da1a4bfbd9951e3570Marco Nelissen } 6779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 6789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case AudioManager.STREAM_BLUETOOTH_SCO: { 6819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* 6829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * For in-call voice call volume, there is no inaudible volume. 6839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Rescale the UI control so the progress bar doesn't go all 6849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * the way to zero and don't show the mute icon. 6859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 6869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project index++; 6879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project max++; 6889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 6899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6903114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi 6913114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi case AudioService.STREAM_REMOTE_MUSIC: { 6923114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi if (LOGD) { Log.d(TAG, "showing remote volume "+index+" over "+ max); } 6933114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi break; 6943114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi } 6959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6972bbdd77ab20788e901a410f299edef028b66bb6eAmith Yamasani StreamControl sc = mStreamControls.get(streamType); 6982bbdd77ab20788e901a410f299edef028b66bb6eAmith Yamasani if (sc != null) { 699d47a3aee7ad7d8ef66ee279ab64b64a0f7918e90Amith Yamasani if (sc.seekbarView.getMax() != max) { 700d47a3aee7ad7d8ef66ee279ab64b64a0f7918e90Amith Yamasani sc.seekbarView.setMax(max); 701d47a3aee7ad7d8ef66ee279ab64b64a0f7918e90Amith Yamasani } 7024bbcc6549738f3d69831b2bd9eb4accec3e9920eEric Laurent 7032bbdd77ab20788e901a410f299edef028b66bb6eAmith Yamasani sc.seekbarView.setProgress(index); 7044bbcc6549738f3d69831b2bd9eb4accec3e9920eEric Laurent if (((flags & AudioManager.FLAG_FIXED_VOLUME) != 0) || 7054bbcc6549738f3d69831b2bd9eb4accec3e9920eEric Laurent (streamType != mAudioManager.getMasterStreamType() && 7064bbcc6549738f3d69831b2bd9eb4accec3e9920eEric Laurent streamType != AudioService.STREAM_REMOTE_MUSIC && 7074bbcc6549738f3d69831b2bd9eb4accec3e9920eEric Laurent isMuted(streamType))) { 7088c78752f2bf786ca3e6f45b9dc6955d3b4bba59cEric Laurent sc.seekbarView.setEnabled(false); 7098c78752f2bf786ca3e6f45b9dc6955d3b4bba59cEric Laurent } else { 7108c78752f2bf786ca3e6f45b9dc6955d3b4bba59cEric Laurent sc.seekbarView.setEnabled(true); 7118c78752f2bf786ca3e6f45b9dc6955d3b4bba59cEric Laurent } 7129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7142bbdd77ab20788e901a410f299edef028b66bb6eAmith Yamasani if (!mDialog.isShowing()) { 7153114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi int stream = (streamType == AudioService.STREAM_REMOTE_MUSIC) ? -1 : streamType; 7163114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi // when the stream is for remote playback, use -1 to reset the stream type evaluation 7173114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi mAudioManager.forceVolumeControlStream(stream); 7182bbdd77ab20788e901a410f299edef028b66bb6eAmith Yamasani mDialog.setContentView(mView); 7192bbdd77ab20788e901a410f299edef028b66bb6eAmith Yamasani // Showing dialog - use collapsed state 72042722bfa136f5616872a2c4e199813e804621c81Amith Yamasani if (mShowCombinedVolumes) { 72142722bfa136f5616872a2c4e199813e804621c81Amith Yamasani collapse(); 72242722bfa136f5616872a2c4e199813e804621c81Amith Yamasani } 7232bbdd77ab20788e901a410f299edef028b66bb6eAmith Yamasani mDialog.show(); 7249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Do a little vibrate if applicable (only when going into vibrate mode) 7273114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi if ((streamType != AudioService.STREAM_REMOTE_MUSIC) && 7283114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi ((flags & AudioManager.FLAG_VIBRATE) != 0) && 7299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mAudioService.isStreamAffectedByRingerMode(streamType) && 7308c78752f2bf786ca3e6f45b9dc6955d3b4bba59cEric Laurent mAudioManager.getRingerMode() == AudioManager.RINGER_MODE_VIBRATE) { 7319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sendMessageDelayed(obtainMessage(MSG_VIBRATE), VIBRATE_DELAY); 7329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project protected void onPlaySound(int streamType, int flags) { 7369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (hasMessages(MSG_STOP_SOUNDS)) { 7389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project removeMessages(MSG_STOP_SOUNDS); 7399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Force stop right now 7409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project onStopSounds(); 7419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project synchronized (this) { 7449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ToneGenerator toneGen = getOrCreateToneGenerator(streamType); 745733a42b24b91ce2881e2e4457a1ee06f12bb127aEric Laurent if (toneGen != null) { 746733a42b24b91ce2881e2e4457a1ee06f12bb127aEric Laurent toneGen.startTone(ToneGenerator.TONE_PROP_BEEP); 747733a42b24b91ce2881e2e4457a1ee06f12bb127aEric Laurent sendMessageDelayed(obtainMessage(MSG_STOP_SOUNDS), BEEP_DURATION); 748733a42b24b91ce2881e2e4457a1ee06f12bb127aEric Laurent } 7499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project protected void onStopSounds() { 7539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project synchronized (this) { 7559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int numStreamTypes = AudioSystem.getNumStreamTypes(); 7569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = numStreamTypes - 1; i >= 0; i--) { 7579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ToneGenerator toneGen = mToneGenerators[i]; 7589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (toneGen != null) { 7599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project toneGen.stopTone(); 7609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project protected void onVibrate() { 7669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Make sure we ended up in vibrate ringer mode 7688c78752f2bf786ca3e6f45b9dc6955d3b4bba59cEric Laurent if (mAudioManager.getRingerMode() != AudioManager.RINGER_MODE_VIBRATE) { 7699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 7709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mVibrator.vibrate(VIBRATE_DURATION); 7739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7753114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi protected void onRemoteVolumeChanged(int streamType, int flags) { 7763114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi // streamType is the real stream type being affected, but for the UI sliders, we 7773114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi // refer to AudioService.STREAM_REMOTE_MUSIC. We still play the beeps on the real 7783114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi // stream type. 7793114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi if (LOGD) Log.d(TAG, "onRemoteVolumeChanged(stream:"+streamType+", flags: " + flags + ")"); 7803114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi 7813114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi if (((flags & AudioManager.FLAG_SHOW_UI) != 0) || mDialog.isShowing()) { 7823114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi synchronized (this) { 7833114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi if (mActiveStreamType != AudioService.STREAM_REMOTE_MUSIC) { 7843114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi reorderSliders(AudioService.STREAM_REMOTE_MUSIC); 7853114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi } 7863114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi onShowVolumeChanged(AudioService.STREAM_REMOTE_MUSIC, flags); 7873114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi } 7883114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi } else { 7893114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi if (LOGD) Log.d(TAG, "not calling onShowVolumeChanged(), no FLAG_SHOW_UI or no UI"); 7903114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi } 7913114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi 7923114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi if ((flags & AudioManager.FLAG_PLAY_SOUND) != 0 && ! mRingIsSilent) { 7933114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi removeMessages(MSG_PLAY_SOUND); 7943114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi sendMessageDelayed(obtainMessage(MSG_PLAY_SOUND, streamType, flags), PLAY_SOUND_DELAY); 7953114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi } 7963114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi 7973114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi if ((flags & AudioManager.FLAG_REMOVE_SOUND_AND_VIBRATE) != 0) { 7983114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi removeMessages(MSG_PLAY_SOUND); 7993114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi removeMessages(MSG_VIBRATE); 8003114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi onStopSounds(); 8013114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi } 8023114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi 8033114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi removeMessages(MSG_FREE_RESOURCES); 8043114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi sendMessageDelayed(obtainMessage(MSG_FREE_RESOURCES), FREE_DELAY); 8053114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi 8063114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi resetTimeout(); 8073114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi } 8083114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi 8093114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi protected void onRemoteVolumeUpdateIfShown() { 8103114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi if (LOGD) Log.d(TAG, "onRemoteVolumeUpdateIfShown()"); 8113114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi if (mDialog.isShowing() 8123114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi && (mActiveStreamType == AudioService.STREAM_REMOTE_MUSIC) 8133114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi && (mStreamControls != null)) { 8143114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi onShowVolumeChanged(AudioService.STREAM_REMOTE_MUSIC, 0); 8153114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi } 8163114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi } 8173114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi 8183114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi 8193114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi /** 8203114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi * Handler for MSG_SLIDER_VISIBILITY_CHANGED 8213114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi * Hide or show a slider 8223114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi * @param streamType can be a valid stream type value, or VolumePanel.STREAM_MASTER, 8233114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi * or AudioService.STREAM_REMOTE_MUSIC 8243114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi * @param visible 8253114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi */ 8263114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi synchronized protected void onSliderVisibilityChanged(int streamType, int visible) { 8273114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi if (LOGD) Log.d(TAG, "onSliderVisibilityChanged(stream="+streamType+", visi="+visible+")"); 8283114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi boolean isVisible = (visible == 1); 8293114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi for (int i = STREAMS.length - 1 ; i >= 0 ; i--) { 8303114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi StreamResources streamRes = STREAMS[i]; 8313114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi if (streamRes.streamType == streamType) { 8323114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi streamRes.show = isVisible; 8333114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi if (!isVisible && (mActiveStreamType == streamType)) { 8343114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi mActiveStreamType = -1; 8353114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi } 8363114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi break; 8373114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi } 8383114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi } 8393114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi } 8403114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi 841c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent protected void onDisplaySafeVolumeWarning() { 8420516a9ecb0d4d76acd2f1c4c2521f44c696789a8Eric Laurent synchronized (sConfirmSafeVolumeLock) { 8430516a9ecb0d4d76acd2f1c4c2521f44c696789a8Eric Laurent if (sConfirmSafeVolumeDialog != null) { 8440516a9ecb0d4d76acd2f1c4c2521f44c696789a8Eric Laurent return; 8450516a9ecb0d4d76acd2f1c4c2521f44c696789a8Eric Laurent } 8460516a9ecb0d4d76acd2f1c4c2521f44c696789a8Eric Laurent sConfirmSafeVolumeDialog = new AlertDialog.Builder(mContext) 8470516a9ecb0d4d76acd2f1c4c2521f44c696789a8Eric Laurent .setMessage(com.android.internal.R.string.safe_media_volume_warning) 8480516a9ecb0d4d76acd2f1c4c2521f44c696789a8Eric Laurent .setPositiveButton(com.android.internal.R.string.yes, 8490516a9ecb0d4d76acd2f1c4c2521f44c696789a8Eric Laurent new DialogInterface.OnClickListener() { 8500516a9ecb0d4d76acd2f1c4c2521f44c696789a8Eric Laurent public void onClick(DialogInterface dialog, int which) { 8510516a9ecb0d4d76acd2f1c4c2521f44c696789a8Eric Laurent mAudioService.disableSafeMediaVolume(); 8520516a9ecb0d4d76acd2f1c4c2521f44c696789a8Eric Laurent } 8530516a9ecb0d4d76acd2f1c4c2521f44c696789a8Eric Laurent }) 8540516a9ecb0d4d76acd2f1c4c2521f44c696789a8Eric Laurent .setNegativeButton(com.android.internal.R.string.no, null) 8550516a9ecb0d4d76acd2f1c4c2521f44c696789a8Eric Laurent .setIconAttribute(android.R.attr.alertDialogIcon) 8560516a9ecb0d4d76acd2f1c4c2521f44c696789a8Eric Laurent .create(); 8570516a9ecb0d4d76acd2f1c4c2521f44c696789a8Eric Laurent final WarningDialogReceiver warning = new WarningDialogReceiver(mContext, 8580516a9ecb0d4d76acd2f1c4c2521f44c696789a8Eric Laurent sConfirmSafeVolumeDialog); 8590516a9ecb0d4d76acd2f1c4c2521f44c696789a8Eric Laurent 8600516a9ecb0d4d76acd2f1c4c2521f44c696789a8Eric Laurent sConfirmSafeVolumeDialog.setOnDismissListener(warning); 8610516a9ecb0d4d76acd2f1c4c2521f44c696789a8Eric Laurent sConfirmSafeVolumeDialog.getWindow().setType( 8620516a9ecb0d4d76acd2f1c4c2521f44c696789a8Eric Laurent WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG); 8630516a9ecb0d4d76acd2f1c4c2521f44c696789a8Eric Laurent sConfirmSafeVolumeDialog.show(); 8640516a9ecb0d4d76acd2f1c4c2521f44c696789a8Eric Laurent } 865c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent } 866c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent 8679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 8689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Lock on this VolumePanel instance as long as you use the returned ToneGenerator. 8699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 8709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private ToneGenerator getOrCreateToneGenerator(int streamType) { 871c4b78d206ffcdccac01e3436a4a3462bef9672edChristopher Tate if (streamType == STREAM_MASTER) { 872c4b78d206ffcdccac01e3436a4a3462bef9672edChristopher Tate // For devices that use the master volume setting only but still want to 873c4b78d206ffcdccac01e3436a4a3462bef9672edChristopher Tate // play a volume-changed tone, direct the master volume pseudostream to 874c4b78d206ffcdccac01e3436a4a3462bef9672edChristopher Tate // the system stream's tone generator. 875c4b78d206ffcdccac01e3436a4a3462bef9672edChristopher Tate if (mPlayMasterStreamTones) { 876c4b78d206ffcdccac01e3436a4a3462bef9672edChristopher Tate streamType = AudioManager.STREAM_SYSTEM; 877c4b78d206ffcdccac01e3436a4a3462bef9672edChristopher Tate } else { 878c4b78d206ffcdccac01e3436a4a3462bef9672edChristopher Tate return null; 879c4b78d206ffcdccac01e3436a4a3462bef9672edChristopher Tate } 880c4b78d206ffcdccac01e3436a4a3462bef9672edChristopher Tate } 8819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project synchronized (this) { 8829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mToneGenerators[streamType] == null) { 883733a42b24b91ce2881e2e4457a1ee06f12bb127aEric Laurent try { 884733a42b24b91ce2881e2e4457a1ee06f12bb127aEric Laurent mToneGenerators[streamType] = new ToneGenerator(streamType, MAX_VOLUME); 885733a42b24b91ce2881e2e4457a1ee06f12bb127aEric Laurent } catch (RuntimeException e) { 886733a42b24b91ce2881e2e4457a1ee06f12bb127aEric Laurent if (LOGD) { 887733a42b24b91ce2881e2e4457a1ee06f12bb127aEric Laurent Log.d(TAG, "ToneGenerator constructor failed with " 888733a42b24b91ce2881e2e4457a1ee06f12bb127aEric Laurent + "RuntimeException: " + e); 889733a42b24b91ce2881e2e4457a1ee06f12bb127aEric Laurent } 890733a42b24b91ce2881e2e4457a1ee06f12bb127aEric Laurent } 8919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 892733a42b24b91ce2881e2e4457a1ee06f12bb127aEric Laurent return mToneGenerators[streamType]; 8939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 8982bbdd77ab20788e901a410f299edef028b66bb6eAmith Yamasani * Switch between icons because Bluetooth music is same as music volume, but with 8992bbdd77ab20788e901a410f299edef028b66bb6eAmith Yamasani * different icons. 9009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 9012bbdd77ab20788e901a410f299edef028b66bb6eAmith Yamasani private void setMusicIcon(int resId, int resMuteId) { 9022bbdd77ab20788e901a410f299edef028b66bb6eAmith Yamasani StreamControl sc = mStreamControls.get(AudioManager.STREAM_MUSIC); 9032bbdd77ab20788e901a410f299edef028b66bb6eAmith Yamasani if (sc != null) { 9042bbdd77ab20788e901a410f299edef028b66bb6eAmith Yamasani sc.iconRes = resId; 9052bbdd77ab20788e901a410f299edef028b66bb6eAmith Yamasani sc.iconMuteRes = resMuteId; 9062bbdd77ab20788e901a410f299edef028b66bb6eAmith Yamasani sc.icon.setImageResource(isMuted(sc.streamType) ? sc.iconMuteRes : sc.iconRes); 9079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project protected void onFreeResources() { 9119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project synchronized (this) { 9129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = mToneGenerators.length - 1; i >= 0; i--) { 9139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mToneGenerators[i] != null) { 9149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mToneGenerators[i].release(); 9159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mToneGenerators[i] = null; 9179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 9229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void handleMessage(Message msg) { 9239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project switch (msg.what) { 9249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case MSG_VOLUME_CHANGED: { 9269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project onVolumeChanged(msg.arg1, msg.arg2); 9279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 9289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 930ce952c8e13c535bedde77bcdb94dfcc7508475aaMike Lockwood case MSG_MUTE_CHANGED: { 931ce952c8e13c535bedde77bcdb94dfcc7508475aaMike Lockwood onMuteChanged(msg.arg1, msg.arg2); 932ce952c8e13c535bedde77bcdb94dfcc7508475aaMike Lockwood break; 933ce952c8e13c535bedde77bcdb94dfcc7508475aaMike Lockwood } 934ce952c8e13c535bedde77bcdb94dfcc7508475aaMike Lockwood 9359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case MSG_FREE_RESOURCES: { 9369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project onFreeResources(); 9379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 9389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case MSG_STOP_SOUNDS: { 9419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project onStopSounds(); 9429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 9439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case MSG_PLAY_SOUND: { 9469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project onPlaySound(msg.arg1, msg.arg2); 9479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 9489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case MSG_VIBRATE: { 9519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project onVibrate(); 9529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 9539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9552bbdd77ab20788e901a410f299edef028b66bb6eAmith Yamasani case MSG_TIMEOUT: { 9562bbdd77ab20788e901a410f299edef028b66bb6eAmith Yamasani if (mDialog.isShowing()) { 9572bbdd77ab20788e901a410f299edef028b66bb6eAmith Yamasani mDialog.dismiss(); 9582bbdd77ab20788e901a410f299edef028b66bb6eAmith Yamasani mActiveStreamType = -1; 9592bbdd77ab20788e901a410f299edef028b66bb6eAmith Yamasani } 9602bbdd77ab20788e901a410f299edef028b66bb6eAmith Yamasani break; 9612bbdd77ab20788e901a410f299edef028b66bb6eAmith Yamasani } 9622bbdd77ab20788e901a410f299edef028b66bb6eAmith Yamasani case MSG_RINGER_MODE_CHANGED: { 9632bbdd77ab20788e901a410f299edef028b66bb6eAmith Yamasani if (mDialog.isShowing()) { 9642bbdd77ab20788e901a410f299edef028b66bb6eAmith Yamasani updateStates(); 9652bbdd77ab20788e901a410f299edef028b66bb6eAmith Yamasani } 9662bbdd77ab20788e901a410f299edef028b66bb6eAmith Yamasani break; 9672bbdd77ab20788e901a410f299edef028b66bb6eAmith Yamasani } 9683114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi 9693114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi case MSG_REMOTE_VOLUME_CHANGED: { 9703114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi onRemoteVolumeChanged(msg.arg1, msg.arg2); 9713114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi break; 9723114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi } 9733114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi 9743114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi case MSG_REMOTE_VOLUME_UPDATE_IF_SHOWN: 9753114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi onRemoteVolumeUpdateIfShown(); 9763114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi break; 9773114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi 9783114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi case MSG_SLIDER_VISIBILITY_CHANGED: 9793114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi onSliderVisibilityChanged(msg.arg1, msg.arg2); 9803114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi break; 981c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent 982c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent case MSG_DISPLAY_SAFE_VOLUME_WARNING: 983c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent onDisplaySafeVolumeWarning(); 984c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent break; 9859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9882bbdd77ab20788e901a410f299edef028b66bb6eAmith Yamasani private void resetTimeout() { 9892bbdd77ab20788e901a410f299edef028b66bb6eAmith Yamasani removeMessages(MSG_TIMEOUT); 9902bbdd77ab20788e901a410f299edef028b66bb6eAmith Yamasani sendMessageDelayed(obtainMessage(MSG_TIMEOUT), TIMEOUT_DELAY); 9912bbdd77ab20788e901a410f299edef028b66bb6eAmith Yamasani } 9922bbdd77ab20788e901a410f299edef028b66bb6eAmith Yamasani 993baf6dbfa9340f3266e41841ebd51f21effc583eeAmith Yamasani private void forceTimeout() { 994baf6dbfa9340f3266e41841ebd51f21effc583eeAmith Yamasani removeMessages(MSG_TIMEOUT); 995baf6dbfa9340f3266e41841ebd51f21effc583eeAmith Yamasani sendMessage(obtainMessage(MSG_TIMEOUT)); 996baf6dbfa9340f3266e41841ebd51f21effc583eeAmith Yamasani } 997baf6dbfa9340f3266e41841ebd51f21effc583eeAmith Yamasani 9982bbdd77ab20788e901a410f299edef028b66bb6eAmith Yamasani public void onProgressChanged(SeekBar seekBar, int progress, 9992bbdd77ab20788e901a410f299edef028b66bb6eAmith Yamasani boolean fromUser) { 10002bbdd77ab20788e901a410f299edef028b66bb6eAmith Yamasani final Object tag = seekBar.getTag(); 10012bbdd77ab20788e901a410f299edef028b66bb6eAmith Yamasani if (fromUser && tag instanceof StreamControl) { 10022bbdd77ab20788e901a410f299edef028b66bb6eAmith Yamasani StreamControl sc = (StreamControl) tag; 10038dc1dabd254249b7ddb8743e88fdb96580ffc585Mike Lockwood if (getStreamVolume(sc.streamType) != progress) { 10048dc1dabd254249b7ddb8743e88fdb96580ffc585Mike Lockwood setStreamVolume(sc.streamType, progress, 0); 10052bbdd77ab20788e901a410f299edef028b66bb6eAmith Yamasani } 10062bbdd77ab20788e901a410f299edef028b66bb6eAmith Yamasani } 10072bbdd77ab20788e901a410f299edef028b66bb6eAmith Yamasani resetTimeout(); 10082bbdd77ab20788e901a410f299edef028b66bb6eAmith Yamasani } 10092bbdd77ab20788e901a410f299edef028b66bb6eAmith Yamasani 10102bbdd77ab20788e901a410f299edef028b66bb6eAmith Yamasani public void onStartTrackingTouch(SeekBar seekBar) { 10112bbdd77ab20788e901a410f299edef028b66bb6eAmith Yamasani } 10122bbdd77ab20788e901a410f299edef028b66bb6eAmith Yamasani 10132bbdd77ab20788e901a410f299edef028b66bb6eAmith Yamasani public void onStopTrackingTouch(SeekBar seekBar) { 10143114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi final Object tag = seekBar.getTag(); 10153114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi if (tag instanceof StreamControl) { 10163114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi StreamControl sc = (StreamControl) tag; 10173114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi // because remote volume updates are asynchronous, AudioService might have received 10183114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi // a new remote volume value since the finger adjusted the slider. So when the 10193114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi // progress of the slider isn't being tracked anymore, adjust the slider to the last 10203114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi // "published" remote volume value, so the UI reflects the actual volume. 10213114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi if (sc.streamType == AudioService.STREAM_REMOTE_MUSIC) { 10223114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi seekBar.setProgress(getStreamVolume(AudioService.STREAM_REMOTE_MUSIC)); 10233114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi } 10243114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi } 10252bbdd77ab20788e901a410f299edef028b66bb6eAmith Yamasani } 10262bbdd77ab20788e901a410f299edef028b66bb6eAmith Yamasani 10272bbdd77ab20788e901a410f299edef028b66bb6eAmith Yamasani public void onClick(View v) { 10282bbdd77ab20788e901a410f299edef028b66bb6eAmith Yamasani if (v == mMoreButton) { 10292bbdd77ab20788e901a410f299edef028b66bb6eAmith Yamasani expand(); 10302bbdd77ab20788e901a410f299edef028b66bb6eAmith Yamasani } 10312bbdd77ab20788e901a410f299edef028b66bb6eAmith Yamasani resetTimeout(); 10322bbdd77ab20788e901a410f299edef028b66bb6eAmith Yamasani } 10339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 1034