19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/* 29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Copyright (C) 2006 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.media; 189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 19098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkeyimport static android.Manifest.permission.REMOTE_AUDIO_PLAYBACK; 20c696a53d1fe4d61373c5dc64dd057d322da90c8fAmith Yamasaniimport static android.media.AudioManager.RINGER_MODE_NORMAL; 21c696a53d1fe4d61373c5dc64dd057d322da90c8fAmith Yamasaniimport static android.media.AudioManager.RINGER_MODE_SILENT; 22c696a53d1fe4d61373c5dc64dd057d322da90c8fAmith Yamasaniimport static android.media.AudioManager.RINGER_MODE_VIBRATE; 23c696a53d1fe4d61373c5dc64dd057d322da90c8fAmith Yamasani 24c68022258ebd3dd97a5079ba99f4f3cd12b223b0Jean-Michel Triviimport android.app.Activity; 25fd116ad1ab02f6060a0b2201f018317fa32e28b4Glenn Kastenimport android.app.ActivityManager; 269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.app.ActivityManagerNative; 27ba50b97cff80e73620a0e3d13cae169e095974a7Dianne Hackbornimport android.app.AppOpsManager; 286243edd818b84adfbe712d5d233d6414b33653acAmith Yamasaniimport android.app.KeyguardManager; 29f0cff0456258478ba768097f73d4367ab67fd7a3Jean-Michel Triviimport android.app.PendingIntent; 30f0cff0456258478ba768097f73d4367ab67fd7a3Jean-Michel Triviimport android.app.PendingIntent.CanceledException; 3182aa7f017daaaeb96c13e6e3491d5037ab471085Jaikumar Ganeshimport android.bluetooth.BluetoothA2dp; 3282aa7f017daaaeb96c13e6e3491d5037ab471085Jaikumar Ganeshimport android.bluetooth.BluetoothAdapter; 3382aa7f017daaaeb96c13e6e3491d5037ab471085Jaikumar Ganeshimport android.bluetooth.BluetoothClass; 3482aa7f017daaaeb96c13e6e3491d5037ab471085Jaikumar Ganeshimport android.bluetooth.BluetoothDevice; 3582aa7f017daaaeb96c13e6e3491d5037ab471085Jaikumar Ganeshimport android.bluetooth.BluetoothHeadset; 3682aa7f017daaaeb96c13e6e3491d5037ab471085Jaikumar Ganeshimport android.bluetooth.BluetoothProfile; 374294b83927f51e5c115ebaafd2e185ba5de91436Jean-Michel Triviimport android.content.ActivityNotFoundException; 38bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pellyimport android.content.BroadcastReceiver; 39d327f21626217aa3c9c0cdb7a84a742c531e59a3Jean-Michel Triviimport android.content.ComponentName; 409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.ContentResolver; 419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.Context; 429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.Intent; 43a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurentimport android.content.IntentFilter; 449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.pm.PackageManager; 45f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Triviimport android.content.res.Configuration; 46e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurentimport android.content.res.Resources; 47e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurentimport android.content.res.XmlResourceParser; 48b109615ebebd6f3b9ae789412279f576c3ace46bJason Parekhimport android.database.ContentObserver; 499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.media.MediaPlayer.OnCompletionListener; 509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.media.MediaPlayer.OnErrorListener; 51f108cdd9ee5efe354d87edd02a07b323298c116cJean-Michel Triviimport android.net.Uri; 529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Binder; 53c18c9138cee0f0859bcab636a004ce92ca4a9ab5Eric Laurentimport android.os.Build; 54f0cff0456258478ba768097f73d4367ab67fd7a3Jean-Michel Triviimport android.os.Bundle; 559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Environment; 569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Handler; 579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.IBinder; 589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Looper; 599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Message; 60c68022258ebd3dd97a5079ba99f4f3cd12b223b0Jean-Michel Triviimport android.os.PowerManager; 61632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackbornimport android.os.RemoteCallbackList; 629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.RemoteException; 639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.ServiceManager; 6482aa7f017daaaeb96c13e6e3491d5037ab471085Jaikumar Ganeshimport android.os.SystemProperties; 655ac72a29593ab9a20337a2225df52bdf4754be02Dianne Hackbornimport android.os.UserHandle; 66bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurentimport android.os.Vibrator; 679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.provider.Settings; 689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.provider.Settings.System; 693c2711fc2853394324b044632b79ca67388df8f4Jean-Michel Triviimport android.speech.RecognizerIntent; 70b4bccb6d8df16a2c5235cead187156bc721cf074Jean-Michel Triviimport android.telephony.PhoneStateListener; 71b4bccb6d8df16a2c5235cead187156bc721cf074Jean-Michel Triviimport android.telephony.TelephonyManager; 72632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackbornimport android.text.TextUtils; 739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.Log; 74d327f21626217aa3c9c0cdb7a84a742c531e59a3Jean-Michel Triviimport android.view.KeyEvent; 75bb6f8711a7f804d39c45218db2d6339940cc5d35Jean-Michel Triviimport android.view.Surface; 769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.VolumePanel; 77bb6f8711a7f804d39c45218db2d6339940cc5d35Jean-Michel Triviimport android.view.WindowManager; 789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport com.android.internal.telephony.ITelephony; 80e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurentimport com.android.internal.util.XmlUtils; 81e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent 82e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurentimport org.xmlpull.v1.XmlPullParserException; 839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 84d5176cfe6eae954e9cef1e2ec17859a5089e1330Jean-Michel Triviimport java.io.FileDescriptor; 859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.IOException; 86d5176cfe6eae954e9cef1e2ec17859a5089e1330Jean-Michel Triviimport java.io.PrintWriter; 87e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurentimport java.lang.reflect.Field; 889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.ArrayList; 893172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurentimport java.util.concurrent.ConcurrentHashMap; 90c42ac9d4d03f62c3a1ba197a28a81fda44bd8b7fEric Laurentimport java.util.HashMap; 91f108cdd9ee5efe354d87edd02a07b323298c116cJean-Michel Triviimport java.util.HashSet; 92c42ac9d4d03f62c3a1ba197a28a81fda44bd8b7fEric Laurentimport java.util.Iterator; 935a1e4cf83f5be1b5d79e2643fa791aa269b6a4bcJaikumar Ganeshimport java.util.List; 94c42ac9d4d03f62c3a1ba197a28a81fda44bd8b7fEric Laurentimport java.util.Map; 9582aa7f017daaaeb96c13e6e3491d5037ab471085Jaikumar Ganeshimport java.util.NoSuchElementException; 96c42ac9d4d03f62c3a1ba197a28a81fda44bd8b7fEric Laurentimport java.util.Set; 97d5176cfe6eae954e9cef1e2ec17859a5089e1330Jean-Michel Triviimport java.util.Stack; 989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/** 1009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * The implementation of the volume manager service. 1019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p> 1029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * This implementation focuses on delivering a responsive UI. Most methods are 1039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * asynchronous to external calls. For example, the task of setting a volume 1049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * will update our internal state, but in a separate thread will set the system 1059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * volume and later persist to the database. Similarly, setting the ringer mode 1069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * will update the state and broadcast a change and in a separate thread later 1079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * persist the ringer mode. 1089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 1099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @hide 1109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 111fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivipublic class AudioService extends IAudioService.Stub { 1129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final String TAG = "AudioService"; 1149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11518e7bce52318f00b5023f33933a571c477f2b61cJean-Michel Trivi /** Debug remote control client/display feature */ 1167ff866e8cf43afc64111e98863dab549b57447b4Jean-Michel Trivi protected static final boolean DEBUG_RC = false; 1173114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi /** Debug volumes */ 1183114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi protected static final boolean DEBUG_VOL = false; 11918e7bce52318f00b5023f33933a571c477f2b61cJean-Michel Trivi 1209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** How long to delay before persisting a change in volume/ringer mode. */ 12145edba1b8b0377dfe70a4f2b0afb0f04dd8e1ee9RoboErik private static final int PERSIST_DELAY = 500; 1229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 123ba50b97cff80e73620a0e3d13cae169e095974a7Dianne Hackborn private final Context mContext; 124ba50b97cff80e73620a0e3d13cae169e095974a7Dianne Hackborn private final ContentResolver mContentResolver; 125ba50b97cff80e73620a0e3d13cae169e095974a7Dianne Hackborn private final AppOpsManager mAppOps; 126ba50b97cff80e73620a0e3d13cae169e095974a7Dianne Hackborn private final boolean mVoiceCapable; 127d5176cfe6eae954e9cef1e2ec17859a5089e1330Jean-Michel Trivi 1289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** The UI */ 1299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private VolumePanel mVolumePanel; 1309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // sendMsg() flags 1329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** If the msg is already queued, replace it with this one. */ 1339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final int SENDMSG_REPLACE = 0; 1349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** If the msg is already queued, ignore this one and leave the old. */ 1359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final int SENDMSG_NOOP = 1; 1369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** If the msg is already queued, queue this one and leave the old. */ 1379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final int SENDMSG_QUEUE = 2; 1389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1393114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi // AudioHandler messages 1409bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent private static final int MSG_SET_DEVICE_VOLUME = 0; 1419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final int MSG_PERSIST_VOLUME = 1; 1425c55a051ad7d86a464fb91426f1ea3c0250e38b3Mike Lockwood private static final int MSG_PERSIST_MASTER_VOLUME = 2; 1439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final int MSG_PERSIST_RINGER_MODE = 3; 144bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent private static final int MSG_MEDIA_SERVER_DIED = 4; 145dfb881f96af7898151940a4bbc52e45e6043d38bEric Laurent private static final int MSG_PLAY_SOUND_EFFECT = 5; 146dfb881f96af7898151940a4bbc52e45e6043d38bEric Laurent private static final int MSG_BTA2DP_DOCK_TIMEOUT = 6; 147dfb881f96af7898151940a4bbc52e45e6043d38bEric Laurent private static final int MSG_LOAD_SOUND_EFFECTS = 7; 148dfb881f96af7898151940a4bbc52e45e6043d38bEric Laurent private static final int MSG_SET_FORCE_USE = 8; 149dfb881f96af7898151940a4bbc52e45e6043d38bEric Laurent private static final int MSG_BT_HEADSET_CNCT_FAILED = 9; 150dfb881f96af7898151940a4bbc52e45e6043d38bEric Laurent private static final int MSG_SET_ALL_VOLUMES = 10; 151dfb881f96af7898151940a4bbc52e45e6043d38bEric Laurent private static final int MSG_PERSIST_MASTER_VOLUME_MUTE = 11; 152dfb881f96af7898151940a4bbc52e45e6043d38bEric Laurent private static final int MSG_REPORT_NEW_ROUTES = 12; 153dfb881f96af7898151940a4bbc52e45e6043d38bEric Laurent private static final int MSG_SET_FORCE_BT_A2DP_USE = 13; 154dfb881f96af7898151940a4bbc52e45e6043d38bEric Laurent private static final int MSG_CHECK_MUSIC_ACTIVE = 14; 155dfb881f96af7898151940a4bbc52e45e6043d38bEric Laurent private static final int MSG_BROADCAST_AUDIO_BECOMING_NOISY = 15; 156dfb881f96af7898151940a4bbc52e45e6043d38bEric Laurent private static final int MSG_CONFIGURE_SAFE_MEDIA_VOLUME = 16; 157dfb881f96af7898151940a4bbc52e45e6043d38bEric Laurent private static final int MSG_CONFIGURE_SAFE_MEDIA_VOLUME_FORCED = 17; 158dfb881f96af7898151940a4bbc52e45e6043d38bEric Laurent private static final int MSG_PERSIST_SAFE_VOLUME_STATE = 18; 159dfb881f96af7898151940a4bbc52e45e6043d38bEric Laurent private static final int MSG_BROADCAST_BT_CONNECTION_STATE = 19; 160dfb881f96af7898151940a4bbc52e45e6043d38bEric Laurent private static final int MSG_UNLOAD_SOUND_EFFECTS = 20; 1613114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi // start of messages handled under wakelock 1623114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi // these messages can only be queued, i.e. sent with queueMsgUnderWakeLock(), 163e12c39bb9cedb8b363658979872694eb55b1386eJean-Michel Trivi // and not with sendMsg(..., ..., SENDMSG_QUEUE, ...) 164fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi private static final int MSG_SET_WIRED_DEVICE_CONNECTION_STATE = 100; 165fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi private static final int MSG_SET_A2DP_CONNECTION_STATE = 101; 1663114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi // end of messages handled under wakelock 167afbb047c3945e9c2b7e9bc6b25098d5fb80bba4eEric Laurent 1684c637b9e34f4c8db69a64ad21a4e2bcfa7485b5fJean-Michel Trivi private static final int BTA2DP_DOCK_TIMEOUT_MILLIS = 8000; 169dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent // Timeout for connection to bluetooth headset service 170dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent private static final int BT_HEADSET_CNCT_TIMEOUT_MS = 3000; 171dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent 1729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** @see AudioSystemThread */ 1739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private AudioSystemThread mAudioSystemThread; 1749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** @see AudioHandler */ 1759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private AudioHandler mAudioHandler; 1769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** @see VolumeStreamState */ 1779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private VolumeStreamState[] mStreamStates; 178b109615ebebd6f3b9ae789412279f576c3ace46bJason Parekh private SettingsObserver mSettingsObserver; 179a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent 180fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi private int mMode = AudioSystem.MODE_NORMAL; 181ba195ebc76f23b6679443724ab58c9dc9f2df884Glenn Kasten // protects mRingerMode 182ba195ebc76f23b6679443724ab58c9dc9f2df884Glenn Kasten private final Object mSettingsLock = new Object(); 18345c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent 1849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private SoundPool mSoundPool; 18530c918ce7fbe171944b28fc91b3f22b3d631872dGlenn Kasten private final Object mSoundEffectsLock = new Object(); 1869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final int NUM_SOUNDPOOL_CHANNELS = 4; 1879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1884767690f09ea3447b8c5c32fb28d27650aa18e00Mike Lockwood // Internally master volume is a float in the 0.0 - 1.0 range, 1894767690f09ea3447b8c5c32fb28d27650aa18e00Mike Lockwood // but to support integer based AudioManager API we translate it to 0 - 100 1904767690f09ea3447b8c5c32fb28d27650aa18e00Mike Lockwood private static final int MAX_MASTER_VOLUME = 100; 1914767690f09ea3447b8c5c32fb28d27650aa18e00Mike Lockwood 1926c798970ccb8759d1e613b57111daa8da0ab44c7Lei Zhang // Maximum volume adjust steps allowed in a single batch call. 1936c798970ccb8759d1e613b57111daa8da0ab44c7Lei Zhang private static final int MAX_BATCH_VOLUME_ADJUST_STEPS = 4; 1946c798970ccb8759d1e613b57111daa8da0ab44c7Lei Zhang 1959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* Sound effect file names */ 1969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final String SOUND_EFFECTS_PATH = "/media/audio/ui/"; 197e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent private static final List<String> SOUND_EFFECT_FILES = new ArrayList<String>(); 1989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* Sound effect file name mapping sound effect id (AudioManager.FX_xxx) to 2009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * file index in SOUND_EFFECT_FILES[] (first column) and indicating if effect 2019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * uses soundpool (second column) */ 202e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent private final int[][] SOUND_EFFECT_FILES_MAP = new int[AudioManager.NUM_SOUND_EFFECTS][2]; 2039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2045982013cfc8274ff0bafaba83c676b3a8890cba9Jared Suttles /** @hide Maximum volume index values for audio streams */ 205fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi private static final int[] MAX_STREAM_VOLUME = new int[] { 2066ee9952bc20be72b9419cb653c9e2e833889a3d3Eric Laurent 5, // STREAM_VOICE_CALL 2076ee9952bc20be72b9419cb653c9e2e833889a3d3Eric Laurent 7, // STREAM_SYSTEM 2086ee9952bc20be72b9419cb653c9e2e833889a3d3Eric Laurent 7, // STREAM_RING 2096ee9952bc20be72b9419cb653c9e2e833889a3d3Eric Laurent 15, // STREAM_MUSIC 2106ee9952bc20be72b9419cb653c9e2e833889a3d3Eric Laurent 7, // STREAM_ALARM 2116ee9952bc20be72b9419cb653c9e2e833889a3d3Eric Laurent 7, // STREAM_NOTIFICATION 2126ee9952bc20be72b9419cb653c9e2e833889a3d3Eric Laurent 15, // STREAM_BLUETOOTH_SCO 2136ee9952bc20be72b9419cb653c9e2e833889a3d3Eric Laurent 7, // STREAM_SYSTEM_ENFORCED 2146ee9952bc20be72b9419cb653c9e2e833889a3d3Eric Laurent 15, // STREAM_DTMF 2156ee9952bc20be72b9419cb653c9e2e833889a3d3Eric Laurent 15 // STREAM_TTS 2165982013cfc8274ff0bafaba83c676b3a8890cba9Jared Suttles }; 2176d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent /* mStreamVolumeAlias[] indicates for each stream if it uses the volume settings 218a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent * of another stream: This avoids multiplying the volume settings for hidden 219a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent * stream types that follow other stream behavior for volume settings 2206d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent * NOTE: do not create loops in aliases! 2216d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent * Some streams alias to different streams according to device category (phone or tablet) or 22224e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent * use case (in call vs off call...). See updateStreamVolumeAlias() for more details. 2236d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent * mStreamVolumeAlias contains the default aliases for a voice capable device (phone) and 2246d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent * STREAM_VOLUME_ALIAS_NON_VOICE for a non voice capable device (tablet).*/ 22530c918ce7fbe171944b28fc91b3f22b3d631872dGlenn Kasten private final int[] STREAM_VOLUME_ALIAS = new int[] { 2266d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent AudioSystem.STREAM_VOICE_CALL, // STREAM_VOICE_CALL 2276d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent AudioSystem.STREAM_RING, // STREAM_SYSTEM 2286d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent AudioSystem.STREAM_RING, // STREAM_RING 2296d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent AudioSystem.STREAM_MUSIC, // STREAM_MUSIC 2306d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent AudioSystem.STREAM_ALARM, // STREAM_ALARM 2316d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent AudioSystem.STREAM_RING, // STREAM_NOTIFICATION 2326d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent AudioSystem.STREAM_BLUETOOTH_SCO, // STREAM_BLUETOOTH_SCO 2336d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent AudioSystem.STREAM_RING, // STREAM_SYSTEM_ENFORCED 2346d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent AudioSystem.STREAM_RING, // STREAM_DTMF 2356d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent AudioSystem.STREAM_MUSIC // STREAM_TTS 236a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent }; 2376d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent private final int[] STREAM_VOLUME_ALIAS_NON_VOICE = new int[] { 2386d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent AudioSystem.STREAM_VOICE_CALL, // STREAM_VOICE_CALL 2396d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent AudioSystem.STREAM_MUSIC, // STREAM_SYSTEM 2406d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent AudioSystem.STREAM_RING, // STREAM_RING 2416d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent AudioSystem.STREAM_MUSIC, // STREAM_MUSIC 2426d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent AudioSystem.STREAM_ALARM, // STREAM_ALARM 2436d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent AudioSystem.STREAM_RING, // STREAM_NOTIFICATION 2446d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent AudioSystem.STREAM_BLUETOOTH_SCO, // STREAM_BLUETOOTH_SCO 2456d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent AudioSystem.STREAM_MUSIC, // STREAM_SYSTEM_ENFORCED 2466d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent AudioSystem.STREAM_MUSIC, // STREAM_DTMF 2476d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent AudioSystem.STREAM_MUSIC // STREAM_TTS 2486d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent }; 2496d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent private int[] mStreamVolumeAlias; 250a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent 251ba50b97cff80e73620a0e3d13cae169e095974a7Dianne Hackborn /** 252ba50b97cff80e73620a0e3d13cae169e095974a7Dianne Hackborn * Map AudioSystem.STREAM_* constants to app ops. This should be used 253ba50b97cff80e73620a0e3d13cae169e095974a7Dianne Hackborn * after mapping through mStreamVolumeAlias. 254ba50b97cff80e73620a0e3d13cae169e095974a7Dianne Hackborn */ 255ba50b97cff80e73620a0e3d13cae169e095974a7Dianne Hackborn private static final int[] STEAM_VOLUME_OPS = new int[] { 256ba50b97cff80e73620a0e3d13cae169e095974a7Dianne Hackborn AppOpsManager.OP_AUDIO_VOICE_VOLUME, // STREAM_VOICE_CALL 257ba50b97cff80e73620a0e3d13cae169e095974a7Dianne Hackborn AppOpsManager.OP_AUDIO_MEDIA_VOLUME, // STREAM_SYSTEM 258ba50b97cff80e73620a0e3d13cae169e095974a7Dianne Hackborn AppOpsManager.OP_AUDIO_RING_VOLUME, // STREAM_RING 259ba50b97cff80e73620a0e3d13cae169e095974a7Dianne Hackborn AppOpsManager.OP_AUDIO_MEDIA_VOLUME, // STREAM_MUSIC 260ba50b97cff80e73620a0e3d13cae169e095974a7Dianne Hackborn AppOpsManager.OP_AUDIO_ALARM_VOLUME, // STREAM_ALARM 261ba50b97cff80e73620a0e3d13cae169e095974a7Dianne Hackborn AppOpsManager.OP_AUDIO_NOTIFICATION_VOLUME, // STREAM_NOTIFICATION 262ba50b97cff80e73620a0e3d13cae169e095974a7Dianne Hackborn AppOpsManager.OP_AUDIO_BLUETOOTH_VOLUME, // STREAM_BLUETOOTH_SCO 263ba50b97cff80e73620a0e3d13cae169e095974a7Dianne Hackborn AppOpsManager.OP_AUDIO_MEDIA_VOLUME, // STREAM_SYSTEM_ENFORCED 264ba50b97cff80e73620a0e3d13cae169e095974a7Dianne Hackborn AppOpsManager.OP_AUDIO_MEDIA_VOLUME, // STREAM_DTMF 265ba50b97cff80e73620a0e3d13cae169e095974a7Dianne Hackborn AppOpsManager.OP_AUDIO_MEDIA_VOLUME, // STREAM_TTS 266ba50b97cff80e73620a0e3d13cae169e095974a7Dianne Hackborn }; 267ba50b97cff80e73620a0e3d13cae169e095974a7Dianne Hackborn 26883a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent private final boolean mUseFixedVolume; 26983a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent 270bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent // stream names used by dumpStreamStates() 271bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent private final String[] STREAM_NAMES = new String[] { 272bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent "STREAM_VOICE_CALL", 273bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent "STREAM_SYSTEM", 274bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent "STREAM_RING", 275bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent "STREAM_MUSIC", 276bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent "STREAM_ALARM", 277bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent "STREAM_NOTIFICATION", 278bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent "STREAM_BLUETOOTH_SCO", 279bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent "STREAM_SYSTEM_ENFORCED", 280bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent "STREAM_DTMF", 281bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent "STREAM_TTS" 282bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent }; 283bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent 28430c918ce7fbe171944b28fc91b3f22b3d631872dGlenn Kasten private final AudioSystem.ErrorCallback mAudioSystemCallback = new AudioSystem.ErrorCallback() { 2859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void onError(int error) { 2869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project switch (error) { 2879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case AudioSystem.AUDIO_STATUS_SERVER_DIED: 288dfb881f96af7898151940a4bbc52e45e6043d38bEric Laurent sendMsg(mAudioHandler, MSG_MEDIA_SERVER_DIED, 289dfb881f96af7898151940a4bbc52e45e6043d38bEric Laurent SENDMSG_NOOP, 0, 0, null, 0); 2909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 2919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project default: 2929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 2939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 294dfb881f96af7898151940a4bbc52e45e6043d38bEric Laurent } 2959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project }; 2969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 2989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Current ringer mode from one of {@link AudioManager#RINGER_MODE_NORMAL}, 2999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link AudioManager#RINGER_MODE_SILENT}, or 3009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link AudioManager#RINGER_MODE_VIBRATE}. 3019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 302ba195ebc76f23b6679443724ab58c9dc9f2df884Glenn Kasten // protected by mSettingsLock 3039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private int mRingerMode; 3049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3059bcf401d13d47416043a704430388abd59aef7cdEric Laurent /** @see System#MODE_RINGER_STREAMS_AFFECTED */ 30624e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent private int mRingerModeAffectedStreams = 0; 3079bcf401d13d47416043a704430388abd59aef7cdEric Laurent 3085b4e654d0c7de8e4d58d73e73b0d5220f19b68f7Eric Laurent // Streams currently muted by ringer mode 3095b4e654d0c7de8e4d58d73e73b0d5220f19b68f7Eric Laurent private int mRingerModeMutedStreams; 3105b4e654d0c7de8e4d58d73e73b0d5220f19b68f7Eric Laurent 3119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** @see System#MUTE_STREAMS_AFFECTED */ 3129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private int mMuteAffectedStreams; 3139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 315bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent * NOTE: setVibrateSetting(), getVibrateSetting(), shouldVibrate() are deprecated. 316bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent * mVibrateSetting is just maintained during deprecation period but vibration policy is 317bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent * now only controlled by mHasVibrator and mRingerMode 3189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 3199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private int mVibrateSetting; 3209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 321bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent // Is there a vibrator 322bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent private final boolean mHasVibrator; 323bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent 324a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent // Broadcast receiver for device connections intent broadcasts 325a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent private final BroadcastReceiver mReceiver = new AudioServiceBroadcastReceiver(); 326a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent 327c42ac9d4d03f62c3a1ba197a28a81fda44bd8b7fEric Laurent // Devices currently connected 32830c918ce7fbe171944b28fc91b3f22b3d631872dGlenn Kasten private final HashMap <Integer, String> mConnectedDevices = new HashMap <Integer, String>(); 329c42ac9d4d03f62c3a1ba197a28a81fda44bd8b7fEric Laurent 330c42ac9d4d03f62c3a1ba197a28a81fda44bd8b7fEric Laurent // Forced device usage for communications 331c42ac9d4d03f62c3a1ba197a28a81fda44bd8b7fEric Laurent private int mForcedUseForComm; 332c42ac9d4d03f62c3a1ba197a28a81fda44bd8b7fEric Laurent 3330dc37cce9d564ae43883c8dc8672b9266b881e63Mike Lockwood // True if we have master volume support 3340dc37cce9d564ae43883c8dc8672b9266b881e63Mike Lockwood private final boolean mUseMasterVolume; 3350dc37cce9d564ae43883c8dc8672b9266b881e63Mike Lockwood 3369760647dd0ee67e7c20f3e9d661d2006b1df0b54Mike Lockwood private final int[] mMasterVolumeRamp; 3379760647dd0ee67e7c20f3e9d661d2006b1df0b54Mike Lockwood 3389272b4b4a44fe1f33e3030810618194f817caaecEric Laurent // List of binder death handlers for setMode() client processes. 3399272b4b4a44fe1f33e3030810618194f817caaecEric Laurent // The last process to have called setMode() is at the top of the list. 34030c918ce7fbe171944b28fc91b3f22b3d631872dGlenn Kasten private final ArrayList <SetModeDeathHandler> mSetModeDeathHandlers = new ArrayList <SetModeDeathHandler>(); 341eb14a783be073b5fd6e8c8c9bc87d2d1919f2c9eEric Laurent 3423def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent // List of clients having issued a SCO start request 34330c918ce7fbe171944b28fc91b3f22b3d631872dGlenn Kasten private final ArrayList <ScoClient> mScoClients = new ArrayList <ScoClient>(); 3443def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent 3453def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent // BluetoothHeadset API to control SCO connection 3463def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent private BluetoothHeadset mBluetoothHeadset; 3473def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent 34882aa7f017daaaeb96c13e6e3491d5037ab471085Jaikumar Ganesh // Bluetooth headset device 34982aa7f017daaaeb96c13e6e3491d5037ab471085Jaikumar Ganesh private BluetoothDevice mBluetoothHeadsetDevice; 3503def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent 35162ef767b15a712bab31cc0d5508a330906f535c2Eric Laurent // Indicate if SCO audio connection is currently active and if the initiator is 35262ef767b15a712bab31cc0d5508a330906f535c2Eric Laurent // audio service (internal) or bluetooth headset (external) 35362ef767b15a712bab31cc0d5508a330906f535c2Eric Laurent private int mScoAudioState; 35462ef767b15a712bab31cc0d5508a330906f535c2Eric Laurent // SCO audio state is not active 35562ef767b15a712bab31cc0d5508a330906f535c2Eric Laurent private static final int SCO_STATE_INACTIVE = 0; 356dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent // SCO audio activation request waiting for headset service to connect 357dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent private static final int SCO_STATE_ACTIVATE_REQ = 1; 35825fc29b3691a1d2a84164988dc74b2e7d301868eEric Laurent // SCO audio state is active or starting due to a request from AudioManager API 359dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent private static final int SCO_STATE_ACTIVE_INTERNAL = 3; 360dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent // SCO audio deactivation request waiting for headset service to connect 361dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent private static final int SCO_STATE_DEACTIVATE_REQ = 5; 362dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent 36362ef767b15a712bab31cc0d5508a330906f535c2Eric Laurent // SCO audio state is active due to an action in BT handsfree (either voice recognition or 36462ef767b15a712bab31cc0d5508a330906f535c2Eric Laurent // in call audio) 36562ef767b15a712bab31cc0d5508a330906f535c2Eric Laurent private static final int SCO_STATE_ACTIVE_EXTERNAL = 2; 366dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent // Deactivation request for all SCO connections (initiated by audio mode change) 367dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent // waiting for headset service to connect 368dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent private static final int SCO_STATE_DEACTIVATE_EXT_REQ = 4; 369dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent 370c18c9138cee0f0859bcab636a004ce92ca4a9ab5Eric Laurent // Indicates the mode used for SCO audio connection. The mode is virtual call if the request 371c18c9138cee0f0859bcab636a004ce92ca4a9ab5Eric Laurent // originated from an app targeting an API version before JB MR2 and raw audio after that. 372c18c9138cee0f0859bcab636a004ce92ca4a9ab5Eric Laurent private int mScoAudioMode; 373c18c9138cee0f0859bcab636a004ce92ca4a9ab5Eric Laurent // SCO audio mode is virtual voice call (BluetoothHeadset.startScoUsingVirtualVoiceCall()) 374c18c9138cee0f0859bcab636a004ce92ca4a9ab5Eric Laurent private static final int SCO_MODE_VIRTUAL_CALL = 0; 375c18c9138cee0f0859bcab636a004ce92ca4a9ab5Eric Laurent // SCO audio mode is raw audio (BluetoothHeadset.connectAudio()) 376c18c9138cee0f0859bcab636a004ce92ca4a9ab5Eric Laurent private static final int SCO_MODE_RAW = 1; 377c18c9138cee0f0859bcab636a004ce92ca4a9ab5Eric Laurent 378dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent // Current connection state indicated by bluetooth headset 379dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent private int mScoConnectionState; 38062ef767b15a712bab31cc0d5508a330906f535c2Eric Laurent 381a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent // true if boot sequence has been completed 382a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent private boolean mBootCompleted; 383a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent // listener for SoundPool sample load completion indication 384a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent private SoundPoolCallback mSoundPoolCallBack; 385a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent // thread for SoundPool listener 386a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent private SoundPoolListenerThread mSoundPoolListenerThread; 387a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent // message looper for SoundPool listener 388a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent private Looper mSoundPoolLooper = null; 389c55b393efd462490cd5e27fc373bceafdd25662eJean-Michel Trivi // volume applied to sound played with playSoundEffect() 390f2b0c11f4e797e183131261724d8de310dac5431Jean-Michel Trivi private static int sSoundEffectVolumeDb; 3919903e2638a6c502d96413680d3ebae4fb77fc412Eric Laurent // getActiveStreamType() will return: 3929903e2638a6c502d96413680d3ebae4fb77fc412Eric Laurent // - STREAM_NOTIFICATION on tablets during this period after a notification stopped 3939903e2638a6c502d96413680d3ebae4fb77fc412Eric Laurent // - STREAM_MUSIC on phones during this period after music or talkback/voice search prompt 39425101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent // stopped 3959903e2638a6c502d96413680d3ebae4fb77fc412Eric Laurent private static final int DEFAULT_STREAM_TYPE_OVERRIDE_DELAY_MS = 5000; 39625101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent // previous volume adjustment direction received by checkForRingerModeChange() 39725101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent private int mPrevVolDirection = AudioManager.ADJUST_SAME; 3986243edd818b84adfbe712d5d233d6414b33653acAmith Yamasani // Keyguard manager proxy 3996243edd818b84adfbe712d5d233d6414b33653acAmith Yamasani private KeyguardManager mKeyguardManager; 40045c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent // mVolumeControlStream is set by VolumePanel to temporarily force the stream type which volume 40145c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent // is controlled by Vol keys. 40245c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent private int mVolumeControlStream = -1; 40345c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent private final Object mForceControlStreamLock = new Object(); 40445c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent // VolumePanel is currently the only client of forceVolumeControlStream() and runs in system 40545c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent // server process so in theory it is not necessary to monitor the client death. 40645c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent // However it is good to be ready for future evolutions. 40745c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent private ForceControlStreamClient mForceControlStreamClient = null; 408098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey // Used to play ringtones outside system_server 409098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey private volatile IRingtonePlayer mRingtonePlayer; 4109bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent 411f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi private int mDeviceOrientation = Configuration.ORIENTATION_UNDEFINED; 412bb6f8711a7f804d39c45218db2d6339940cc5d35Jean-Michel Trivi private int mDeviceRotation = Surface.ROTATION_0; 413f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi 4147847211fb4699bf6018e29d214a918ed6657319bEric Laurent // Request to override default use of A2DP for media. 4157847211fb4699bf6018e29d214a918ed6657319bEric Laurent private boolean mBluetoothA2dpEnabled; 4167847211fb4699bf6018e29d214a918ed6657319bEric Laurent private final Object mBluetoothA2dpEnabledLock = new Object(); 4177847211fb4699bf6018e29d214a918ed6657319bEric Laurent 418632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn // Monitoring of audio routes. Protected by mCurAudioRoutes. 419632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn final AudioRoutesInfo mCurAudioRoutes = new AudioRoutesInfo(); 420632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn final RemoteCallbackList<IAudioRoutesObserver> mRoutesObservers 421632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn = new RemoteCallbackList<IAudioRoutesObserver>(); 422632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn 4233114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi /** 4243114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi * A fake stream type to match the notion of remote media playback 4253114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi */ 4263114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi public final static int STREAM_REMOTE_MUSIC = -200; 4273114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi 4284bbcc6549738f3d69831b2bd9eb4accec3e9920eEric Laurent // Devices for which the volume is fixed and VolumePanel slider should be disabled 4294bbcc6549738f3d69831b2bd9eb4accec3e9920eEric Laurent final int mFixedVolumeDevices = AudioSystem.DEVICE_OUT_AUX_DIGITAL | 4304bbcc6549738f3d69831b2bd9eb4accec3e9920eEric Laurent AudioSystem.DEVICE_OUT_DGTL_DOCK_HEADSET | 4317ee1e4ff7346a278a6722108fbc1869240b3e866Eric Laurent AudioSystem.DEVICE_OUT_ANLG_DOCK_HEADSET | 4324bbcc6549738f3d69831b2bd9eb4accec3e9920eEric Laurent AudioSystem.DEVICE_OUT_ALL_USB; 4334bbcc6549738f3d69831b2bd9eb4accec3e9920eEric Laurent 434bb6f8711a7f804d39c45218db2d6339940cc5d35Jean-Michel Trivi // TODO merge orientation and rotation 435d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent private final boolean mMonitorOrientation; 436bb6f8711a7f804d39c45218db2d6339940cc5d35Jean-Michel Trivi private final boolean mMonitorRotation; 437d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent 4387ee1e4ff7346a278a6722108fbc1869240b3e866Eric Laurent private boolean mDockAudioMediaEnabled = true; 4397ee1e4ff7346a278a6722108fbc1869240b3e866Eric Laurent 44008ed1b9d2099ec8231b21353b33b901492ea9885Eric Laurent private int mDockState = Intent.EXTRA_DOCK_STATE_UNDOCKED; 44108ed1b9d2099ec8231b21353b33b901492ea9885Eric Laurent 442fde16d5879ea88a971004c984093409468b6139cEric Laurent // Used when safe volume warning message display is requested by setStreamVolume(). In this 443fde16d5879ea88a971004c984093409468b6139cEric Laurent // case, the new requested volume, stream type and device are stored in mPendingVolumeCommand 444fde16d5879ea88a971004c984093409468b6139cEric Laurent // and used later when/if disableSafeMediaVolume() is called. 445fde16d5879ea88a971004c984093409468b6139cEric Laurent private StreamVolumeCommand mPendingVolumeCommand; 446fde16d5879ea88a971004c984093409468b6139cEric Laurent 447fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi private PowerManager.WakeLock mAudioEventWakeLock; 448fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi 449fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi private final MediaFocusControl mMediaFocusControl; 450fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi 4515a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du // Reference to BluetoothA2dp to query for AbsoluteVolume. 4525a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du private BluetoothA2dp mA2dp; 4535a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du private final Object mA2dpAvrcpLock = new Object(); 4545a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du // If absolute volume is supported in AVRCP device 4555a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du private boolean mAvrcpAbsVolSupported = false; 4565a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du 4579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /////////////////////////////////////////////////////////////////////////// 4589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Construction 4599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /////////////////////////////////////////////////////////////////////////// 4609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** @hide */ 4629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public AudioService(Context context) { 4639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext = context; 4649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContentResolver = context.getContentResolver(); 465ba50b97cff80e73620a0e3d13cae169e095974a7Dianne Hackborn mAppOps = (AppOpsManager)context.getSystemService(Context.APP_OPS_SERVICE); 466c7fcba4b7bd3d78e7cfe975a3f8e4dde2f6738b7Joe Onorato mVoiceCapable = mContext.getResources().getBoolean( 467c7fcba4b7bd3d78e7cfe975a3f8e4dde2f6738b7Joe Onorato com.android.internal.R.bool.config_voice_capable); 4685982013cfc8274ff0bafaba83c676b3a8890cba9Jared Suttles 469c68022258ebd3dd97a5079ba99f4f3cd12b223b0Jean-Michel Trivi PowerManager pm = (PowerManager)context.getSystemService(Context.POWER_SERVICE); 470fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi mAudioEventWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "handleAudioEvent"); 471c68022258ebd3dd97a5079ba99f4f3cd12b223b0Jean-Michel Trivi 472bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent Vibrator vibrator = (Vibrator) context.getSystemService(Context.VIBRATOR_SERVICE); 473bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent mHasVibrator = vibrator == null ? false : vibrator.hasVibrator(); 474bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent 4755982013cfc8274ff0bafaba83c676b3a8890cba9Jared Suttles // Intialized volume 4765982013cfc8274ff0bafaba83c676b3a8890cba9Jared Suttles MAX_STREAM_VOLUME[AudioSystem.STREAM_VOICE_CALL] = SystemProperties.getInt( 4775982013cfc8274ff0bafaba83c676b3a8890cba9Jared Suttles "ro.config.vc_call_vol_steps", 4785982013cfc8274ff0bafaba83c676b3a8890cba9Jared Suttles MAX_STREAM_VOLUME[AudioSystem.STREAM_VOICE_CALL]); 4795982013cfc8274ff0bafaba83c676b3a8890cba9Jared Suttles 480f2b0c11f4e797e183131261724d8de310dac5431Jean-Michel Trivi sSoundEffectVolumeDb = context.getResources().getInteger( 481c55b393efd462490cd5e27fc373bceafdd25662eJean-Michel Trivi com.android.internal.R.integer.config_soundEffectVolumeDb); 48225101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent 4839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mVolumePanel = new VolumePanel(context, this); 484c42ac9d4d03f62c3a1ba197a28a81fda44bd8b7fEric Laurent mForcedUseForComm = AudioSystem.FORCE_NONE; 485dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent 4869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project createAudioSystemThread(); 487dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent 488fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi mMediaFocusControl = new MediaFocusControl(mAudioHandler.getLooper(), 489fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi mContext, /*VolumeController*/ mVolumePanel, this); 490fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi 491dfb881f96af7898151940a4bbc52e45e6043d38bEric Laurent AudioSystem.setErrorCallback(mAudioSystemCallback); 492dfb881f96af7898151940a4bbc52e45e6043d38bEric Laurent 493dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent boolean cameraSoundForced = mContext.getResources().getBoolean( 494dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent com.android.internal.R.bool.config_camera_sound_forced); 495dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent mCameraSoundForced = new Boolean(cameraSoundForced); 496dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent sendMsg(mAudioHandler, 497dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent MSG_SET_FORCE_USE, 498dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent SENDMSG_QUEUE, 499dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent AudioSystem.FOR_SYSTEM, 500dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent cameraSoundForced ? 501dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent AudioSystem.FORCE_SYSTEM_ENFORCED : AudioSystem.FORCE_NONE, 502dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent null, 503dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent 0); 504dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent 50505274f348e12983eb8613cc6eb9ae561e8197e28Eric Laurent mSafeMediaVolumeState = new Integer(Settings.Global.getInt(mContentResolver, 50605274f348e12983eb8613cc6eb9ae561e8197e28Eric Laurent Settings.Global.AUDIO_SAFE_VOLUME_STATE, 50705274f348e12983eb8613cc6eb9ae561e8197e28Eric Laurent SAFE_MEDIA_VOLUME_NOT_CONFIGURED)); 50805274f348e12983eb8613cc6eb9ae561e8197e28Eric Laurent // The default safe volume index read here will be replaced by the actual value when 50905274f348e12983eb8613cc6eb9ae561e8197e28Eric Laurent // the mcc is read by onConfigureSafeVolume() 51005274f348e12983eb8613cc6eb9ae561e8197e28Eric Laurent mSafeMediaVolumeIndex = mContext.getResources().getInteger( 51105274f348e12983eb8613cc6eb9ae561e8197e28Eric Laurent com.android.internal.R.integer.config_safe_media_volume_index) * 10; 51205274f348e12983eb8613cc6eb9ae561e8197e28Eric Laurent 51383a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent mUseFixedVolume = mContext.getResources().getBoolean( 51483a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent com.android.internal.R.bool.config_useFixedVolume); 51583a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent 51624e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent // must be called before readPersistedSettings() which needs a valid mStreamVolumeAlias[] 51724e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent // array initialized by updateStreamVolumeAlias() 51824e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent updateStreamVolumeAlias(false /*updateVolumes*/); 5199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project readPersistedSettings(); 520c1d4166289ce016965d1147f7e8d37862ee347ecEric Laurent mSettingsObserver = new SettingsObserver(); 521a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent createStreamStates(); 5229f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent 523fd116ad1ab02f6060a0b2201f018317fa32e28b4Glenn Kasten readAndSetLowRamDevice(); 5243891c4cc918e8062abb97c542a8625d556dccc59Eric Laurent 5253891c4cc918e8062abb97c542a8625d556dccc59Eric Laurent // Call setRingerModeInt() to apply correct mute 5263891c4cc918e8062abb97c542a8625d556dccc59Eric Laurent // state on streams affected by ringer mode. 5273891c4cc918e8062abb97c542a8625d556dccc59Eric Laurent mRingerModeMutedStreams = 0; 5283891c4cc918e8062abb97c542a8625d556dccc59Eric Laurent setRingerModeInt(getRingerMode(), false); 5293891c4cc918e8062abb97c542a8625d556dccc59Eric Laurent 530a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent // Register for device connection intent broadcasts. 531a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent IntentFilter intentFilter = 532b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent new IntentFilter(BluetoothHeadset.ACTION_AUDIO_STATE_CHANGED); 53382aa7f017daaaeb96c13e6e3491d5037ab471085Jaikumar Ganesh intentFilter.addAction(BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED); 53482aa7f017daaaeb96c13e6e3491d5037ab471085Jaikumar Ganesh intentFilter.addAction(Intent.ACTION_DOCK_EVENT); 53559f482764e346a5c5ac118ee1f7b24da645c2559Eric Laurent intentFilter.addAction(Intent.ACTION_USB_AUDIO_ACCESSORY_PLUG); 53659f482764e346a5c5ac118ee1f7b24da645c2559Eric Laurent intentFilter.addAction(Intent.ACTION_USB_AUDIO_DEVICE_PLUG); 53762ef767b15a712bab31cc0d5508a330906f535c2Eric Laurent intentFilter.addAction(Intent.ACTION_BOOT_COMPLETED); 538950e8cb40a6d826af4cc2eef9d3908c1b70486e6Eric Laurent intentFilter.addAction(Intent.ACTION_SCREEN_ON); 539950e8cb40a6d826af4cc2eef9d3908c1b70486e6Eric Laurent intentFilter.addAction(Intent.ACTION_SCREEN_OFF); 540bc0fab1fc2db832ef86d8a33466ec4d68b103ca0Eric Laurent intentFilter.addAction(Intent.ACTION_USER_SWITCHED); 541f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi 542d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent intentFilter.addAction(Intent.ACTION_CONFIGURATION_CHANGED); 543bb6f8711a7f804d39c45218db2d6339940cc5d35Jean-Michel Trivi // TODO merge orientation and rotation 544d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent mMonitorOrientation = SystemProperties.getBoolean("ro.audio.monitorOrientation", false); 545d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent if (mMonitorOrientation) { 546f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi Log.v(TAG, "monitoring device orientation"); 547f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi // initialize orientation in AudioSystem 548f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi setOrientationForAudioSystem(); 549f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi } 550bb6f8711a7f804d39c45218db2d6339940cc5d35Jean-Michel Trivi mMonitorRotation = SystemProperties.getBoolean("ro.audio.monitorRotation", false); 551bb6f8711a7f804d39c45218db2d6339940cc5d35Jean-Michel Trivi if (mMonitorRotation) { 552bb6f8711a7f804d39c45218db2d6339940cc5d35Jean-Michel Trivi mDeviceRotation = ((WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE)) 553bb6f8711a7f804d39c45218db2d6339940cc5d35Jean-Michel Trivi .getDefaultDisplay().getRotation(); 554bb6f8711a7f804d39c45218db2d6339940cc5d35Jean-Michel Trivi Log.v(TAG, "monitoring device rotation, initial=" + mDeviceRotation); 555bb6f8711a7f804d39c45218db2d6339940cc5d35Jean-Michel Trivi // initialize rotation in AudioSystem 556bb6f8711a7f804d39c45218db2d6339940cc5d35Jean-Michel Trivi setRotationForAudioSystem(); 557bb6f8711a7f804d39c45218db2d6339940cc5d35Jean-Michel Trivi } 558f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi 559a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent context.registerReceiver(mReceiver, intentFilter); 5605982013cfc8274ff0bafaba83c676b3a8890cba9Jared Suttles 5610dc37cce9d564ae43883c8dc8672b9266b881e63Mike Lockwood mUseMasterVolume = context.getResources().getBoolean( 5620dc37cce9d564ae43883c8dc8672b9266b881e63Mike Lockwood com.android.internal.R.bool.config_useMasterVolume); 5639063154a793b0ab38b3c5992cbaed046427b4a82Mike Lockwood restoreMasterVolume(); 5649760647dd0ee67e7c20f3e9d661d2006b1df0b54Mike Lockwood 5659760647dd0ee67e7c20f3e9d661d2006b1df0b54Mike Lockwood mMasterVolumeRamp = context.getResources().getIntArray( 5669760647dd0ee67e7c20f3e9d661d2006b1df0b54Mike Lockwood com.android.internal.R.array.config_masterVolumeRamp); 5677847211fb4699bf6018e29d214a918ed6657319bEric Laurent 5689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private void createAudioSystemThread() { 5719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mAudioSystemThread = new AudioSystemThread(); 5729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mAudioSystemThread.start(); 5739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project waitForAudioHandlerCreation(); 5749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** Waits for the volume handler to be created by the other thread. */ 5779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private void waitForAudioHandlerCreation() { 5789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project synchronized(this) { 5799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project while (mAudioHandler == null) { 5809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 5819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Wait for mAudioHandler to be set by the other thread 5829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project wait(); 5839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } catch (InterruptedException e) { 5849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Log.e(TAG, "Interrupted while waiting on volume handler."); 5859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 590244820185269991186d07068b92985624cede4a5Eric Laurent private void checkAllAliasStreamVolumes() { 591244820185269991186d07068b92985624cede4a5Eric Laurent int numStreamTypes = AudioSystem.getNumStreamTypes(); 592244820185269991186d07068b92985624cede4a5Eric Laurent for (int streamType = 0; streamType < numStreamTypes; streamType++) { 593244820185269991186d07068b92985624cede4a5Eric Laurent if (streamType != mStreamVolumeAlias[streamType]) { 594244820185269991186d07068b92985624cede4a5Eric Laurent mStreamStates[streamType]. 59542b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent setAllIndexes(mStreamStates[mStreamVolumeAlias[streamType]]); 596244820185269991186d07068b92985624cede4a5Eric Laurent } 597244820185269991186d07068b92985624cede4a5Eric Laurent // apply stream volume 59842b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent if (!mStreamStates[streamType].isMuted()) { 599244820185269991186d07068b92985624cede4a5Eric Laurent mStreamStates[streamType].applyAllVolumes(); 600244820185269991186d07068b92985624cede4a5Eric Laurent } 601244820185269991186d07068b92985624cede4a5Eric Laurent } 602244820185269991186d07068b92985624cede4a5Eric Laurent } 603244820185269991186d07068b92985624cede4a5Eric Laurent 6049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private void createStreamStates() { 6059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int numStreamTypes = AudioSystem.getNumStreamTypes(); 6069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project VolumeStreamState[] streams = mStreamStates = new VolumeStreamState[numStreamTypes]; 6079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = 0; i < numStreamTypes; i++) { 6096d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent streams[i] = new VolumeStreamState(System.VOLUME_SETTINGS[mStreamVolumeAlias[i]], i); 6109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 612244820185269991186d07068b92985624cede4a5Eric Laurent checkAllAliasStreamVolumes(); 6139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 615bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent private void dumpStreamStates(PrintWriter pw) { 616bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent pw.println("\nStream volumes (device: index)"); 617bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent int numStreamTypes = AudioSystem.getNumStreamTypes(); 618bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent for (int i = 0; i < numStreamTypes; i++) { 619bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent pw.println("- "+STREAM_NAMES[i]+":"); 620bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent mStreamStates[i].dump(pw); 621bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent pw.println(""); 622bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent } 623dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent pw.print("\n- mute affected streams = 0x"); 624dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent pw.println(Integer.toHexString(mMuteAffectedStreams)); 625bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent } 626bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent 6276d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent 6286d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent private void updateStreamVolumeAlias(boolean updateVolumes) { 6296d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent int dtmfStreamAlias; 6306d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent if (mVoiceCapable) { 6316d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent mStreamVolumeAlias = STREAM_VOLUME_ALIAS; 6326d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent dtmfStreamAlias = AudioSystem.STREAM_RING; 6336d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent } else { 6346d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent mStreamVolumeAlias = STREAM_VOLUME_ALIAS_NON_VOICE; 6356d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent dtmfStreamAlias = AudioSystem.STREAM_MUSIC; 6366d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent } 6376d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent if (isInCommunication()) { 6386d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent dtmfStreamAlias = AudioSystem.STREAM_VOICE_CALL; 63924e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent mRingerModeAffectedStreams &= ~(1 << AudioSystem.STREAM_DTMF); 64024e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent } else { 64124e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent mRingerModeAffectedStreams |= (1 << AudioSystem.STREAM_DTMF); 6426d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent } 6436d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent mStreamVolumeAlias[AudioSystem.STREAM_DTMF] = dtmfStreamAlias; 6446d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent if (updateVolumes) { 64542b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent mStreamStates[AudioSystem.STREAM_DTMF].setAllIndexes(mStreamStates[dtmfStreamAlias]); 64624e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent // apply stream mute states according to new value of mRingerModeAffectedStreams 64724e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent setRingerModeInt(getRingerMode(), false); 6486d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent sendMsg(mAudioHandler, 6496d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent MSG_SET_ALL_VOLUMES, 6506d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent SENDMSG_QUEUE, 6516d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent 0, 6526d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent 0, 6536d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent mStreamStates[AudioSystem.STREAM_DTMF], 0); 6546d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent } 6556d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent } 6566d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent 6577ee1e4ff7346a278a6722108fbc1869240b3e866Eric Laurent private void readDockAudioSettings(ContentResolver cr) 6587ee1e4ff7346a278a6722108fbc1869240b3e866Eric Laurent { 6597ee1e4ff7346a278a6722108fbc1869240b3e866Eric Laurent mDockAudioMediaEnabled = Settings.Global.getInt( 6605ba0ffa0237a5c300545e4c72591613c6e5b2ed9Eric Laurent cr, Settings.Global.DOCK_AUDIO_MEDIA_ENABLED, 0) == 1; 6617ee1e4ff7346a278a6722108fbc1869240b3e866Eric Laurent 6627ee1e4ff7346a278a6722108fbc1869240b3e866Eric Laurent if (mDockAudioMediaEnabled) { 6637ee1e4ff7346a278a6722108fbc1869240b3e866Eric Laurent mBecomingNoisyIntentDevices |= AudioSystem.DEVICE_OUT_ANLG_DOCK_HEADSET; 6647ee1e4ff7346a278a6722108fbc1869240b3e866Eric Laurent } else { 6657ee1e4ff7346a278a6722108fbc1869240b3e866Eric Laurent mBecomingNoisyIntentDevices &= ~AudioSystem.DEVICE_OUT_ANLG_DOCK_HEADSET; 6667ee1e4ff7346a278a6722108fbc1869240b3e866Eric Laurent } 6677ee1e4ff7346a278a6722108fbc1869240b3e866Eric Laurent 6687ee1e4ff7346a278a6722108fbc1869240b3e866Eric Laurent sendMsg(mAudioHandler, 6697ee1e4ff7346a278a6722108fbc1869240b3e866Eric Laurent MSG_SET_FORCE_USE, 6707ee1e4ff7346a278a6722108fbc1869240b3e866Eric Laurent SENDMSG_QUEUE, 6717ee1e4ff7346a278a6722108fbc1869240b3e866Eric Laurent AudioSystem.FOR_DOCK, 6727ee1e4ff7346a278a6722108fbc1869240b3e866Eric Laurent mDockAudioMediaEnabled ? 6737ee1e4ff7346a278a6722108fbc1869240b3e866Eric Laurent AudioSystem.FORCE_ANALOG_DOCK : AudioSystem.FORCE_NONE, 6747ee1e4ff7346a278a6722108fbc1869240b3e866Eric Laurent null, 6757ee1e4ff7346a278a6722108fbc1869240b3e866Eric Laurent 0); 6767ee1e4ff7346a278a6722108fbc1869240b3e866Eric Laurent } 6777ee1e4ff7346a278a6722108fbc1869240b3e866Eric Laurent 6789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private void readPersistedSettings() { 6799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final ContentResolver cr = mContentResolver; 6809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 681bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent int ringerModeFromSettings = 6828d9a1f66d9d3dbbd45a56d441a746ec11dba7645Jeff Sharkey Settings.Global.getInt( 6838d9a1f66d9d3dbbd45a56d441a746ec11dba7645Jeff Sharkey cr, Settings.Global.MODE_RINGER, AudioManager.RINGER_MODE_NORMAL); 684bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent int ringerMode = ringerModeFromSettings; 68572668b2c040b581b298b069f3b5af5ed7f212d89Eric Laurent // sanity check in case the settings are restored from a device with incompatible 68672668b2c040b581b298b069f3b5af5ed7f212d89Eric Laurent // ringer modes 687ba195ebc76f23b6679443724ab58c9dc9f2df884Glenn Kasten if (!AudioManager.isValidRingerMode(ringerMode)) { 688ba195ebc76f23b6679443724ab58c9dc9f2df884Glenn Kasten ringerMode = AudioManager.RINGER_MODE_NORMAL; 689bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent } 690bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent if ((ringerMode == AudioManager.RINGER_MODE_VIBRATE) && !mHasVibrator) { 691bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent ringerMode = AudioManager.RINGER_MODE_SILENT; 692bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent } 693bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent if (ringerMode != ringerModeFromSettings) { 6948d9a1f66d9d3dbbd45a56d441a746ec11dba7645Jeff Sharkey Settings.Global.putInt(cr, Settings.Global.MODE_RINGER, ringerMode); 695ba195ebc76f23b6679443724ab58c9dc9f2df884Glenn Kasten } 69683a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent if (mUseFixedVolume) { 69783a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent ringerMode = AudioManager.RINGER_MODE_NORMAL; 69883a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent } 699ba195ebc76f23b6679443724ab58c9dc9f2df884Glenn Kasten synchronized(mSettingsLock) { 700ba195ebc76f23b6679443724ab58c9dc9f2df884Glenn Kasten mRingerMode = ringerMode; 7019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 702dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent // System.VIBRATE_ON is not used any more but defaults for mVibrateSetting 703dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent // are still needed while setVibrateSetting() and getVibrateSetting() are being 704dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent // deprecated. 705dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent mVibrateSetting = getValueForVibrateSetting(0, 706dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent AudioManager.VIBRATE_TYPE_NOTIFICATION, 707dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent mHasVibrator ? AudioManager.VIBRATE_SETTING_ONLY_SILENT 708dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent : AudioManager.VIBRATE_SETTING_OFF); 709dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent mVibrateSetting = getValueForVibrateSetting(mVibrateSetting, 710dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent AudioManager.VIBRATE_TYPE_RINGER, 711dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent mHasVibrator ? AudioManager.VIBRATE_SETTING_ONLY_SILENT 712dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent : AudioManager.VIBRATE_SETTING_OFF); 713dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent 71424e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent updateRingerModeAffectedStreams(); 7157ee1e4ff7346a278a6722108fbc1869240b3e866Eric Laurent readDockAudioSettings(cr); 716402f7f29634a9f68e7929be828a927a3e2f5efe9Eric Laurent } 717c1d4166289ce016965d1147f7e8d37862ee347ecEric Laurent 718bc0fab1fc2db832ef86d8a33466ec4d68b103ca0Eric Laurent mMuteAffectedStreams = System.getIntForUser(cr, 7199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project System.MUTE_STREAMS_AFFECTED, 720bc0fab1fc2db832ef86d8a33466ec4d68b103ca0Eric Laurent ((1 << AudioSystem.STREAM_MUSIC)| 721bc0fab1fc2db832ef86d8a33466ec4d68b103ca0Eric Laurent (1 << AudioSystem.STREAM_RING)| 722bc0fab1fc2db832ef86d8a33466ec4d68b103ca0Eric Laurent (1 << AudioSystem.STREAM_SYSTEM)), 723bc0fab1fc2db832ef86d8a33466ec4d68b103ca0Eric Laurent UserHandle.USER_CURRENT); 7249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 725bc0fab1fc2db832ef86d8a33466ec4d68b103ca0Eric Laurent boolean masterMute = System.getIntForUser(cr, System.VOLUME_MASTER_MUTE, 726bc0fab1fc2db832ef86d8a33466ec4d68b103ca0Eric Laurent 0, UserHandle.USER_CURRENT) == 1; 72783a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent if (mUseFixedVolume) { 72883a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent masterMute = false; 72983a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent AudioSystem.setMasterVolume(1.0f); 73083a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent } 73157978ed86286a33d5b1a0fd000ca3406ba9d87b3Justin Koh AudioSystem.setMasterMute(masterMute); 73257978ed86286a33d5b1a0fd000ca3406ba9d87b3Justin Koh broadcastMasterMuteStatus(masterMute); 73357978ed86286a33d5b1a0fd000ca3406ba9d87b3Justin Koh 7349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Each stream will read its own persisted settings 7359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Broadcast the sticky intent 737ba195ebc76f23b6679443724ab58c9dc9f2df884Glenn Kasten broadcastRingerMode(ringerMode); 7389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Broadcast vibrate settings 7409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project broadcastVibrateSetting(AudioManager.VIBRATE_TYPE_RINGER); 7419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project broadcastVibrateSetting(AudioManager.VIBRATE_TYPE_NOTIFICATION); 742d589fea865e90859324f00d21765fa7d7759e465Jean-Michel Trivi 743d589fea865e90859324f00d21765fa7d7759e465Jean-Michel Trivi // Restore the default media button receiver from the system settings 744fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi mMediaFocusControl.restoreMediaButtonReceiver(); 7459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 747a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent private int rescaleIndex(int index, int srcStream, int dstStream) { 748a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent return (index * mStreamStates[dstStream].getMaxIndex() + mStreamStates[srcStream].getMaxIndex() / 2) / mStreamStates[srcStream].getMaxIndex(); 749a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent } 7509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /////////////////////////////////////////////////////////////////////////// 7529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // IPC methods 7539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /////////////////////////////////////////////////////////////////////////// 754fca1e603236b8d1681f784e77e3719d1d59c1428Jean-Michel Trivi /** @see AudioManager#isLocalOrRemoteMusicActive() */ 755fca1e603236b8d1681f784e77e3719d1d59c1428Jean-Michel Trivi public boolean isLocalOrRemoteMusicActive() { 756fca1e603236b8d1681f784e77e3719d1d59c1428Jean-Michel Trivi if (AudioSystem.isStreamActive(AudioSystem.STREAM_MUSIC, 0)) { 757fca1e603236b8d1681f784e77e3719d1d59c1428Jean-Michel Trivi // local / wired / BT playback active 758fca1e603236b8d1681f784e77e3719d1d59c1428Jean-Michel Trivi if (DEBUG_VOL) Log.d(TAG, "isLocalOrRemoteMusicActive(): local"); 759fca1e603236b8d1681f784e77e3719d1d59c1428Jean-Michel Trivi return true; 760fca1e603236b8d1681f784e77e3719d1d59c1428Jean-Michel Trivi } 761fca1e603236b8d1681f784e77e3719d1d59c1428Jean-Michel Trivi if (mMediaFocusControl.checkUpdateRemoteStateIfActive(AudioSystem.STREAM_MUSIC)) { 762fca1e603236b8d1681f784e77e3719d1d59c1428Jean-Michel Trivi // remote "cast-like" playback active 763fca1e603236b8d1681f784e77e3719d1d59c1428Jean-Michel Trivi if (DEBUG_VOL) Log.d(TAG, "isLocalOrRemoteMusicActive(): has PLAYBACK_TYPE_REMOTE"); 764fca1e603236b8d1681f784e77e3719d1d59c1428Jean-Michel Trivi return true; 765fca1e603236b8d1681f784e77e3719d1d59c1428Jean-Michel Trivi } 766fca1e603236b8d1681f784e77e3719d1d59c1428Jean-Michel Trivi if (AudioSystem.isStreamActiveRemotely(AudioSystem.STREAM_MUSIC, 0)) { 767fca1e603236b8d1681f784e77e3719d1d59c1428Jean-Michel Trivi // remote submix playback active 768fca1e603236b8d1681f784e77e3719d1d59c1428Jean-Michel Trivi if (DEBUG_VOL) Log.d(TAG, "isLocalOrRemoteMusicActive(): remote submix"); 769fca1e603236b8d1681f784e77e3719d1d59c1428Jean-Michel Trivi return true; 770fca1e603236b8d1681f784e77e3719d1d59c1428Jean-Michel Trivi } 771fca1e603236b8d1681f784e77e3719d1d59c1428Jean-Michel Trivi if (DEBUG_VOL) Log.d(TAG, "isLocalOrRemoteMusicActive(): no"); 772fca1e603236b8d1681f784e77e3719d1d59c1428Jean-Michel Trivi return false; 773fca1e603236b8d1681f784e77e3719d1d59c1428Jean-Michel Trivi } 7749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** @see AudioManager#adjustVolume(int, int) */ 776ba50b97cff80e73620a0e3d13cae169e095974a7Dianne Hackborn public void adjustVolume(int direction, int flags, String callingPackage) { 777ba50b97cff80e73620a0e3d13cae169e095974a7Dianne Hackborn adjustSuggestedStreamVolume(direction, AudioManager.USE_DEFAULT_STREAM_TYPE, flags, 778ba50b97cff80e73620a0e3d13cae169e095974a7Dianne Hackborn callingPackage); 7799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7813114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi /** @see AudioManager#adjustLocalOrRemoteStreamVolume(int, int) with current assumption 7823114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi * on streamType: fixed to STREAM_MUSIC */ 783ba50b97cff80e73620a0e3d13cae169e095974a7Dianne Hackborn public void adjustLocalOrRemoteStreamVolume(int streamType, int direction, 784ba50b97cff80e73620a0e3d13cae169e095974a7Dianne Hackborn String callingPackage) { 7853114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi if (DEBUG_VOL) Log.d(TAG, "adjustLocalOrRemoteStreamVolume(dir="+direction+")"); 786fca1e603236b8d1681f784e77e3719d1d59c1428Jean-Michel Trivi if (AudioSystem.isStreamActive(AudioSystem.STREAM_MUSIC, 0)) { 787ba50b97cff80e73620a0e3d13cae169e095974a7Dianne Hackborn adjustStreamVolume(AudioSystem.STREAM_MUSIC, direction, 0, callingPackage); 788fca1e603236b8d1681f784e77e3719d1d59c1428Jean-Michel Trivi } else if (mMediaFocusControl.checkUpdateRemoteStateIfActive(AudioSystem.STREAM_MUSIC)) { 789fca1e603236b8d1681f784e77e3719d1d59c1428Jean-Michel Trivi mMediaFocusControl.adjustRemoteVolume(AudioSystem.STREAM_MUSIC, direction, 0); 7903114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi } 7913114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi } 7923114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi 793961cae92540763226648813d111c5b5c3b0f1597Dianne Hackborn /** @see AudioManager#adjustVolume(int, int) */ 794ba50b97cff80e73620a0e3d13cae169e095974a7Dianne Hackborn public void adjustSuggestedStreamVolume(int direction, int suggestedStreamType, int flags, 795ba50b97cff80e73620a0e3d13cae169e095974a7Dianne Hackborn String callingPackage) { 7963114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi if (DEBUG_VOL) Log.d(TAG, "adjustSuggestedStreamVolume() stream="+suggestedStreamType); 797402f7f29634a9f68e7929be828a927a3e2f5efe9Eric Laurent int streamType; 79845c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent if (mVolumeControlStream != -1) { 79945c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent streamType = mVolumeControlStream; 800402f7f29634a9f68e7929be828a927a3e2f5efe9Eric Laurent } else { 801402f7f29634a9f68e7929be828a927a3e2f5efe9Eric Laurent streamType = getActiveStreamType(suggestedStreamType); 802402f7f29634a9f68e7929be828a927a3e2f5efe9Eric Laurent } 8039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8046243edd818b84adfbe712d5d233d6414b33653acAmith Yamasani // Play sounds on STREAM_RING only and if lock screen is not on. 8053114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi if ((streamType != STREAM_REMOTE_MUSIC) && 8063114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi (flags & AudioManager.FLAG_PLAY_SOUND) != 0 && 8076d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent ((mStreamVolumeAlias[streamType] != AudioSystem.STREAM_RING) 8086243edd818b84adfbe712d5d233d6414b33653acAmith Yamasani || (mKeyguardManager != null && mKeyguardManager.isKeyguardLocked()))) { 8099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project flags &= ~AudioManager.FLAG_PLAY_SOUND; 8109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8123114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi if (streamType == STREAM_REMOTE_MUSIC) { 8133114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi // don't play sounds for remote 814799448bee167c046ed715c7c4e3fe3486bf80d43Eric Laurent flags &= ~(AudioManager.FLAG_PLAY_SOUND|AudioManager.FLAG_FIXED_VOLUME); 8153114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi //if (DEBUG_VOL) Log.i(TAG, "Need to adjust remote volume: calling adjustRemoteVolume()"); 816fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi mMediaFocusControl.adjustRemoteVolume(AudioSystem.STREAM_MUSIC, direction, flags); 8173114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi } else { 818ba50b97cff80e73620a0e3d13cae169e095974a7Dianne Hackborn adjustStreamVolume(streamType, direction, flags, callingPackage); 8193114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi } 8209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** @see AudioManager#adjustStreamVolume(int, int, int) */ 823ba50b97cff80e73620a0e3d13cae169e095974a7Dianne Hackborn public void adjustStreamVolume(int streamType, int direction, int flags, 824ba50b97cff80e73620a0e3d13cae169e095974a7Dianne Hackborn String callingPackage) { 82583a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent if (mUseFixedVolume) { 82683a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent return; 82783a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent } 8283114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi if (DEBUG_VOL) Log.d(TAG, "adjustStreamVolume() stream="+streamType+", dir="+direction); 8293114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi 8309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ensureValidDirection(direction); 8319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ensureValidStreamType(streamType); 8329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 83396a33d1caad2fab0bc28891cfbf553f4b050bf0bEric Laurent // use stream type alias here so that streams with same alias have the same behavior, 83496a33d1caad2fab0bc28891cfbf553f4b050bf0bEric Laurent // including with regard to silent mode control (e.g the use of STREAM_RING below and in 83596a33d1caad2fab0bc28891cfbf553f4b050bf0bEric Laurent // checkForRingerModeChange() in place of STREAM_RING or STREAM_NOTIFICATION) 8366d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent int streamTypeAlias = mStreamVolumeAlias[streamType]; 837b024c30a80684ac08daef3137b7ba0d347fe3ce5Eric Laurent VolumeStreamState streamState = mStreamStates[streamTypeAlias]; 8389bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent 8399bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent final int device = getDeviceForStream(streamTypeAlias); 8403ef7549876a159dae1568429edcb57e4e7d08459Eric Laurent 84142b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent int aliasIndex = streamState.getIndex(device); 8429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project boolean adjustVolume = true; 8433ef7549876a159dae1568429edcb57e4e7d08459Eric Laurent int step; 844244820185269991186d07068b92985624cede4a5Eric Laurent 845c9d1d5f35091226e96fcfa91817480f589eb36e2Matthew Xie // skip a2dp absolute volume control request when the device 846c9d1d5f35091226e96fcfa91817480f589eb36e2Matthew Xie // is not an a2dp device 847c9d1d5f35091226e96fcfa91817480f589eb36e2Matthew Xie if ((device & AudioSystem.DEVICE_OUT_ALL_A2DP) == 0 && 848c9d1d5f35091226e96fcfa91817480f589eb36e2Matthew Xie (flags & AudioManager.FLAG_BLUETOOTH_ABS_VOLUME) != 0) { 849c9d1d5f35091226e96fcfa91817480f589eb36e2Matthew Xie return; 850c9d1d5f35091226e96fcfa91817480f589eb36e2Matthew Xie } 851c9d1d5f35091226e96fcfa91817480f589eb36e2Matthew Xie 852ba50b97cff80e73620a0e3d13cae169e095974a7Dianne Hackborn if (mAppOps.noteOp(STEAM_VOLUME_OPS[streamTypeAlias], Binder.getCallingUid(), 853ba50b97cff80e73620a0e3d13cae169e095974a7Dianne Hackborn callingPackage) != AppOpsManager.MODE_ALLOWED) { 854ba50b97cff80e73620a0e3d13cae169e095974a7Dianne Hackborn return; 855ba50b97cff80e73620a0e3d13cae169e095974a7Dianne Hackborn } 856ba50b97cff80e73620a0e3d13cae169e095974a7Dianne Hackborn 857fde16d5879ea88a971004c984093409468b6139cEric Laurent // reset any pending volume command 858fde16d5879ea88a971004c984093409468b6139cEric Laurent synchronized (mSafeMediaVolumeState) { 859fde16d5879ea88a971004c984093409468b6139cEric Laurent mPendingVolumeCommand = null; 860fde16d5879ea88a971004c984093409468b6139cEric Laurent } 861fde16d5879ea88a971004c984093409468b6139cEric Laurent 8623ef7549876a159dae1568429edcb57e4e7d08459Eric Laurent flags &= ~AudioManager.FLAG_FIXED_VOLUME; 8633ef7549876a159dae1568429edcb57e4e7d08459Eric Laurent if ((streamTypeAlias == AudioSystem.STREAM_MUSIC) && 8643ef7549876a159dae1568429edcb57e4e7d08459Eric Laurent ((device & mFixedVolumeDevices) != 0)) { 8653ef7549876a159dae1568429edcb57e4e7d08459Eric Laurent flags |= AudioManager.FLAG_FIXED_VOLUME; 8663ef7549876a159dae1568429edcb57e4e7d08459Eric Laurent 8673ef7549876a159dae1568429edcb57e4e7d08459Eric Laurent // Always toggle between max safe volume and 0 for fixed volume devices where safe 8683ef7549876a159dae1568429edcb57e4e7d08459Eric Laurent // volume is enforced, and max and 0 for the others. 8693ef7549876a159dae1568429edcb57e4e7d08459Eric Laurent // This is simulated by stepping by the full allowed volume range 8703ef7549876a159dae1568429edcb57e4e7d08459Eric Laurent if (mSafeMediaVolumeState == SAFE_MEDIA_VOLUME_ACTIVE && 8713ef7549876a159dae1568429edcb57e4e7d08459Eric Laurent (device & mSafeMediaVolumeDevices) != 0) { 8723ef7549876a159dae1568429edcb57e4e7d08459Eric Laurent step = mSafeMediaVolumeIndex; 8733ef7549876a159dae1568429edcb57e4e7d08459Eric Laurent } else { 8743ef7549876a159dae1568429edcb57e4e7d08459Eric Laurent step = streamState.getMaxIndex(); 8753ef7549876a159dae1568429edcb57e4e7d08459Eric Laurent } 8763ef7549876a159dae1568429edcb57e4e7d08459Eric Laurent if (aliasIndex != 0) { 8773ef7549876a159dae1568429edcb57e4e7d08459Eric Laurent aliasIndex = step; 8783ef7549876a159dae1568429edcb57e4e7d08459Eric Laurent } 8793ef7549876a159dae1568429edcb57e4e7d08459Eric Laurent } else { 8803ef7549876a159dae1568429edcb57e4e7d08459Eric Laurent // convert one UI step (+/-1) into a number of internal units on the stream alias 8813ef7549876a159dae1568429edcb57e4e7d08459Eric Laurent step = rescaleIndex(10, streamType, streamTypeAlias); 8823ef7549876a159dae1568429edcb57e4e7d08459Eric Laurent } 8833ef7549876a159dae1568429edcb57e4e7d08459Eric Laurent 88442b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent // If either the client forces allowing ringer modes for this adjustment, 88542b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent // or the stream type is one that is affected by ringer modes 88642b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent if (((flags & AudioManager.FLAG_ALLOW_RINGER_MODES) != 0) || 88742b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent (streamTypeAlias == getMasterStreamType())) { 88842b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent int ringerMode = getRingerMode(); 88942b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent // do not vibrate if already in vibrate mode 89042b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent if (ringerMode == AudioManager.RINGER_MODE_VIBRATE) { 89142b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent flags &= ~AudioManager.FLAG_VIBRATE; 89242b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent } 89342b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent // Check if the ringer mode changes with this volume adjustment. If 89442b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent // it does, it will handle adjusting the volume, so we won't below 89542b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent adjustVolume = checkForRingerModeChange(aliasIndex, direction, step); 89642b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent } 89742b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent 89842b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent int oldIndex = mStreamStates[streamType].getIndex(device); 89942b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent 90042b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent if (adjustVolume && (direction != AudioManager.ADJUST_SAME)) { 901c9d1d5f35091226e96fcfa91817480f589eb36e2Matthew Xie 9025a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du // Check if volume update should be send to AVRCP 903c9d1d5f35091226e96fcfa91817480f589eb36e2Matthew Xie if (streamTypeAlias == AudioSystem.STREAM_MUSIC && 904c9d1d5f35091226e96fcfa91817480f589eb36e2Matthew Xie (device & AudioSystem.DEVICE_OUT_ALL_A2DP) != 0 && 905c9d1d5f35091226e96fcfa91817480f589eb36e2Matthew Xie (flags & AudioManager.FLAG_BLUETOOTH_ABS_VOLUME) == 0) { 906c9d1d5f35091226e96fcfa91817480f589eb36e2Matthew Xie synchronized (mA2dpAvrcpLock) { 907c9d1d5f35091226e96fcfa91817480f589eb36e2Matthew Xie if (mA2dp != null && mAvrcpAbsVolSupported) { 908c9d1d5f35091226e96fcfa91817480f589eb36e2Matthew Xie mA2dp.adjustAvrcpAbsoluteVolume(direction); 909c9d1d5f35091226e96fcfa91817480f589eb36e2Matthew Xie } 9105a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du } 9115a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du } 912c9d1d5f35091226e96fcfa91817480f589eb36e2Matthew Xie 91342b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent if ((direction == AudioManager.ADJUST_RAISE) && 91442b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent !checkSafeMediaVolume(streamTypeAlias, aliasIndex + step, device)) { 91542b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent Log.e(TAG, "adjustStreamVolume() safe volume index = "+oldIndex); 91642b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent mVolumePanel.postDisplaySafeVolumeWarning(flags); 91742b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent } else if (streamState.adjustIndex(direction * step, device)) { 91842b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent // Post message to set system volume (it in turn will post a message 91942b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent // to persist). Do not change volume if stream is muted. 92042b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent sendMsg(mAudioHandler, 92142b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent MSG_SET_DEVICE_VOLUME, 92242b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent SENDMSG_QUEUE, 92342b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent device, 92442b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent 0, 92542b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent streamState, 92642b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent 0); 9274bbcc6549738f3d69831b2bd9eb4accec3e9920eEric Laurent } 9284bbcc6549738f3d69831b2bd9eb4accec3e9920eEric Laurent } 92942b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent int index = mStreamStates[streamType].getIndex(device); 93025101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent sendVolumeUpdate(streamType, oldIndex, index, flags); 9319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 933961cae92540763226648813d111c5b5c3b0f1597Dianne Hackborn /** @see AudioManager#adjustMasterVolume(int, int) */ 934ba50b97cff80e73620a0e3d13cae169e095974a7Dianne Hackborn public void adjustMasterVolume(int steps, int flags, String callingPackage) { 93583a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent if (mUseFixedVolume) { 93683a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent return; 93783a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent } 9386c798970ccb8759d1e613b57111daa8da0ab44c7Lei Zhang ensureValidSteps(steps); 9399760647dd0ee67e7c20f3e9d661d2006b1df0b54Mike Lockwood int volume = Math.round(AudioSystem.getMasterVolume() * MAX_MASTER_VOLUME); 9409760647dd0ee67e7c20f3e9d661d2006b1df0b54Mike Lockwood int delta = 0; 9416c798970ccb8759d1e613b57111daa8da0ab44c7Lei Zhang int numSteps = Math.abs(steps); 9426c798970ccb8759d1e613b57111daa8da0ab44c7Lei Zhang int direction = steps > 0 ? AudioManager.ADJUST_RAISE : AudioManager.ADJUST_LOWER; 9436c798970ccb8759d1e613b57111daa8da0ab44c7Lei Zhang for (int i = 0; i < numSteps; ++i) { 9446c798970ccb8759d1e613b57111daa8da0ab44c7Lei Zhang delta = findVolumeDelta(direction, volume); 9456c798970ccb8759d1e613b57111daa8da0ab44c7Lei Zhang volume += delta; 946cbdb49dc5e1b993a0bc5c68dbfb9486bfa0cd762Mike Lockwood } 94724b082f87e96c00d5c17d60c735423900be40e70RoboErik 9486c798970ccb8759d1e613b57111daa8da0ab44c7Lei Zhang //Log.d(TAG, "adjustMasterVolume volume: " + volume + " steps: " + steps); 949ba50b97cff80e73620a0e3d13cae169e095974a7Dianne Hackborn setMasterVolume(volume, flags, callingPackage); 950cbdb49dc5e1b993a0bc5c68dbfb9486bfa0cd762Mike Lockwood } 951cbdb49dc5e1b993a0bc5c68dbfb9486bfa0cd762Mike Lockwood 952fde16d5879ea88a971004c984093409468b6139cEric Laurent // StreamVolumeCommand contains the information needed to defer the process of 953fde16d5879ea88a971004c984093409468b6139cEric Laurent // setStreamVolume() in case the user has to acknowledge the safe volume warning message. 954fde16d5879ea88a971004c984093409468b6139cEric Laurent class StreamVolumeCommand { 955fde16d5879ea88a971004c984093409468b6139cEric Laurent public final int mStreamType; 956fde16d5879ea88a971004c984093409468b6139cEric Laurent public final int mIndex; 957fde16d5879ea88a971004c984093409468b6139cEric Laurent public final int mFlags; 958fde16d5879ea88a971004c984093409468b6139cEric Laurent public final int mDevice; 9593ef7549876a159dae1568429edcb57e4e7d08459Eric Laurent 960fde16d5879ea88a971004c984093409468b6139cEric Laurent StreamVolumeCommand(int streamType, int index, int flags, int device) { 961fde16d5879ea88a971004c984093409468b6139cEric Laurent mStreamType = streamType; 962fde16d5879ea88a971004c984093409468b6139cEric Laurent mIndex = index; 963fde16d5879ea88a971004c984093409468b6139cEric Laurent mFlags = flags; 964fde16d5879ea88a971004c984093409468b6139cEric Laurent mDevice = device; 9654bbcc6549738f3d69831b2bd9eb4accec3e9920eEric Laurent } 966fde16d5879ea88a971004c984093409468b6139cEric Laurent }; 9673ef7549876a159dae1568429edcb57e4e7d08459Eric Laurent 968fde16d5879ea88a971004c984093409468b6139cEric Laurent private void onSetStreamVolume(int streamType, int index, int flags, int device) { 96942b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent setStreamVolumeInt(mStreamVolumeAlias[streamType], index, device, false); 9703ef7549876a159dae1568429edcb57e4e7d08459Eric Laurent // setting volume on master stream type also controls silent mode 9713ef7549876a159dae1568429edcb57e4e7d08459Eric Laurent if (((flags & AudioManager.FLAG_ALLOW_RINGER_MODES) != 0) || 9723ef7549876a159dae1568429edcb57e4e7d08459Eric Laurent (mStreamVolumeAlias[streamType] == getMasterStreamType())) { 9733ef7549876a159dae1568429edcb57e4e7d08459Eric Laurent int newRingerMode; 9743ef7549876a159dae1568429edcb57e4e7d08459Eric Laurent if (index == 0) { 9753ef7549876a159dae1568429edcb57e4e7d08459Eric Laurent newRingerMode = mHasVibrator ? AudioManager.RINGER_MODE_VIBRATE 9763ef7549876a159dae1568429edcb57e4e7d08459Eric Laurent : AudioManager.RINGER_MODE_SILENT; 9773ef7549876a159dae1568429edcb57e4e7d08459Eric Laurent } else { 9783ef7549876a159dae1568429edcb57e4e7d08459Eric Laurent newRingerMode = AudioManager.RINGER_MODE_NORMAL; 9793ef7549876a159dae1568429edcb57e4e7d08459Eric Laurent } 9803ef7549876a159dae1568429edcb57e4e7d08459Eric Laurent setRingerMode(newRingerMode); 9813ef7549876a159dae1568429edcb57e4e7d08459Eric Laurent } 982fde16d5879ea88a971004c984093409468b6139cEric Laurent } 983fde16d5879ea88a971004c984093409468b6139cEric Laurent 984fde16d5879ea88a971004c984093409468b6139cEric Laurent /** @see AudioManager#setStreamVolume(int, int, int) */ 985ba50b97cff80e73620a0e3d13cae169e095974a7Dianne Hackborn public void setStreamVolume(int streamType, int index, int flags, String callingPackage) { 98683a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent if (mUseFixedVolume) { 98783a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent return; 98883a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent } 98983a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent 990fde16d5879ea88a971004c984093409468b6139cEric Laurent ensureValidStreamType(streamType); 991ba50b97cff80e73620a0e3d13cae169e095974a7Dianne Hackborn int streamTypeAlias = mStreamVolumeAlias[streamType]; 992ba50b97cff80e73620a0e3d13cae169e095974a7Dianne Hackborn VolumeStreamState streamState = mStreamStates[streamTypeAlias]; 993fde16d5879ea88a971004c984093409468b6139cEric Laurent 994fde16d5879ea88a971004c984093409468b6139cEric Laurent final int device = getDeviceForStream(streamType); 995fde16d5879ea88a971004c984093409468b6139cEric Laurent int oldIndex; 996fde16d5879ea88a971004c984093409468b6139cEric Laurent 997c9d1d5f35091226e96fcfa91817480f589eb36e2Matthew Xie // skip a2dp absolute volume control request when the device 998c9d1d5f35091226e96fcfa91817480f589eb36e2Matthew Xie // is not an a2dp device 999c9d1d5f35091226e96fcfa91817480f589eb36e2Matthew Xie if ((device & AudioSystem.DEVICE_OUT_ALL_A2DP) == 0 && 1000c9d1d5f35091226e96fcfa91817480f589eb36e2Matthew Xie (flags & AudioManager.FLAG_BLUETOOTH_ABS_VOLUME) != 0) { 1001c9d1d5f35091226e96fcfa91817480f589eb36e2Matthew Xie return; 1002c9d1d5f35091226e96fcfa91817480f589eb36e2Matthew Xie } 1003c9d1d5f35091226e96fcfa91817480f589eb36e2Matthew Xie 1004ba50b97cff80e73620a0e3d13cae169e095974a7Dianne Hackborn if (mAppOps.noteOp(STEAM_VOLUME_OPS[streamTypeAlias], Binder.getCallingUid(), 1005ba50b97cff80e73620a0e3d13cae169e095974a7Dianne Hackborn callingPackage) != AppOpsManager.MODE_ALLOWED) { 1006ba50b97cff80e73620a0e3d13cae169e095974a7Dianne Hackborn return; 1007ba50b97cff80e73620a0e3d13cae169e095974a7Dianne Hackborn } 1008ba50b97cff80e73620a0e3d13cae169e095974a7Dianne Hackborn 1009fde16d5879ea88a971004c984093409468b6139cEric Laurent synchronized (mSafeMediaVolumeState) { 1010fde16d5879ea88a971004c984093409468b6139cEric Laurent // reset any pending volume command 1011fde16d5879ea88a971004c984093409468b6139cEric Laurent mPendingVolumeCommand = null; 1012fde16d5879ea88a971004c984093409468b6139cEric Laurent 101342b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent oldIndex = streamState.getIndex(device); 1014fde16d5879ea88a971004c984093409468b6139cEric Laurent 1015ba50b97cff80e73620a0e3d13cae169e095974a7Dianne Hackborn index = rescaleIndex(index * 10, streamType, streamTypeAlias); 1016fde16d5879ea88a971004c984093409468b6139cEric Laurent 1017c9d1d5f35091226e96fcfa91817480f589eb36e2Matthew Xie if (streamTypeAlias == AudioSystem.STREAM_MUSIC && 1018c9d1d5f35091226e96fcfa91817480f589eb36e2Matthew Xie (device & AudioSystem.DEVICE_OUT_ALL_A2DP) != 0 && 1019c9d1d5f35091226e96fcfa91817480f589eb36e2Matthew Xie (flags & AudioManager.FLAG_BLUETOOTH_ABS_VOLUME) == 0) { 1020c9d1d5f35091226e96fcfa91817480f589eb36e2Matthew Xie synchronized (mA2dpAvrcpLock) { 1021c9d1d5f35091226e96fcfa91817480f589eb36e2Matthew Xie if (mA2dp != null && mAvrcpAbsVolSupported) { 1022c9d1d5f35091226e96fcfa91817480f589eb36e2Matthew Xie mA2dp.setAvrcpAbsoluteVolume(index); 1023c9d1d5f35091226e96fcfa91817480f589eb36e2Matthew Xie } 10245a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du } 10255a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du } 10265a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du 1027fde16d5879ea88a971004c984093409468b6139cEric Laurent flags &= ~AudioManager.FLAG_FIXED_VOLUME; 1028ba50b97cff80e73620a0e3d13cae169e095974a7Dianne Hackborn if ((streamTypeAlias == AudioSystem.STREAM_MUSIC) && 1029fde16d5879ea88a971004c984093409468b6139cEric Laurent ((device & mFixedVolumeDevices) != 0)) { 1030fde16d5879ea88a971004c984093409468b6139cEric Laurent flags |= AudioManager.FLAG_FIXED_VOLUME; 1031fde16d5879ea88a971004c984093409468b6139cEric Laurent 1032fde16d5879ea88a971004c984093409468b6139cEric Laurent // volume is either 0 or max allowed for fixed volume devices 1033fde16d5879ea88a971004c984093409468b6139cEric Laurent if (index != 0) { 1034fde16d5879ea88a971004c984093409468b6139cEric Laurent if (mSafeMediaVolumeState == SAFE_MEDIA_VOLUME_ACTIVE && 1035fde16d5879ea88a971004c984093409468b6139cEric Laurent (device & mSafeMediaVolumeDevices) != 0) { 1036fde16d5879ea88a971004c984093409468b6139cEric Laurent index = mSafeMediaVolumeIndex; 1037fde16d5879ea88a971004c984093409468b6139cEric Laurent } else { 1038fde16d5879ea88a971004c984093409468b6139cEric Laurent index = streamState.getMaxIndex(); 1039fde16d5879ea88a971004c984093409468b6139cEric Laurent } 1040fde16d5879ea88a971004c984093409468b6139cEric Laurent } 1041fde16d5879ea88a971004c984093409468b6139cEric Laurent } 1042fde16d5879ea88a971004c984093409468b6139cEric Laurent 1043ba50b97cff80e73620a0e3d13cae169e095974a7Dianne Hackborn if (!checkSafeMediaVolume(streamTypeAlias, index, device)) { 1044fde16d5879ea88a971004c984093409468b6139cEric Laurent mVolumePanel.postDisplaySafeVolumeWarning(flags); 1045fde16d5879ea88a971004c984093409468b6139cEric Laurent mPendingVolumeCommand = new StreamVolumeCommand( 1046fde16d5879ea88a971004c984093409468b6139cEric Laurent streamType, index, flags, device); 1047fde16d5879ea88a971004c984093409468b6139cEric Laurent } else { 1048fde16d5879ea88a971004c984093409468b6139cEric Laurent onSetStreamVolume(streamType, index, flags, device); 104942b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent index = mStreamStates[streamType].getIndex(device); 1050fde16d5879ea88a971004c984093409468b6139cEric Laurent } 1051fde16d5879ea88a971004c984093409468b6139cEric Laurent } 105225101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent sendVolumeUpdate(streamType, oldIndex, index, flags); 10539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 105545c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent /** @see AudioManager#forceVolumeControlStream(int) */ 105645c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent public void forceVolumeControlStream(int streamType, IBinder cb) { 105745c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent synchronized(mForceControlStreamLock) { 105845c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent mVolumeControlStream = streamType; 105945c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent if (mVolumeControlStream == -1) { 106045c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent if (mForceControlStreamClient != null) { 106145c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent mForceControlStreamClient.release(); 106245c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent mForceControlStreamClient = null; 106345c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent } 106445c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent } else { 106545c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent mForceControlStreamClient = new ForceControlStreamClient(cb); 106645c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent } 106745c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent } 106845c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent } 106945c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent 107045c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent private class ForceControlStreamClient implements IBinder.DeathRecipient { 107145c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent private IBinder mCb; // To be notified of client's death 107245c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent 107345c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent ForceControlStreamClient(IBinder cb) { 107445c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent if (cb != null) { 107545c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent try { 107645c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent cb.linkToDeath(this, 0); 107745c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent } catch (RemoteException e) { 107845c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent // Client has died! 107945c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent Log.w(TAG, "ForceControlStreamClient() could not link to "+cb+" binder death"); 108045c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent cb = null; 108145c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent } 108245c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent } 108345c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent mCb = cb; 108445c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent } 108545c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent 108645c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent public void binderDied() { 108745c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent synchronized(mForceControlStreamLock) { 108845c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent Log.w(TAG, "SCO client died"); 108945c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent if (mForceControlStreamClient != this) { 109045c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent Log.w(TAG, "unregistered control stream client died"); 109145c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent } else { 109245c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent mForceControlStreamClient = null; 109345c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent mVolumeControlStream = -1; 109445c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent } 109545c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent } 109645c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent } 109745c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent 109845c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent public void release() { 109945c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent if (mCb != null) { 110045c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent mCb.unlinkToDeath(this, 0); 110145c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent mCb = null; 110245c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent } 110345c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent } 110445c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent } 110545c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent 11066c798970ccb8759d1e613b57111daa8da0ab44c7Lei Zhang private int findVolumeDelta(int direction, int volume) { 11076c798970ccb8759d1e613b57111daa8da0ab44c7Lei Zhang int delta = 0; 11086c798970ccb8759d1e613b57111daa8da0ab44c7Lei Zhang if (direction == AudioManager.ADJUST_RAISE) { 11096c798970ccb8759d1e613b57111daa8da0ab44c7Lei Zhang if (volume == MAX_MASTER_VOLUME) { 11106c798970ccb8759d1e613b57111daa8da0ab44c7Lei Zhang return 0; 11116c798970ccb8759d1e613b57111daa8da0ab44c7Lei Zhang } 11126c798970ccb8759d1e613b57111daa8da0ab44c7Lei Zhang // This is the default value if we make it to the end 11136c798970ccb8759d1e613b57111daa8da0ab44c7Lei Zhang delta = mMasterVolumeRamp[1]; 11146c798970ccb8759d1e613b57111daa8da0ab44c7Lei Zhang // If we're raising the volume move down the ramp array until we 11156c798970ccb8759d1e613b57111daa8da0ab44c7Lei Zhang // find the volume we're above and use that groups delta. 11166c798970ccb8759d1e613b57111daa8da0ab44c7Lei Zhang for (int i = mMasterVolumeRamp.length - 1; i > 1; i -= 2) { 11176c798970ccb8759d1e613b57111daa8da0ab44c7Lei Zhang if (volume >= mMasterVolumeRamp[i - 1]) { 11186c798970ccb8759d1e613b57111daa8da0ab44c7Lei Zhang delta = mMasterVolumeRamp[i]; 11196c798970ccb8759d1e613b57111daa8da0ab44c7Lei Zhang break; 11206c798970ccb8759d1e613b57111daa8da0ab44c7Lei Zhang } 11216c798970ccb8759d1e613b57111daa8da0ab44c7Lei Zhang } 11226c798970ccb8759d1e613b57111daa8da0ab44c7Lei Zhang } else if (direction == AudioManager.ADJUST_LOWER){ 11236c798970ccb8759d1e613b57111daa8da0ab44c7Lei Zhang if (volume == 0) { 11246c798970ccb8759d1e613b57111daa8da0ab44c7Lei Zhang return 0; 11256c798970ccb8759d1e613b57111daa8da0ab44c7Lei Zhang } 11266c798970ccb8759d1e613b57111daa8da0ab44c7Lei Zhang int length = mMasterVolumeRamp.length; 11276c798970ccb8759d1e613b57111daa8da0ab44c7Lei Zhang // This is the default value if we make it to the end 11286c798970ccb8759d1e613b57111daa8da0ab44c7Lei Zhang delta = -mMasterVolumeRamp[length - 1]; 11296c798970ccb8759d1e613b57111daa8da0ab44c7Lei Zhang // If we're lowering the volume move up the ramp array until we 11306c798970ccb8759d1e613b57111daa8da0ab44c7Lei Zhang // find the volume we're below and use the group below it's delta 11316c798970ccb8759d1e613b57111daa8da0ab44c7Lei Zhang for (int i = 2; i < length; i += 2) { 11326c798970ccb8759d1e613b57111daa8da0ab44c7Lei Zhang if (volume <= mMasterVolumeRamp[i]) { 11336c798970ccb8759d1e613b57111daa8da0ab44c7Lei Zhang delta = -mMasterVolumeRamp[i - 1]; 11346c798970ccb8759d1e613b57111daa8da0ab44c7Lei Zhang break; 11356c798970ccb8759d1e613b57111daa8da0ab44c7Lei Zhang } 11366c798970ccb8759d1e613b57111daa8da0ab44c7Lei Zhang } 11376c798970ccb8759d1e613b57111daa8da0ab44c7Lei Zhang } 11386c798970ccb8759d1e613b57111daa8da0ab44c7Lei Zhang return delta; 11396c798970ccb8759d1e613b57111daa8da0ab44c7Lei Zhang } 11406c798970ccb8759d1e613b57111daa8da0ab44c7Lei Zhang 11415ac72a29593ab9a20337a2225df52bdf4754be02Dianne Hackborn private void sendBroadcastToAll(Intent intent) { 11425ac72a29593ab9a20337a2225df52bdf4754be02Dianne Hackborn final long ident = Binder.clearCallingIdentity(); 11435ac72a29593ab9a20337a2225df52bdf4754be02Dianne Hackborn try { 11445ac72a29593ab9a20337a2225df52bdf4754be02Dianne Hackborn mContext.sendBroadcastAsUser(intent, UserHandle.ALL); 11455ac72a29593ab9a20337a2225df52bdf4754be02Dianne Hackborn } finally { 11465ac72a29593ab9a20337a2225df52bdf4754be02Dianne Hackborn Binder.restoreCallingIdentity(ident); 11475ac72a29593ab9a20337a2225df52bdf4754be02Dianne Hackborn } 11485ac72a29593ab9a20337a2225df52bdf4754be02Dianne Hackborn } 11495ac72a29593ab9a20337a2225df52bdf4754be02Dianne Hackborn 11505ac72a29593ab9a20337a2225df52bdf4754be02Dianne Hackborn private void sendStickyBroadcastToAll(Intent intent) { 11515ac72a29593ab9a20337a2225df52bdf4754be02Dianne Hackborn final long ident = Binder.clearCallingIdentity(); 11525ac72a29593ab9a20337a2225df52bdf4754be02Dianne Hackborn try { 11535ac72a29593ab9a20337a2225df52bdf4754be02Dianne Hackborn mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL); 11545ac72a29593ab9a20337a2225df52bdf4754be02Dianne Hackborn } finally { 11555ac72a29593ab9a20337a2225df52bdf4754be02Dianne Hackborn Binder.restoreCallingIdentity(ident); 11565ac72a29593ab9a20337a2225df52bdf4754be02Dianne Hackborn } 11575ac72a29593ab9a20337a2225df52bdf4754be02Dianne Hackborn } 11585ac72a29593ab9a20337a2225df52bdf4754be02Dianne Hackborn 115925101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent // UI update and Broadcast Intent 116025101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent private void sendVolumeUpdate(int streamType, int oldIndex, int index, int flags) { 116125101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent if (!mVoiceCapable && (streamType == AudioSystem.STREAM_RING)) { 116225101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent streamType = AudioSystem.STREAM_NOTIFICATION; 116325101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent } 116425101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent 116525101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent mVolumePanel.postVolumeChanged(streamType, flags); 116625101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent 11674bbcc6549738f3d69831b2bd9eb4accec3e9920eEric Laurent if ((flags & AudioManager.FLAG_FIXED_VOLUME) == 0) { 11684bbcc6549738f3d69831b2bd9eb4accec3e9920eEric Laurent oldIndex = (oldIndex + 5) / 10; 11694bbcc6549738f3d69831b2bd9eb4accec3e9920eEric Laurent index = (index + 5) / 10; 11704bbcc6549738f3d69831b2bd9eb4accec3e9920eEric Laurent Intent intent = new Intent(AudioManager.VOLUME_CHANGED_ACTION); 11714bbcc6549738f3d69831b2bd9eb4accec3e9920eEric Laurent intent.putExtra(AudioManager.EXTRA_VOLUME_STREAM_TYPE, streamType); 11724bbcc6549738f3d69831b2bd9eb4accec3e9920eEric Laurent intent.putExtra(AudioManager.EXTRA_VOLUME_STREAM_VALUE, index); 11734bbcc6549738f3d69831b2bd9eb4accec3e9920eEric Laurent intent.putExtra(AudioManager.EXTRA_PREV_VOLUME_STREAM_VALUE, oldIndex); 11744bbcc6549738f3d69831b2bd9eb4accec3e9920eEric Laurent sendBroadcastToAll(intent); 11754bbcc6549738f3d69831b2bd9eb4accec3e9920eEric Laurent } 11769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 11779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11780dc37cce9d564ae43883c8dc8672b9266b881e63Mike Lockwood // UI update and Broadcast Intent 11790dc37cce9d564ae43883c8dc8672b9266b881e63Mike Lockwood private void sendMasterVolumeUpdate(int flags, int oldVolume, int newVolume) { 11800dc37cce9d564ae43883c8dc8672b9266b881e63Mike Lockwood mVolumePanel.postMasterVolumeChanged(flags); 11810dc37cce9d564ae43883c8dc8672b9266b881e63Mike Lockwood 11820dc37cce9d564ae43883c8dc8672b9266b881e63Mike Lockwood Intent intent = new Intent(AudioManager.MASTER_VOLUME_CHANGED_ACTION); 11830dc37cce9d564ae43883c8dc8672b9266b881e63Mike Lockwood intent.putExtra(AudioManager.EXTRA_PREV_MASTER_VOLUME_VALUE, oldVolume); 11840dc37cce9d564ae43883c8dc8672b9266b881e63Mike Lockwood intent.putExtra(AudioManager.EXTRA_MASTER_VOLUME_VALUE, newVolume); 11855ac72a29593ab9a20337a2225df52bdf4754be02Dianne Hackborn sendBroadcastToAll(intent); 11860dc37cce9d564ae43883c8dc8672b9266b881e63Mike Lockwood } 11870dc37cce9d564ae43883c8dc8672b9266b881e63Mike Lockwood 11880dc37cce9d564ae43883c8dc8672b9266b881e63Mike Lockwood // UI update and Broadcast Intent 11890dc37cce9d564ae43883c8dc8672b9266b881e63Mike Lockwood private void sendMasterMuteUpdate(boolean muted, int flags) { 11900dc37cce9d564ae43883c8dc8672b9266b881e63Mike Lockwood mVolumePanel.postMasterMuteChanged(flags); 119157978ed86286a33d5b1a0fd000ca3406ba9d87b3Justin Koh broadcastMasterMuteStatus(muted); 119257978ed86286a33d5b1a0fd000ca3406ba9d87b3Justin Koh } 11930dc37cce9d564ae43883c8dc8672b9266b881e63Mike Lockwood 119457978ed86286a33d5b1a0fd000ca3406ba9d87b3Justin Koh private void broadcastMasterMuteStatus(boolean muted) { 11950dc37cce9d564ae43883c8dc8672b9266b881e63Mike Lockwood Intent intent = new Intent(AudioManager.MASTER_MUTE_CHANGED_ACTION); 11960dc37cce9d564ae43883c8dc8672b9266b881e63Mike Lockwood intent.putExtra(AudioManager.EXTRA_MASTER_VOLUME_MUTED, muted); 119757978ed86286a33d5b1a0fd000ca3406ba9d87b3Justin Koh intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT 119857978ed86286a33d5b1a0fd000ca3406ba9d87b3Justin Koh | Intent.FLAG_RECEIVER_REPLACE_PENDING); 11995ac72a29593ab9a20337a2225df52bdf4754be02Dianne Hackborn sendStickyBroadcastToAll(intent); 12000dc37cce9d564ae43883c8dc8672b9266b881e63Mike Lockwood } 12010dc37cce9d564ae43883c8dc8672b9266b881e63Mike Lockwood 12029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 12039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Sets the stream state's index, and posts a message to set system volume. 12049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * This will not call out to the UI. Assumes a valid stream type. 12059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 12069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param streamType Type of the stream 12079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param index Desired volume index of the stream 12089bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent * @param device the device whose volume must be changed 12099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param force If true, set the volume even if the desired volume is same 12109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * as the current volume. 12119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 12129bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent private void setStreamVolumeInt(int streamType, 12139bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent int index, 12149bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent int device, 121542b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent boolean force) { 12169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project VolumeStreamState streamState = mStreamStates[streamType]; 12175b4e654d0c7de8e4d58d73e73b0d5220f19b68f7Eric Laurent 121842b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent if (streamState.setIndex(index, device) || force) { 121942b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent // Post message to set system volume (it in turn will post a message 122042b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent // to persist). 122142b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent sendMsg(mAudioHandler, 122242b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent MSG_SET_DEVICE_VOLUME, 122342b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent SENDMSG_QUEUE, 122442b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent device, 122542b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent 0, 122642b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent streamState, 122742b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent 0); 12289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 12299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 12309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 12319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** @see AudioManager#setStreamSolo(int, boolean) */ 12329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void setStreamSolo(int streamType, boolean state, IBinder cb) { 123383a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent if (mUseFixedVolume) { 123483a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent return; 123583a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent } 123683a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent 12379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int stream = 0; stream < mStreamStates.length; stream++) { 12389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!isStreamAffectedByMute(stream) || stream == streamType) continue; 12399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mStreamStates[stream].mute(cb, state); 12409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 12419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 12429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 12439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** @see AudioManager#setStreamMute(int, boolean) */ 12449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void setStreamMute(int streamType, boolean state, IBinder cb) { 124583a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent if (mUseFixedVolume) { 124683a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent return; 124783a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent } 124883a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent 12499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (isStreamAffectedByMute(streamType)) { 12509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mStreamStates[streamType].mute(cb, state); 12519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 12529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 12539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 125425101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent /** get stream mute state. */ 125525101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent public boolean isStreamMute(int streamType) { 125642b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent return mStreamStates[streamType].isMuted(); 125725101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent } 125825101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent 1259961cae92540763226648813d111c5b5c3b0f1597Dianne Hackborn /** @see AudioManager#setMasterMute(boolean, int) */ 12600273af55cf68d54d26d154b44d105d40fed79701Justin Koh public void setMasterMute(boolean state, int flags, IBinder cb) { 126183a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent if (mUseFixedVolume) { 126283a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent return; 126383a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent } 126483a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent 12651ce5b26d707e0086e09af3cd0428f1b441145261Jason Simmons if (state != AudioSystem.getMasterMute()) { 12661ce5b26d707e0086e09af3cd0428f1b441145261Jason Simmons AudioSystem.setMasterMute(state); 126757978ed86286a33d5b1a0fd000ca3406ba9d87b3Justin Koh // Post a persist master volume msg 126875cf9e19a575c28c200c02c0ab6f83bb79f5c50dJustin Koh sendMsg(mAudioHandler, MSG_PERSIST_MASTER_VOLUME_MUTE, SENDMSG_REPLACE, state ? 1 126957978ed86286a33d5b1a0fd000ca3406ba9d87b3Justin Koh : 0, 0, null, PERSIST_DELAY); 12700273af55cf68d54d26d154b44d105d40fed79701Justin Koh sendMasterMuteUpdate(state, flags); 12711ce5b26d707e0086e09af3cd0428f1b441145261Jason Simmons } 1272ce952c8e13c535bedde77bcdb94dfcc7508475aaMike Lockwood } 1273ce952c8e13c535bedde77bcdb94dfcc7508475aaMike Lockwood 1274ce952c8e13c535bedde77bcdb94dfcc7508475aaMike Lockwood /** get master mute state. */ 1275ce952c8e13c535bedde77bcdb94dfcc7508475aaMike Lockwood public boolean isMasterMute() { 12763194ea94348bce8e7ee9f803698d877f46f8279aMike Lockwood return AudioSystem.getMasterMute(); 1277ce952c8e13c535bedde77bcdb94dfcc7508475aaMike Lockwood } 1278ce952c8e13c535bedde77bcdb94dfcc7508475aaMike Lockwood 1279fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi protected static int getMaxStreamVolume(int streamType) { 1280fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi return MAX_STREAM_VOLUME[streamType]; 1281fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi } 1282fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi 12839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** @see AudioManager#getStreamVolume(int) */ 12849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int getStreamVolume(int streamType) { 12859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ensureValidStreamType(streamType); 12869bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent int device = getDeviceForStream(streamType); 128742b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent int index = mStreamStates[streamType].getIndex(device); 12884bbcc6549738f3d69831b2bd9eb4accec3e9920eEric Laurent 128942b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent // by convention getStreamVolume() returns 0 when a stream is muted. 129042b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent if (mStreamStates[streamType].isMuted()) { 129142b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent index = 0; 129242b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent } 12933ef7549876a159dae1568429edcb57e4e7d08459Eric Laurent if (index != 0 && (mStreamVolumeAlias[streamType] == AudioSystem.STREAM_MUSIC) && 12944bbcc6549738f3d69831b2bd9eb4accec3e9920eEric Laurent (device & mFixedVolumeDevices) != 0) { 12954bbcc6549738f3d69831b2bd9eb4accec3e9920eEric Laurent index = mStreamStates[streamType].getMaxIndex(); 12964bbcc6549738f3d69831b2bd9eb4accec3e9920eEric Laurent } 12974bbcc6549738f3d69831b2bd9eb4accec3e9920eEric Laurent return (index + 5) / 10; 12989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 12999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 13004767690f09ea3447b8c5c32fb28d27650aa18e00Mike Lockwood public int getMasterVolume() { 1301ce952c8e13c535bedde77bcdb94dfcc7508475aaMike Lockwood if (isMasterMute()) return 0; 1302ce952c8e13c535bedde77bcdb94dfcc7508475aaMike Lockwood return getLastAudibleMasterVolume(); 13038dc1dabd254249b7ddb8743e88fdb96580ffc585Mike Lockwood } 13048dc1dabd254249b7ddb8743e88fdb96580ffc585Mike Lockwood 1305ba50b97cff80e73620a0e3d13cae169e095974a7Dianne Hackborn public void setMasterVolume(int volume, int flags, String callingPackage) { 130683a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent if (mUseFixedVolume) { 130783a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent return; 130883a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent } 130983a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent 1310ba50b97cff80e73620a0e3d13cae169e095974a7Dianne Hackborn if (mAppOps.noteOp(AppOpsManager.OP_AUDIO_MASTER_VOLUME, Binder.getCallingUid(), 1311ba50b97cff80e73620a0e3d13cae169e095974a7Dianne Hackborn callingPackage) != AppOpsManager.MODE_ALLOWED) { 1312ba50b97cff80e73620a0e3d13cae169e095974a7Dianne Hackborn return; 1313ba50b97cff80e73620a0e3d13cae169e095974a7Dianne Hackborn } 1314ba50b97cff80e73620a0e3d13cae169e095974a7Dianne Hackborn 13159760647dd0ee67e7c20f3e9d661d2006b1df0b54Mike Lockwood if (volume < 0) { 13169760647dd0ee67e7c20f3e9d661d2006b1df0b54Mike Lockwood volume = 0; 13179760647dd0ee67e7c20f3e9d661d2006b1df0b54Mike Lockwood } else if (volume > MAX_MASTER_VOLUME) { 13189760647dd0ee67e7c20f3e9d661d2006b1df0b54Mike Lockwood volume = MAX_MASTER_VOLUME; 13199760647dd0ee67e7c20f3e9d661d2006b1df0b54Mike Lockwood } 13205c55a051ad7d86a464fb91426f1ea3c0250e38b3Mike Lockwood doSetMasterVolume((float)volume / MAX_MASTER_VOLUME, flags); 13215c55a051ad7d86a464fb91426f1ea3c0250e38b3Mike Lockwood } 13225c55a051ad7d86a464fb91426f1ea3c0250e38b3Mike Lockwood 13235c55a051ad7d86a464fb91426f1ea3c0250e38b3Mike Lockwood private void doSetMasterVolume(float volume, int flags) { 13245c55a051ad7d86a464fb91426f1ea3c0250e38b3Mike Lockwood // don't allow changing master volume when muted 13255c55a051ad7d86a464fb91426f1ea3c0250e38b3Mike Lockwood if (!AudioSystem.getMasterMute()) { 13265c55a051ad7d86a464fb91426f1ea3c0250e38b3Mike Lockwood int oldVolume = getMasterVolume(); 13275c55a051ad7d86a464fb91426f1ea3c0250e38b3Mike Lockwood AudioSystem.setMasterVolume(volume); 13285c55a051ad7d86a464fb91426f1ea3c0250e38b3Mike Lockwood 13295c55a051ad7d86a464fb91426f1ea3c0250e38b3Mike Lockwood int newVolume = getMasterVolume(); 13305c55a051ad7d86a464fb91426f1ea3c0250e38b3Mike Lockwood if (newVolume != oldVolume) { 13315c55a051ad7d86a464fb91426f1ea3c0250e38b3Mike Lockwood // Post a persist master volume msg 13325c55a051ad7d86a464fb91426f1ea3c0250e38b3Mike Lockwood sendMsg(mAudioHandler, MSG_PERSIST_MASTER_VOLUME, SENDMSG_REPLACE, 13335c55a051ad7d86a464fb91426f1ea3c0250e38b3Mike Lockwood Math.round(volume * (float)1000.0), 0, null, PERSIST_DELAY); 13345c55a051ad7d86a464fb91426f1ea3c0250e38b3Mike Lockwood } 13353caba517253d1703fc29b50740c4567b932279fbJustin Koh // Send the volume update regardless whether there was a change. 13363caba517253d1703fc29b50740c4567b932279fbJustin Koh sendMasterVolumeUpdate(flags, oldVolume, newVolume); 13375c55a051ad7d86a464fb91426f1ea3c0250e38b3Mike Lockwood } 13388dc1dabd254249b7ddb8743e88fdb96580ffc585Mike Lockwood } 13398dc1dabd254249b7ddb8743e88fdb96580ffc585Mike Lockwood 13409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** @see AudioManager#getStreamMaxVolume(int) */ 13419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int getStreamMaxVolume(int streamType) { 13429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ensureValidStreamType(streamType); 1343a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent return (mStreamStates[streamType].getMaxIndex() + 5) / 10; 13449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 13459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 13464767690f09ea3447b8c5c32fb28d27650aa18e00Mike Lockwood public int getMasterMaxVolume() { 13474767690f09ea3447b8c5c32fb28d27650aa18e00Mike Lockwood return MAX_MASTER_VOLUME; 13484767690f09ea3447b8c5c32fb28d27650aa18e00Mike Lockwood } 134925101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent 135025101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent /** Get last audible volume before stream was muted. */ 135125101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent public int getLastAudibleStreamVolume(int streamType) { 135225101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent ensureValidStreamType(streamType); 13539bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent int device = getDeviceForStream(streamType); 135442b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent return (mStreamStates[streamType].getIndex(device) + 5) / 10; 135525101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent } 135625101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent 1357ce952c8e13c535bedde77bcdb94dfcc7508475aaMike Lockwood /** Get last audible master volume before it was muted. */ 1358ce952c8e13c535bedde77bcdb94dfcc7508475aaMike Lockwood public int getLastAudibleMasterVolume() { 1359ce952c8e13c535bedde77bcdb94dfcc7508475aaMike Lockwood return Math.round(AudioSystem.getMasterVolume() * MAX_MASTER_VOLUME); 1360ce952c8e13c535bedde77bcdb94dfcc7508475aaMike Lockwood } 1361ce952c8e13c535bedde77bcdb94dfcc7508475aaMike Lockwood 1362961cae92540763226648813d111c5b5c3b0f1597Dianne Hackborn /** @see AudioManager#getMasterStreamType() */ 13636d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent public int getMasterStreamType() { 13646d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent if (mVoiceCapable) { 13656d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent return AudioSystem.STREAM_RING; 13666d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent } else { 13676d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent return AudioSystem.STREAM_MUSIC; 13686d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent } 13696d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent } 13706d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent 13719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** @see AudioManager#getRingerMode() */ 13729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int getRingerMode() { 1373ba195ebc76f23b6679443724ab58c9dc9f2df884Glenn Kasten synchronized(mSettingsLock) { 1374ba195ebc76f23b6679443724ab58c9dc9f2df884Glenn Kasten return mRingerMode; 1375ba195ebc76f23b6679443724ab58c9dc9f2df884Glenn Kasten } 1376ba195ebc76f23b6679443724ab58c9dc9f2df884Glenn Kasten } 1377ba195ebc76f23b6679443724ab58c9dc9f2df884Glenn Kasten 1378ba195ebc76f23b6679443724ab58c9dc9f2df884Glenn Kasten private void ensureValidRingerMode(int ringerMode) { 1379ba195ebc76f23b6679443724ab58c9dc9f2df884Glenn Kasten if (!AudioManager.isValidRingerMode(ringerMode)) { 1380ba195ebc76f23b6679443724ab58c9dc9f2df884Glenn Kasten throw new IllegalArgumentException("Bad ringer mode " + ringerMode); 1381ba195ebc76f23b6679443724ab58c9dc9f2df884Glenn Kasten } 13829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 13839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 13849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** @see AudioManager#setRingerMode(int) */ 13859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void setRingerMode(int ringerMode) { 138683a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent if (mUseFixedVolume) { 138783a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent return; 138883a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent } 138983a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent 1390244820185269991186d07068b92985624cede4a5Eric Laurent if ((ringerMode == AudioManager.RINGER_MODE_VIBRATE) && !mHasVibrator) { 1391244820185269991186d07068b92985624cede4a5Eric Laurent ringerMode = AudioManager.RINGER_MODE_SILENT; 1392244820185269991186d07068b92985624cede4a5Eric Laurent } 1393ba195ebc76f23b6679443724ab58c9dc9f2df884Glenn Kasten if (ringerMode != getRingerMode()) { 1394ba195ebc76f23b6679443724ab58c9dc9f2df884Glenn Kasten setRingerModeInt(ringerMode, true); 1395ba195ebc76f23b6679443724ab58c9dc9f2df884Glenn Kasten // Send sticky broadcast 1396ba195ebc76f23b6679443724ab58c9dc9f2df884Glenn Kasten broadcastRingerMode(ringerMode); 1397b109615ebebd6f3b9ae789412279f576c3ace46bJason Parekh } 1398b109615ebebd6f3b9ae789412279f576c3ace46bJason Parekh } 13999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 14004050c93601b3c3609b21cc1e18a29b64747e7fa9Eric Laurent private void setRingerModeInt(int ringerMode, boolean persist) { 1401ba195ebc76f23b6679443724ab58c9dc9f2df884Glenn Kasten synchronized(mSettingsLock) { 1402ba195ebc76f23b6679443724ab58c9dc9f2df884Glenn Kasten mRingerMode = ringerMode; 1403ba195ebc76f23b6679443724ab58c9dc9f2df884Glenn Kasten } 1404b109615ebebd6f3b9ae789412279f576c3ace46bJason Parekh 14055b4e654d0c7de8e4d58d73e73b0d5220f19b68f7Eric Laurent // Mute stream if not previously muted by ringer mode and ringer mode 14065b4e654d0c7de8e4d58d73e73b0d5220f19b68f7Eric Laurent // is not RINGER_MODE_NORMAL and stream is affected by ringer mode. 14075b4e654d0c7de8e4d58d73e73b0d5220f19b68f7Eric Laurent // Unmute stream if previously muted by ringer mode and ringer mode 14085b4e654d0c7de8e4d58d73e73b0d5220f19b68f7Eric Laurent // is RINGER_MODE_NORMAL or stream is not affected by ringer mode. 1409b109615ebebd6f3b9ae789412279f576c3ace46bJason Parekh int numStreamTypes = AudioSystem.getNumStreamTypes(); 14105b4e654d0c7de8e4d58d73e73b0d5220f19b68f7Eric Laurent for (int streamType = numStreamTypes - 1; streamType >= 0; streamType--) { 14115b4e654d0c7de8e4d58d73e73b0d5220f19b68f7Eric Laurent if (isStreamMutedByRingerMode(streamType)) { 14125b4e654d0c7de8e4d58d73e73b0d5220f19b68f7Eric Laurent if (!isStreamAffectedByRingerMode(streamType) || 1413ba195ebc76f23b6679443724ab58c9dc9f2df884Glenn Kasten ringerMode == AudioManager.RINGER_MODE_NORMAL) { 1414b024c30a80684ac08daef3137b7ba0d347fe3ce5Eric Laurent // ring and notifications volume should never be 0 when not silenced 1415b024c30a80684ac08daef3137b7ba0d347fe3ce5Eric Laurent // on voice capable devices 1416b024c30a80684ac08daef3137b7ba0d347fe3ce5Eric Laurent if (mVoiceCapable && 14176d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent mStreamVolumeAlias[streamType] == AudioSystem.STREAM_RING) { 14183172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent synchronized (mStreamStates[streamType]) { 141942b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent Set set = mStreamStates[streamType].mIndex.entrySet(); 14203172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent Iterator i = set.iterator(); 14213172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent while (i.hasNext()) { 14223172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent Map.Entry entry = (Map.Entry)i.next(); 14233172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent if ((Integer)entry.getValue() == 0) { 14243172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent entry.setValue(10); 14253172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent } 14269bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent } 14279bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent } 1428b024c30a80684ac08daef3137b7ba0d347fe3ce5Eric Laurent } 14295b4e654d0c7de8e4d58d73e73b0d5220f19b68f7Eric Laurent mStreamStates[streamType].mute(null, false); 14305b4e654d0c7de8e4d58d73e73b0d5220f19b68f7Eric Laurent mRingerModeMutedStreams &= ~(1 << streamType); 14319bcf401d13d47416043a704430388abd59aef7cdEric Laurent } 14325b4e654d0c7de8e4d58d73e73b0d5220f19b68f7Eric Laurent } else { 14335b4e654d0c7de8e4d58d73e73b0d5220f19b68f7Eric Laurent if (isStreamAffectedByRingerMode(streamType) && 1434ba195ebc76f23b6679443724ab58c9dc9f2df884Glenn Kasten ringerMode != AudioManager.RINGER_MODE_NORMAL) { 14355b4e654d0c7de8e4d58d73e73b0d5220f19b68f7Eric Laurent mStreamStates[streamType].mute(null, true); 14365b4e654d0c7de8e4d58d73e73b0d5220f19b68f7Eric Laurent mRingerModeMutedStreams |= (1 << streamType); 14375b4e654d0c7de8e4d58d73e73b0d5220f19b68f7Eric Laurent } 1438b109615ebebd6f3b9ae789412279f576c3ace46bJason Parekh } 14399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1440a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent 1441b109615ebebd6f3b9ae789412279f576c3ace46bJason Parekh // Post a persist ringer mode msg 14424050c93601b3c3609b21cc1e18a29b64747e7fa9Eric Laurent if (persist) { 1443afbb047c3945e9c2b7e9bc6b25098d5fb80bba4eEric Laurent sendMsg(mAudioHandler, MSG_PERSIST_RINGER_MODE, 14444050c93601b3c3609b21cc1e18a29b64747e7fa9Eric Laurent SENDMSG_REPLACE, 0, 0, null, PERSIST_DELAY); 14454050c93601b3c3609b21cc1e18a29b64747e7fa9Eric Laurent } 14469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 14479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 14489063154a793b0ab38b3c5992cbaed046427b4a82Mike Lockwood private void restoreMasterVolume() { 144983a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent if (mUseFixedVolume) { 145083a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent AudioSystem.setMasterVolume(1.0f); 145183a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent return; 145283a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent } 14539063154a793b0ab38b3c5992cbaed046427b4a82Mike Lockwood if (mUseMasterVolume) { 1454bc0fab1fc2db832ef86d8a33466ec4d68b103ca0Eric Laurent float volume = Settings.System.getFloatForUser(mContentResolver, 1455bc0fab1fc2db832ef86d8a33466ec4d68b103ca0Eric Laurent Settings.System.VOLUME_MASTER, -1.0f, UserHandle.USER_CURRENT); 14569063154a793b0ab38b3c5992cbaed046427b4a82Mike Lockwood if (volume >= 0.0f) { 14579063154a793b0ab38b3c5992cbaed046427b4a82Mike Lockwood AudioSystem.setMasterVolume(volume); 14589063154a793b0ab38b3c5992cbaed046427b4a82Mike Lockwood } 14599063154a793b0ab38b3c5992cbaed046427b4a82Mike Lockwood } 14609063154a793b0ab38b3c5992cbaed046427b4a82Mike Lockwood } 14619063154a793b0ab38b3c5992cbaed046427b4a82Mike Lockwood 14629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** @see AudioManager#shouldVibrate(int) */ 14639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public boolean shouldVibrate(int vibrateType) { 1464bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent if (!mHasVibrator) return false; 14659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 14669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project switch (getVibrateSetting(vibrateType)) { 14679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 14689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case AudioManager.VIBRATE_SETTING_ON: 1469ba195ebc76f23b6679443724ab58c9dc9f2df884Glenn Kasten return getRingerMode() != AudioManager.RINGER_MODE_SILENT; 14709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 14719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case AudioManager.VIBRATE_SETTING_ONLY_SILENT: 1472ba195ebc76f23b6679443724ab58c9dc9f2df884Glenn Kasten return getRingerMode() == AudioManager.RINGER_MODE_VIBRATE; 14739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 14749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case AudioManager.VIBRATE_SETTING_OFF: 1475bcac496076ef6f439147e7a2be71e8a2b76ddedeDaniel Sandler // return false, even for incoming calls 1476bcac496076ef6f439147e7a2be71e8a2b76ddedeDaniel Sandler return false; 14779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 14789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project default: 14799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 14809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 14819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 14829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 14839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** @see AudioManager#getVibrateSetting(int) */ 14849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int getVibrateSetting(int vibrateType) { 1485bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent if (!mHasVibrator) return AudioManager.VIBRATE_SETTING_OFF; 14869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return (mVibrateSetting >> (vibrateType * 2)) & 3; 14879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 14889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 14899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** @see AudioManager#setVibrateSetting(int, int) */ 14909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void setVibrateSetting(int vibrateType, int vibrateSetting) { 14919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1492bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent if (!mHasVibrator) return; 1493bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent 14949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mVibrateSetting = getValueForVibrateSetting(mVibrateSetting, vibrateType, vibrateSetting); 14959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 14969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Broadcast change 14979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project broadcastVibrateSetting(vibrateType); 14989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 14999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 15009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 15019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 15029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @see #setVibrateSetting(int, int) 15039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 15049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static int getValueForVibrateSetting(int existingValue, int vibrateType, 15059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int vibrateSetting) { 15069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 15079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // First clear the existing setting. Each vibrate type has two bits in 15089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // the value. Note '3' is '11' in binary. 15099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project existingValue &= ~(3 << (vibrateType * 2)); 15109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 15119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Set into the old value 15129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project existingValue |= (vibrateSetting & 3) << (vibrateType * 2); 15139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 15149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return existingValue; 15159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 15169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 15179272b4b4a44fe1f33e3030810618194f817caaecEric Laurent private class SetModeDeathHandler implements IBinder.DeathRecipient { 15189272b4b4a44fe1f33e3030810618194f817caaecEric Laurent private IBinder mCb; // To be notified of client's death 1519f1ddd51f9cd2f92b922bc636c307210a8d587c25Marco Nelissen private int mPid; 15209272b4b4a44fe1f33e3030810618194f817caaecEric Laurent private int mMode = AudioSystem.MODE_NORMAL; // Current mode set by this client 15219272b4b4a44fe1f33e3030810618194f817caaecEric Laurent 15229f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent SetModeDeathHandler(IBinder cb, int pid) { 15239272b4b4a44fe1f33e3030810618194f817caaecEric Laurent mCb = cb; 15249f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent mPid = pid; 15259272b4b4a44fe1f33e3030810618194f817caaecEric Laurent } 15269272b4b4a44fe1f33e3030810618194f817caaecEric Laurent 15279272b4b4a44fe1f33e3030810618194f817caaecEric Laurent public void binderDied() { 1528d7454be47f4111c0478a502353e11dea401378bdEric Laurent int newModeOwnerPid = 0; 15299272b4b4a44fe1f33e3030810618194f817caaecEric Laurent synchronized(mSetModeDeathHandlers) { 15309272b4b4a44fe1f33e3030810618194f817caaecEric Laurent Log.w(TAG, "setMode() client died"); 15319272b4b4a44fe1f33e3030810618194f817caaecEric Laurent int index = mSetModeDeathHandlers.indexOf(this); 15329272b4b4a44fe1f33e3030810618194f817caaecEric Laurent if (index < 0) { 15339272b4b4a44fe1f33e3030810618194f817caaecEric Laurent Log.w(TAG, "unregistered setMode() client died"); 15349272b4b4a44fe1f33e3030810618194f817caaecEric Laurent } else { 1535d7454be47f4111c0478a502353e11dea401378bdEric Laurent newModeOwnerPid = setModeInt(AudioSystem.MODE_NORMAL, mCb, mPid); 15369272b4b4a44fe1f33e3030810618194f817caaecEric Laurent } 15379272b4b4a44fe1f33e3030810618194f817caaecEric Laurent } 15389f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent // when entering RINGTONE, IN_CALL or IN_COMMUNICATION mode, clear all 15399f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent // SCO connections not started by the application changing the mode 1540d7454be47f4111c0478a502353e11dea401378bdEric Laurent if (newModeOwnerPid != 0) { 15416b5e22d52c69cb6d80ff09bd32395b0034ada343Eric Laurent final long ident = Binder.clearCallingIdentity(); 15426b5e22d52c69cb6d80ff09bd32395b0034ada343Eric Laurent disconnectBluetoothSco(newModeOwnerPid); 15436b5e22d52c69cb6d80ff09bd32395b0034ada343Eric Laurent Binder.restoreCallingIdentity(ident); 15449f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent } 15459272b4b4a44fe1f33e3030810618194f817caaecEric Laurent } 15469272b4b4a44fe1f33e3030810618194f817caaecEric Laurent 1547f1ddd51f9cd2f92b922bc636c307210a8d587c25Marco Nelissen public int getPid() { 1548f1ddd51f9cd2f92b922bc636c307210a8d587c25Marco Nelissen return mPid; 1549f1ddd51f9cd2f92b922bc636c307210a8d587c25Marco Nelissen } 1550f1ddd51f9cd2f92b922bc636c307210a8d587c25Marco Nelissen 15519272b4b4a44fe1f33e3030810618194f817caaecEric Laurent public void setMode(int mode) { 15529272b4b4a44fe1f33e3030810618194f817caaecEric Laurent mMode = mode; 15539272b4b4a44fe1f33e3030810618194f817caaecEric Laurent } 15549272b4b4a44fe1f33e3030810618194f817caaecEric Laurent 15559272b4b4a44fe1f33e3030810618194f817caaecEric Laurent public int getMode() { 15569272b4b4a44fe1f33e3030810618194f817caaecEric Laurent return mMode; 15579272b4b4a44fe1f33e3030810618194f817caaecEric Laurent } 15589272b4b4a44fe1f33e3030810618194f817caaecEric Laurent 15599272b4b4a44fe1f33e3030810618194f817caaecEric Laurent public IBinder getBinder() { 15609272b4b4a44fe1f33e3030810618194f817caaecEric Laurent return mCb; 15619272b4b4a44fe1f33e3030810618194f817caaecEric Laurent } 15629272b4b4a44fe1f33e3030810618194f817caaecEric Laurent } 15639272b4b4a44fe1f33e3030810618194f817caaecEric Laurent 15649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** @see AudioManager#setMode(int) */ 15659272b4b4a44fe1f33e3030810618194f817caaecEric Laurent public void setMode(int mode, IBinder cb) { 15669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!checkAudioSettingsPermission("setMode()")) { 15679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 15689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1569a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent 15708f677d66d9c3ba34c97e69b2bb9e161f129af0eeJean-Michel Trivi if (mode < AudioSystem.MODE_CURRENT || mode >= AudioSystem.NUM_MODES) { 1571a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent return; 1572a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent } 1573a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent 1574d7454be47f4111c0478a502353e11dea401378bdEric Laurent int newModeOwnerPid = 0; 15759f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent synchronized(mSetModeDeathHandlers) { 1576a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent if (mode == AudioSystem.MODE_CURRENT) { 1577a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent mode = mMode; 1578a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent } 1579d7454be47f4111c0478a502353e11dea401378bdEric Laurent newModeOwnerPid = setModeInt(mode, cb, Binder.getCallingPid()); 15809f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent } 15819f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent // when entering RINGTONE, IN_CALL or IN_COMMUNICATION mode, clear all 15829f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent // SCO connections not started by the application changing the mode 1583d7454be47f4111c0478a502353e11dea401378bdEric Laurent if (newModeOwnerPid != 0) { 1584d7454be47f4111c0478a502353e11dea401378bdEric Laurent disconnectBluetoothSco(newModeOwnerPid); 15859f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent } 15869f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent } 15872ade576148fe33c5ff6098d30ccfbcf28df70e8eJean-Michel Trivi 15889f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent // must be called synchronized on mSetModeDeathHandlers 1589d7454be47f4111c0478a502353e11dea401378bdEric Laurent // setModeInt() returns a valid PID if the audio mode was successfully set to 15909f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent // any mode other than NORMAL. 1591d7454be47f4111c0478a502353e11dea401378bdEric Laurent int setModeInt(int mode, IBinder cb, int pid) { 1592d7454be47f4111c0478a502353e11dea401378bdEric Laurent int newModeOwnerPid = 0; 15939f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent if (cb == null) { 15949f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent Log.e(TAG, "setModeInt() called with null binder"); 1595d7454be47f4111c0478a502353e11dea401378bdEric Laurent return newModeOwnerPid; 15969f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent } 15972ade576148fe33c5ff6098d30ccfbcf28df70e8eJean-Michel Trivi 15989f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent SetModeDeathHandler hdlr = null; 15999f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent Iterator iter = mSetModeDeathHandlers.iterator(); 16009f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent while (iter.hasNext()) { 16019f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent SetModeDeathHandler h = (SetModeDeathHandler)iter.next(); 16029f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent if (h.getPid() == pid) { 16039f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent hdlr = h; 16049f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent // Remove from client list so that it is re-inserted at top of list 16059f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent iter.remove(); 16069f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent hdlr.getBinder().unlinkToDeath(hdlr, 0); 16079f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent break; 16089f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent } 16099f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent } 16109f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent int status = AudioSystem.AUDIO_STATUS_OK; 16119f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent do { 16129f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent if (mode == AudioSystem.MODE_NORMAL) { 16139f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent // get new mode from client at top the list if any 16149f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent if (!mSetModeDeathHandlers.isEmpty()) { 16159f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent hdlr = mSetModeDeathHandlers.get(0); 16169f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent cb = hdlr.getBinder(); 16179f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent mode = hdlr.getMode(); 16189f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent } 16199f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent } else { 16209f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent if (hdlr == null) { 16219f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent hdlr = new SetModeDeathHandler(cb, pid); 16229f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent } 16239f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent // Register for client death notification 16249f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent try { 16259f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent cb.linkToDeath(hdlr, 0); 16269f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent } catch (RemoteException e) { 16279f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent // Client has died! 16289f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent Log.w(TAG, "setMode() could not link to "+cb+" binder death"); 16299f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent } 16309272b4b4a44fe1f33e3030810618194f817caaecEric Laurent 16319f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent // Last client to call setMode() is always at top of client list 16329f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent // as required by SetModeDeathHandler.binderDied() 16339f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent mSetModeDeathHandlers.add(0, hdlr); 16349f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent hdlr.setMode(mode); 16359f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent } 16363def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent 16379f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent if (mode != mMode) { 16389f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent status = AudioSystem.setPhoneState(mode); 16399f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent if (status == AudioSystem.AUDIO_STATUS_OK) { 16409f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent mMode = mode; 16419f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent } else { 16429f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent if (hdlr != null) { 16439f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent mSetModeDeathHandlers.remove(hdlr); 16449f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent cb.unlinkToDeath(hdlr, 0); 16453def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent } 16469f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent // force reading new top of mSetModeDeathHandlers stack 16479f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent mode = AudioSystem.MODE_NORMAL; 1648b9c9d260f21b321527c4622a123af9767630d94dEric Laurent } 16499f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent } else { 16509f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent status = AudioSystem.AUDIO_STATUS_OK; 16519f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent } 16529f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent } while (status != AudioSystem.AUDIO_STATUS_OK && !mSetModeDeathHandlers.isEmpty()); 16539f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent 16549f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent if (status == AudioSystem.AUDIO_STATUS_OK) { 16559f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent if (mode != AudioSystem.MODE_NORMAL) { 1656d7454be47f4111c0478a502353e11dea401378bdEric Laurent if (mSetModeDeathHandlers.isEmpty()) { 1657d7454be47f4111c0478a502353e11dea401378bdEric Laurent Log.e(TAG, "setMode() different from MODE_NORMAL with empty mode client stack"); 1658d7454be47f4111c0478a502353e11dea401378bdEric Laurent } else { 1659d7454be47f4111c0478a502353e11dea401378bdEric Laurent newModeOwnerPid = mSetModeDeathHandlers.get(0).getPid(); 1660d7454be47f4111c0478a502353e11dea401378bdEric Laurent } 16619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 16629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int streamType = getActiveStreamType(AudioManager.USE_DEFAULT_STREAM_TYPE); 16633114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi if (streamType == STREAM_REMOTE_MUSIC) { 16643114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi // here handle remote media playback the same way as local playback 16653114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi streamType = AudioManager.STREAM_MUSIC; 16663114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi } 16679bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent int device = getDeviceForStream(streamType); 166842b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent int index = mStreamStates[mStreamVolumeAlias[streamType]].getIndex(device); 166942b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent setStreamVolumeInt(mStreamVolumeAlias[streamType], index, device, true); 16706d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent 16716d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent updateStreamVolumeAlias(true /*updateVolumes*/); 16729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1673d7454be47f4111c0478a502353e11dea401378bdEric Laurent return newModeOwnerPid; 16749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 16759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 16769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** @see AudioManager#getMode() */ 16779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int getMode() { 16789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mMode; 16799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 16809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1681e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent //========================================================================================== 1682e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent // Sound Effects 1683e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent //========================================================================================== 1684e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent 1685e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent private static final String TAG_AUDIO_ASSETS = "audio_assets"; 1686e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent private static final String ATTR_VERSION = "version"; 1687e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent private static final String TAG_GROUP = "group"; 1688e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent private static final String ATTR_GROUP_NAME = "name"; 1689e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent private static final String TAG_ASSET = "asset"; 1690e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent private static final String ATTR_ASSET_ID = "id"; 1691e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent private static final String ATTR_ASSET_FILE = "file"; 1692e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent 1693e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent private static final String ASSET_FILE_VERSION = "1.0"; 1694e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent private static final String GROUP_TOUCH_SOUNDS = "touch_sounds"; 1695e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent 16965d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent private static final int SOUND_EFECTS_LOAD_TIMEOUT_MS = 5000; 16975d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent 16985d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent class LoadSoundEffectReply { 16995d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent public int mStatus = 1; 17005d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent }; 17015d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent 1702e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent private void loadTouchSoundAssetDefaults() { 1703e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent SOUND_EFFECT_FILES.add("Effect_Tick.ogg"); 1704e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent for (int i = 0; i < AudioManager.NUM_SOUND_EFFECTS; i++) { 1705e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent SOUND_EFFECT_FILES_MAP[i][0] = 0; 1706e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent SOUND_EFFECT_FILES_MAP[i][1] = -1; 1707e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent } 1708e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent } 1709e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent 1710e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent private void loadTouchSoundAssets() { 1711e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent XmlResourceParser parser = null; 1712e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent 17135d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent // only load assets once. 17145d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent if (!SOUND_EFFECT_FILES.isEmpty()) { 17155d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent return; 17165d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent } 17175d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent 1718e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent loadTouchSoundAssetDefaults(); 1719e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent 1720e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent try { 1721e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent parser = mContext.getResources().getXml(com.android.internal.R.xml.audio_assets); 1722e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent 1723e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent XmlUtils.beginDocument(parser, TAG_AUDIO_ASSETS); 1724e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent String version = parser.getAttributeValue(null, ATTR_VERSION); 1725e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent boolean inTouchSoundsGroup = false; 1726e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent 1727e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent if (ASSET_FILE_VERSION.equals(version)) { 1728e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent while (true) { 1729e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent XmlUtils.nextElement(parser); 1730e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent String element = parser.getName(); 1731e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent if (element == null) { 1732e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent break; 1733e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent } 1734e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent if (element.equals(TAG_GROUP)) { 1735e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent String name = parser.getAttributeValue(null, ATTR_GROUP_NAME); 1736e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent if (GROUP_TOUCH_SOUNDS.equals(name)) { 1737e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent inTouchSoundsGroup = true; 1738e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent break; 1739e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent } 1740e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent } 1741e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent } 1742e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent while (inTouchSoundsGroup) { 1743e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent XmlUtils.nextElement(parser); 1744e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent String element = parser.getName(); 1745e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent if (element == null) { 1746e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent break; 1747e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent } 1748e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent if (element.equals(TAG_ASSET)) { 1749e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent String id = parser.getAttributeValue(null, ATTR_ASSET_ID); 1750e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent String file = parser.getAttributeValue(null, ATTR_ASSET_FILE); 1751e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent int fx; 1752e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent 1753e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent try { 1754e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent Field field = AudioManager.class.getField(id); 1755e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent fx = field.getInt(null); 1756e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent } catch (Exception e) { 1757e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent Log.w(TAG, "Invalid touch sound ID: "+id); 1758e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent continue; 1759e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent } 1760e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent 1761e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent int i = SOUND_EFFECT_FILES.indexOf(file); 1762e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent if (i == -1) { 1763e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent i = SOUND_EFFECT_FILES.size(); 1764e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent SOUND_EFFECT_FILES.add(file); 1765e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent } 1766e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent SOUND_EFFECT_FILES_MAP[fx][0] = i; 1767e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent } else { 1768e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent break; 1769e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent } 1770e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent } 1771e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent } 1772e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent } catch (Resources.NotFoundException e) { 1773e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent Log.w(TAG, "audio assets file not found", e); 1774e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent } catch (XmlPullParserException e) { 1775e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent Log.w(TAG, "XML parser exception reading touch sound assets", e); 1776e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent } catch (IOException e) { 1777e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent Log.w(TAG, "I/O exception reading touch sound assets", e); 1778e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent } finally { 1779e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent if (parser != null) { 1780e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent parser.close(); 1781e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent } 1782e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent } 1783e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent } 1784e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent 17859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** @see AudioManager#playSoundEffect(int) */ 17869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void playSoundEffect(int effectType) { 17875d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent playSoundEffectVolume(effectType, -1.0f); 17889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 17899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 17909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** @see AudioManager#playSoundEffect(int, float) */ 17919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void playSoundEffectVolume(int effectType, float volume) { 17925d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent sendMsg(mAudioHandler, MSG_PLAY_SOUND_EFFECT, SENDMSG_QUEUE, 17939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project effectType, (int) (volume * 1000), null, 0); 17949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 17959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 17969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 17979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Loads samples into the soundpool. 17985c17a820f9e46e0756c11795b3e6f89105f2f539Glenn Kasten * This method must be called at first when sound effects are enabled 17999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 18009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public boolean loadSoundEffects() { 18015d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent int attempts = 3; 18025d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent LoadSoundEffectReply reply = new LoadSoundEffectReply(); 1803117b7bb5b5a4457711f59bde3dcc83d8f111c524Eric Laurent 18045d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent synchronized (reply) { 18055d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent sendMsg(mAudioHandler, MSG_LOAD_SOUND_EFFECTS, SENDMSG_QUEUE, 0, 0, reply, 0); 18065d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent while ((reply.mStatus == 1) && (attempts-- > 0)) { 1807117b7bb5b5a4457711f59bde3dcc83d8f111c524Eric Laurent try { 18085d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent reply.wait(SOUND_EFECTS_LOAD_TIMEOUT_MS); 18095d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent } catch (InterruptedException e) { 18105d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent Log.w(TAG, "loadSoundEffects Interrupted while waiting sound pool loaded."); 1811117b7bb5b5a4457711f59bde3dcc83d8f111c524Eric Laurent } 1812a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent } 18139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 18145d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent return (reply.mStatus == 0); 18159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 18169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 18179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 18189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Unloads samples from the sound pool. 18199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * This method can be called to free some memory when 18209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * sound effects are disabled. 18219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 18229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void unloadSoundEffects() { 18235d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent sendMsg(mAudioHandler, MSG_UNLOAD_SOUND_EFFECTS, SENDMSG_QUEUE, 0, 0, null, 0); 18249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 18259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1826a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent class SoundPoolListenerThread extends Thread { 1827a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent public SoundPoolListenerThread() { 1828a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent super("SoundPoolListenerThread"); 1829a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent } 1830a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent 1831a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent @Override 1832a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent public void run() { 1833a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent 1834a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent Looper.prepare(); 1835a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent mSoundPoolLooper = Looper.myLooper(); 1836a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent 1837a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent synchronized (mSoundEffectsLock) { 1838a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent if (mSoundPool != null) { 1839a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent mSoundPoolCallBack = new SoundPoolCallback(); 1840a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent mSoundPool.setOnLoadCompleteListener(mSoundPoolCallBack); 1841a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent } 1842a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent mSoundEffectsLock.notify(); 1843a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent } 1844a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent Looper.loop(); 1845a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent } 1846a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent } 1847a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent 1848a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent private final class SoundPoolCallback implements 1849a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent android.media.SoundPool.OnLoadCompleteListener { 1850a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent 18515d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent int mStatus = 1; // 1 means neither error nor last sample loaded yet 18525d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent List<Integer> mSamples = new ArrayList<Integer>(); 1853a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent 1854a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent public int status() { 1855a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent return mStatus; 1856a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent } 1857a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent 18585d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent public void setSamples(int[] samples) { 18595d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent for (int i = 0; i < samples.length; i++) { 18605d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent // do not wait ack for samples rejected upfront by SoundPool 18615d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent if (samples[i] > 0) { 18625d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent mSamples.add(samples[i]); 18635d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent } 18645d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent } 1865a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent } 1866a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent 1867a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent public void onLoadComplete(SoundPool soundPool, int sampleId, int status) { 1868a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent synchronized (mSoundEffectsLock) { 18695d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent int i = mSamples.indexOf(sampleId); 18705d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent if (i >= 0) { 18715d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent mSamples.remove(i); 1872a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent } 18735d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent if ((status != 0) || mSamples. isEmpty()) { 18745d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent mStatus = status; 1875a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent mSoundEffectsLock.notify(); 1876a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent } 1877a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent } 1878a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent } 1879a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent } 1880a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent 18814050c93601b3c3609b21cc1e18a29b64747e7fa9Eric Laurent /** @see AudioManager#reloadAudioSettings() */ 18824050c93601b3c3609b21cc1e18a29b64747e7fa9Eric Laurent public void reloadAudioSettings() { 1883bc0fab1fc2db832ef86d8a33466ec4d68b103ca0Eric Laurent readAudioSettings(false /*userSwitch*/); 1884bc0fab1fc2db832ef86d8a33466ec4d68b103ca0Eric Laurent } 1885bc0fab1fc2db832ef86d8a33466ec4d68b103ca0Eric Laurent 1886bc0fab1fc2db832ef86d8a33466ec4d68b103ca0Eric Laurent private void readAudioSettings(boolean userSwitch) { 18874050c93601b3c3609b21cc1e18a29b64747e7fa9Eric Laurent // restore ringer mode, ringer mode affected streams, mute affected streams and vibrate settings 18884050c93601b3c3609b21cc1e18a29b64747e7fa9Eric Laurent readPersistedSettings(); 18894050c93601b3c3609b21cc1e18a29b64747e7fa9Eric Laurent 18904050c93601b3c3609b21cc1e18a29b64747e7fa9Eric Laurent // restore volume settings 18914050c93601b3c3609b21cc1e18a29b64747e7fa9Eric Laurent int numStreamTypes = AudioSystem.getNumStreamTypes(); 18924050c93601b3c3609b21cc1e18a29b64747e7fa9Eric Laurent for (int streamType = 0; streamType < numStreamTypes; streamType++) { 18934050c93601b3c3609b21cc1e18a29b64747e7fa9Eric Laurent VolumeStreamState streamState = mStreamStates[streamType]; 18944050c93601b3c3609b21cc1e18a29b64747e7fa9Eric Laurent 1895bc0fab1fc2db832ef86d8a33466ec4d68b103ca0Eric Laurent if (userSwitch && mStreamVolumeAlias[streamType] == AudioSystem.STREAM_MUSIC) { 1896bc0fab1fc2db832ef86d8a33466ec4d68b103ca0Eric Laurent continue; 1897bc0fab1fc2db832ef86d8a33466ec4d68b103ca0Eric Laurent } 1898bc0fab1fc2db832ef86d8a33466ec4d68b103ca0Eric Laurent 18993172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent synchronized (streamState) { 19003172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent streamState.readSettings(); 1901a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent 19023172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent // unmute stream that was muted but is not affect by mute anymore 190342b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent if (streamState.isMuted() && ((!isStreamAffectedByMute(streamType) && 190483a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent !isStreamMutedByRingerMode(streamType)) || mUseFixedVolume)) { 19053172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent int size = streamState.mDeathHandlers.size(); 19063172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent for (int i = 0; i < size; i++) { 19073172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent streamState.mDeathHandlers.get(i).mMuteCount = 1; 19083172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent streamState.mDeathHandlers.get(i).mute(false); 19093172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent } 19103172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent } 19114050c93601b3c3609b21cc1e18a29b64747e7fa9Eric Laurent } 19124050c93601b3c3609b21cc1e18a29b64747e7fa9Eric Laurent } 19134050c93601b3c3609b21cc1e18a29b64747e7fa9Eric Laurent 191433902db75011d863009585682bd08560c5b89a75Eric Laurent // apply new ringer mode before checking volume for alias streams so that streams 191533902db75011d863009585682bd08560c5b89a75Eric Laurent // muted by ringer mode have the correct volume 191633902db75011d863009585682bd08560c5b89a75Eric Laurent setRingerModeInt(getRingerMode(), false); 191733902db75011d863009585682bd08560c5b89a75Eric Laurent 1918244820185269991186d07068b92985624cede4a5Eric Laurent checkAllAliasStreamVolumes(); 1919244820185269991186d07068b92985624cede4a5Eric Laurent 1920d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent synchronized (mSafeMediaVolumeState) { 1921d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent if (mSafeMediaVolumeState == SAFE_MEDIA_VOLUME_ACTIVE) { 1922f1a457d06c53a901ea08d2d3fb6e766bc06c4d4fEric Laurent enforceSafeMediaVolume(); 1923f1a457d06c53a901ea08d2d3fb6e766bc06c4d4fEric Laurent } 1924c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent } 19254050c93601b3c3609b21cc1e18a29b64747e7fa9Eric Laurent } 19264050c93601b3c3609b21cc1e18a29b64747e7fa9Eric Laurent 1927961cae92540763226648813d111c5b5c3b0f1597Dianne Hackborn /** @see AudioManager#setSpeakerphoneOn(boolean) */ 1928c42ac9d4d03f62c3a1ba197a28a81fda44bd8b7fEric Laurent public void setSpeakerphoneOn(boolean on){ 1929dc1d17a1dbfc2ae01c20012133a836b62f5b6930Eric Laurent if (!checkAudioSettingsPermission("setSpeakerphoneOn()")) { 1930dc1d17a1dbfc2ae01c20012133a836b62f5b6930Eric Laurent return; 1931dc1d17a1dbfc2ae01c20012133a836b62f5b6930Eric Laurent } 19327337bee7839238f244fad31112a45389f6ef907cJohan Gustavsson 19337337bee7839238f244fad31112a45389f6ef907cJohan Gustavsson if (on) { 19347337bee7839238f244fad31112a45389f6ef907cJohan Gustavsson if (mForcedUseForComm == AudioSystem.FORCE_BT_SCO) { 19357337bee7839238f244fad31112a45389f6ef907cJohan Gustavsson sendMsg(mAudioHandler, MSG_SET_FORCE_USE, SENDMSG_QUEUE, 19367337bee7839238f244fad31112a45389f6ef907cJohan Gustavsson AudioSystem.FOR_RECORD, AudioSystem.FORCE_NONE, null, 0); 19377337bee7839238f244fad31112a45389f6ef907cJohan Gustavsson } 19387337bee7839238f244fad31112a45389f6ef907cJohan Gustavsson mForcedUseForComm = AudioSystem.FORCE_SPEAKER; 19397337bee7839238f244fad31112a45389f6ef907cJohan Gustavsson } else if (mForcedUseForComm == AudioSystem.FORCE_SPEAKER){ 19407337bee7839238f244fad31112a45389f6ef907cJohan Gustavsson mForcedUseForComm = AudioSystem.FORCE_NONE; 19417337bee7839238f244fad31112a45389f6ef907cJohan Gustavsson } 1942fa640154f1f42121d81242b2f1a10f03e52f0014Eric Laurent 1943afbb047c3945e9c2b7e9bc6b25098d5fb80bba4eEric Laurent sendMsg(mAudioHandler, MSG_SET_FORCE_USE, SENDMSG_QUEUE, 1944fa640154f1f42121d81242b2f1a10f03e52f0014Eric Laurent AudioSystem.FOR_COMMUNICATION, mForcedUseForComm, null, 0); 1945c42ac9d4d03f62c3a1ba197a28a81fda44bd8b7fEric Laurent } 1946c42ac9d4d03f62c3a1ba197a28a81fda44bd8b7fEric Laurent 1947c42ac9d4d03f62c3a1ba197a28a81fda44bd8b7fEric Laurent /** @see AudioManager#isSpeakerphoneOn() */ 1948c42ac9d4d03f62c3a1ba197a28a81fda44bd8b7fEric Laurent public boolean isSpeakerphoneOn() { 1949fa640154f1f42121d81242b2f1a10f03e52f0014Eric Laurent return (mForcedUseForComm == AudioSystem.FORCE_SPEAKER); 1950c42ac9d4d03f62c3a1ba197a28a81fda44bd8b7fEric Laurent } 1951c42ac9d4d03f62c3a1ba197a28a81fda44bd8b7fEric Laurent 1952961cae92540763226648813d111c5b5c3b0f1597Dianne Hackborn /** @see AudioManager#setBluetoothScoOn(boolean) */ 1953c42ac9d4d03f62c3a1ba197a28a81fda44bd8b7fEric Laurent public void setBluetoothScoOn(boolean on){ 1954dc1d17a1dbfc2ae01c20012133a836b62f5b6930Eric Laurent if (!checkAudioSettingsPermission("setBluetoothScoOn()")) { 1955dc1d17a1dbfc2ae01c20012133a836b62f5b6930Eric Laurent return; 1956dc1d17a1dbfc2ae01c20012133a836b62f5b6930Eric Laurent } 19577337bee7839238f244fad31112a45389f6ef907cJohan Gustavsson 19587337bee7839238f244fad31112a45389f6ef907cJohan Gustavsson if (on) { 19597337bee7839238f244fad31112a45389f6ef907cJohan Gustavsson mForcedUseForComm = AudioSystem.FORCE_BT_SCO; 19607337bee7839238f244fad31112a45389f6ef907cJohan Gustavsson } else if (mForcedUseForComm == AudioSystem.FORCE_BT_SCO) { 19617337bee7839238f244fad31112a45389f6ef907cJohan Gustavsson mForcedUseForComm = AudioSystem.FORCE_NONE; 19627337bee7839238f244fad31112a45389f6ef907cJohan Gustavsson } 1963fa640154f1f42121d81242b2f1a10f03e52f0014Eric Laurent 1964afbb047c3945e9c2b7e9bc6b25098d5fb80bba4eEric Laurent sendMsg(mAudioHandler, MSG_SET_FORCE_USE, SENDMSG_QUEUE, 1965fa640154f1f42121d81242b2f1a10f03e52f0014Eric Laurent AudioSystem.FOR_COMMUNICATION, mForcedUseForComm, null, 0); 1966afbb047c3945e9c2b7e9bc6b25098d5fb80bba4eEric Laurent sendMsg(mAudioHandler, MSG_SET_FORCE_USE, SENDMSG_QUEUE, 1967fa640154f1f42121d81242b2f1a10f03e52f0014Eric Laurent AudioSystem.FOR_RECORD, mForcedUseForComm, null, 0); 1968c42ac9d4d03f62c3a1ba197a28a81fda44bd8b7fEric Laurent } 1969c42ac9d4d03f62c3a1ba197a28a81fda44bd8b7fEric Laurent 1970c42ac9d4d03f62c3a1ba197a28a81fda44bd8b7fEric Laurent /** @see AudioManager#isBluetoothScoOn() */ 1971c42ac9d4d03f62c3a1ba197a28a81fda44bd8b7fEric Laurent public boolean isBluetoothScoOn() { 1972fa640154f1f42121d81242b2f1a10f03e52f0014Eric Laurent return (mForcedUseForComm == AudioSystem.FORCE_BT_SCO); 1973c42ac9d4d03f62c3a1ba197a28a81fda44bd8b7fEric Laurent } 1974c42ac9d4d03f62c3a1ba197a28a81fda44bd8b7fEric Laurent 1975961cae92540763226648813d111c5b5c3b0f1597Dianne Hackborn /** @see AudioManager#setBluetoothA2dpOn(boolean) */ 19767847211fb4699bf6018e29d214a918ed6657319bEric Laurent public void setBluetoothA2dpOn(boolean on) { 1977c390bed06b4a572e273ead1254da9a932e04dce3Eric Laurent synchronized (mBluetoothA2dpEnabledLock) { 1978c390bed06b4a572e273ead1254da9a932e04dce3Eric Laurent mBluetoothA2dpEnabled = on; 1979c390bed06b4a572e273ead1254da9a932e04dce3Eric Laurent sendMsg(mAudioHandler, MSG_SET_FORCE_BT_A2DP_USE, SENDMSG_QUEUE, 1980c390bed06b4a572e273ead1254da9a932e04dce3Eric Laurent AudioSystem.FOR_MEDIA, 1981c390bed06b4a572e273ead1254da9a932e04dce3Eric Laurent mBluetoothA2dpEnabled ? AudioSystem.FORCE_NONE : AudioSystem.FORCE_NO_BT_A2DP, 1982c390bed06b4a572e273ead1254da9a932e04dce3Eric Laurent null, 0); 1983c390bed06b4a572e273ead1254da9a932e04dce3Eric Laurent } 19847847211fb4699bf6018e29d214a918ed6657319bEric Laurent } 19857847211fb4699bf6018e29d214a918ed6657319bEric Laurent 19867847211fb4699bf6018e29d214a918ed6657319bEric Laurent /** @see AudioManager#isBluetoothA2dpOn() */ 19877847211fb4699bf6018e29d214a918ed6657319bEric Laurent public boolean isBluetoothA2dpOn() { 19887847211fb4699bf6018e29d214a918ed6657319bEric Laurent synchronized (mBluetoothA2dpEnabledLock) { 19897847211fb4699bf6018e29d214a918ed6657319bEric Laurent return mBluetoothA2dpEnabled; 19907847211fb4699bf6018e29d214a918ed6657319bEric Laurent } 19917847211fb4699bf6018e29d214a918ed6657319bEric Laurent } 19927847211fb4699bf6018e29d214a918ed6657319bEric Laurent 19933def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent /** @see AudioManager#startBluetoothSco() */ 1994c18c9138cee0f0859bcab636a004ce92ca4a9ab5Eric Laurent public void startBluetoothSco(IBinder cb, int targetSdkVersion){ 1995dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent if (!checkAudioSettingsPermission("startBluetoothSco()") || 1996dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent !mBootCompleted) { 19973def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent return; 19983def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent } 1999854938a72d968c1bc0de4e2b0ea87777cfebc045Eric Laurent ScoClient client = getScoClient(cb, true); 2000f5a1fc3c0fd733acd21e1437f153ba27220be8ceEric Laurent // The calling identity must be cleared before calling ScoClient.incCount(). 2001f5a1fc3c0fd733acd21e1437f153ba27220be8ceEric Laurent // inCount() calls requestScoState() which in turn can call BluetoothHeadset APIs 2002f5a1fc3c0fd733acd21e1437f153ba27220be8ceEric Laurent // and this must be done on behalf of system server to make sure permissions are granted. 2003f5a1fc3c0fd733acd21e1437f153ba27220be8ceEric Laurent // The caller identity must be cleared after getScoClient() because it is needed if a new 2004f5a1fc3c0fd733acd21e1437f153ba27220be8ceEric Laurent // client is created. 2005f5a1fc3c0fd733acd21e1437f153ba27220be8ceEric Laurent final long ident = Binder.clearCallingIdentity(); 2006c18c9138cee0f0859bcab636a004ce92ca4a9ab5Eric Laurent client.incCount(targetSdkVersion); 20072a57ca931fefe817b6110101289721acaacfc808Eric Laurent Binder.restoreCallingIdentity(ident); 20083def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent } 20093def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent 20103def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent /** @see AudioManager#stopBluetoothSco() */ 20113def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent public void stopBluetoothSco(IBinder cb){ 2012dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent if (!checkAudioSettingsPermission("stopBluetoothSco()") || 2013dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent !mBootCompleted) { 20143def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent return; 20153def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent } 2016854938a72d968c1bc0de4e2b0ea87777cfebc045Eric Laurent ScoClient client = getScoClient(cb, false); 2017f5a1fc3c0fd733acd21e1437f153ba27220be8ceEric Laurent // The calling identity must be cleared before calling ScoClient.decCount(). 2018f5a1fc3c0fd733acd21e1437f153ba27220be8ceEric Laurent // decCount() calls requestScoState() which in turn can call BluetoothHeadset APIs 2019f5a1fc3c0fd733acd21e1437f153ba27220be8ceEric Laurent // and this must be done on behalf of system server to make sure permissions are granted. 2020f5a1fc3c0fd733acd21e1437f153ba27220be8ceEric Laurent final long ident = Binder.clearCallingIdentity(); 2021854938a72d968c1bc0de4e2b0ea87777cfebc045Eric Laurent if (client != null) { 2022854938a72d968c1bc0de4e2b0ea87777cfebc045Eric Laurent client.decCount(); 2023854938a72d968c1bc0de4e2b0ea87777cfebc045Eric Laurent } 20242a57ca931fefe817b6110101289721acaacfc808Eric Laurent Binder.restoreCallingIdentity(ident); 20253def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent } 20263def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent 20277847211fb4699bf6018e29d214a918ed6657319bEric Laurent 20283def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent private class ScoClient implements IBinder.DeathRecipient { 20293def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent private IBinder mCb; // To be notified of client's death 2030f1ddd51f9cd2f92b922bc636c307210a8d587c25Marco Nelissen private int mCreatorPid; 20313def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent private int mStartcount; // number of SCO connections started by this client 20323def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent 20333def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent ScoClient(IBinder cb) { 20343def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent mCb = cb; 2035f1ddd51f9cd2f92b922bc636c307210a8d587c25Marco Nelissen mCreatorPid = Binder.getCallingPid(); 20363def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent mStartcount = 0; 20373def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent } 20383def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent 20393def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent public void binderDied() { 20403def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent synchronized(mScoClients) { 20413def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent Log.w(TAG, "SCO client died"); 20423def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent int index = mScoClients.indexOf(this); 20433def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent if (index < 0) { 20443def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent Log.w(TAG, "unregistered SCO client died"); 20453def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent } else { 20463def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent clearCount(true); 20473def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent mScoClients.remove(this); 20483def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent } 20493def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent } 20503def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent } 20513def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent 2052c18c9138cee0f0859bcab636a004ce92ca4a9ab5Eric Laurent public void incCount(int targetSdkVersion) { 20533def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent synchronized(mScoClients) { 2054c18c9138cee0f0859bcab636a004ce92ca4a9ab5Eric Laurent requestScoState(BluetoothHeadset.STATE_AUDIO_CONNECTED, targetSdkVersion); 20553def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent if (mStartcount == 0) { 20563def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent try { 20573def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent mCb.linkToDeath(this, 0); 20583def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent } catch (RemoteException e) { 20593def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent // client has already died! 20603def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent Log.w(TAG, "ScoClient incCount() could not link to "+mCb+" binder death"); 20613def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent } 20623def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent } 20633def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent mStartcount++; 20643def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent } 20653def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent } 20663def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent 20673def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent public void decCount() { 20683def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent synchronized(mScoClients) { 20693def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent if (mStartcount == 0) { 20703def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent Log.w(TAG, "ScoClient.decCount() already 0"); 20713def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent } else { 20723def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent mStartcount--; 20733def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent if (mStartcount == 0) { 2074e2dd8c4592762414c2c27e4589be7edc91a5ecaeEric Laurent try { 2075e2dd8c4592762414c2c27e4589be7edc91a5ecaeEric Laurent mCb.unlinkToDeath(this, 0); 2076e2dd8c4592762414c2c27e4589be7edc91a5ecaeEric Laurent } catch (NoSuchElementException e) { 2077e2dd8c4592762414c2c27e4589be7edc91a5ecaeEric Laurent Log.w(TAG, "decCount() going to 0 but not registered to binder"); 2078e2dd8c4592762414c2c27e4589be7edc91a5ecaeEric Laurent } 20793def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent } 2080c18c9138cee0f0859bcab636a004ce92ca4a9ab5Eric Laurent requestScoState(BluetoothHeadset.STATE_AUDIO_DISCONNECTED, 0); 20813def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent } 20823def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent } 20833def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent } 20843def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent 20853def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent public void clearCount(boolean stopSco) { 20863def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent synchronized(mScoClients) { 2087e2dd8c4592762414c2c27e4589be7edc91a5ecaeEric Laurent if (mStartcount != 0) { 2088e2dd8c4592762414c2c27e4589be7edc91a5ecaeEric Laurent try { 2089e2dd8c4592762414c2c27e4589be7edc91a5ecaeEric Laurent mCb.unlinkToDeath(this, 0); 2090e2dd8c4592762414c2c27e4589be7edc91a5ecaeEric Laurent } catch (NoSuchElementException e) { 2091e2dd8c4592762414c2c27e4589be7edc91a5ecaeEric Laurent Log.w(TAG, "clearCount() mStartcount: "+mStartcount+" != 0 but not registered to binder"); 2092e2dd8c4592762414c2c27e4589be7edc91a5ecaeEric Laurent } 2093e2dd8c4592762414c2c27e4589be7edc91a5ecaeEric Laurent } 20943def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent mStartcount = 0; 20953def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent if (stopSco) { 2096c18c9138cee0f0859bcab636a004ce92ca4a9ab5Eric Laurent requestScoState(BluetoothHeadset.STATE_AUDIO_DISCONNECTED, 0); 20973def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent } 20983def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent } 20993def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent } 21003def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent 21013def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent public int getCount() { 21023def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent return mStartcount; 21033def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent } 21043def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent 21053def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent public IBinder getBinder() { 21063def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent return mCb; 21073def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent } 21083def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent 2109d7454be47f4111c0478a502353e11dea401378bdEric Laurent public int getPid() { 2110d7454be47f4111c0478a502353e11dea401378bdEric Laurent return mCreatorPid; 2111d7454be47f4111c0478a502353e11dea401378bdEric Laurent } 2112d7454be47f4111c0478a502353e11dea401378bdEric Laurent 21133def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent public int totalCount() { 21143def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent synchronized(mScoClients) { 21153def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent int count = 0; 21163def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent int size = mScoClients.size(); 21173def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent for (int i = 0; i < size; i++) { 21183def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent count += mScoClients.get(i).getCount(); 21193def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent } 21203def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent return count; 21213def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent } 21223def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent } 21233def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent 2124c18c9138cee0f0859bcab636a004ce92ca4a9ab5Eric Laurent private void requestScoState(int state, int targetSdkVersion) { 212562ef767b15a712bab31cc0d5508a330906f535c2Eric Laurent checkScoAudioState(); 2126dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent if (totalCount() == 0) { 2127dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent if (state == BluetoothHeadset.STATE_AUDIO_CONNECTED) { 2128dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent // Make sure that the state transitions to CONNECTING even if we cannot initiate 2129dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent // the connection. 2130dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent broadcastScoConnectionState(AudioManager.SCO_AUDIO_STATE_CONNECTING); 2131dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent // Accept SCO audio activation only in NORMAL audio mode or if the mode is 2132f1ddd51f9cd2f92b922bc636c307210a8d587c25Marco Nelissen // currently controlled by the same client process. 21339f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent synchronized(mSetModeDeathHandlers) { 21349f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent if ((mSetModeDeathHandlers.isEmpty() || 21359f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent mSetModeDeathHandlers.get(0).getPid() == mCreatorPid) && 21369f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent (mScoAudioState == SCO_STATE_INACTIVE || 21379f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent mScoAudioState == SCO_STATE_DEACTIVATE_REQ)) { 21389f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent if (mScoAudioState == SCO_STATE_INACTIVE) { 2139c18c9138cee0f0859bcab636a004ce92ca4a9ab5Eric Laurent mScoAudioMode = 2140c18c9138cee0f0859bcab636a004ce92ca4a9ab5Eric Laurent (targetSdkVersion < Build.VERSION_CODES.JELLY_BEAN_MR2) ? 2141c18c9138cee0f0859bcab636a004ce92ca4a9ab5Eric Laurent SCO_MODE_VIRTUAL_CALL : SCO_MODE_RAW; 21429f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent if (mBluetoothHeadset != null && mBluetoothHeadsetDevice != null) { 2143c18c9138cee0f0859bcab636a004ce92ca4a9ab5Eric Laurent boolean status; 2144c18c9138cee0f0859bcab636a004ce92ca4a9ab5Eric Laurent if (mScoAudioMode == SCO_MODE_RAW) { 2145c18c9138cee0f0859bcab636a004ce92ca4a9ab5Eric Laurent status = mBluetoothHeadset.connectAudio(); 2146c18c9138cee0f0859bcab636a004ce92ca4a9ab5Eric Laurent } else { 2147c18c9138cee0f0859bcab636a004ce92ca4a9ab5Eric Laurent status = mBluetoothHeadset.startScoUsingVirtualVoiceCall( 2148c18c9138cee0f0859bcab636a004ce92ca4a9ab5Eric Laurent mBluetoothHeadsetDevice); 2149c18c9138cee0f0859bcab636a004ce92ca4a9ab5Eric Laurent } 2150c18c9138cee0f0859bcab636a004ce92ca4a9ab5Eric Laurent if (status) { 21519f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent mScoAudioState = SCO_STATE_ACTIVE_INTERNAL; 21529f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent } else { 21539f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent broadcastScoConnectionState( 21549f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent AudioManager.SCO_AUDIO_STATE_DISCONNECTED); 21559f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent } 21569f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent } else if (getBluetoothHeadset()) { 21579f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent mScoAudioState = SCO_STATE_ACTIVATE_REQ; 2158dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent } 21599f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent } else { 21609f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent mScoAudioState = SCO_STATE_ACTIVE_INTERNAL; 21619f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent broadcastScoConnectionState(AudioManager.SCO_AUDIO_STATE_CONNECTED); 2162dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent } 2163dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent } else { 21649f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent broadcastScoConnectionState(AudioManager.SCO_AUDIO_STATE_DISCONNECTED); 2165dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent } 2166dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent } 216762ef767b15a712bab31cc0d5508a330906f535c2Eric Laurent } else if (state == BluetoothHeadset.STATE_AUDIO_DISCONNECTED && 2168dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent (mScoAudioState == SCO_STATE_ACTIVE_INTERNAL || 2169dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent mScoAudioState == SCO_STATE_ACTIVATE_REQ)) { 2170dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent if (mScoAudioState == SCO_STATE_ACTIVE_INTERNAL) { 2171671db6f3ba1fdb3c907e0735fe6d0d284f5c34deMarco Nelissen if (mBluetoothHeadset != null && mBluetoothHeadsetDevice != null) { 2172c18c9138cee0f0859bcab636a004ce92ca4a9ab5Eric Laurent boolean status; 2173c18c9138cee0f0859bcab636a004ce92ca4a9ab5Eric Laurent if (mScoAudioMode == SCO_MODE_RAW) { 2174c18c9138cee0f0859bcab636a004ce92ca4a9ab5Eric Laurent status = mBluetoothHeadset.disconnectAudio(); 2175c18c9138cee0f0859bcab636a004ce92ca4a9ab5Eric Laurent } else { 2176c18c9138cee0f0859bcab636a004ce92ca4a9ab5Eric Laurent status = mBluetoothHeadset.stopScoUsingVirtualVoiceCall( 2177c18c9138cee0f0859bcab636a004ce92ca4a9ab5Eric Laurent mBluetoothHeadsetDevice); 2178c18c9138cee0f0859bcab636a004ce92ca4a9ab5Eric Laurent } 2179c18c9138cee0f0859bcab636a004ce92ca4a9ab5Eric Laurent if (!status) { 2180dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent mScoAudioState = SCO_STATE_INACTIVE; 2181dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent broadcastScoConnectionState( 2182dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent AudioManager.SCO_AUDIO_STATE_DISCONNECTED); 2183dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent } 2184dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent } else if (getBluetoothHeadset()) { 2185dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent mScoAudioState = SCO_STATE_DEACTIVATE_REQ; 2186dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent } 2187dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent } else { 2188dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent mScoAudioState = SCO_STATE_INACTIVE; 2189dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent broadcastScoConnectionState(AudioManager.SCO_AUDIO_STATE_DISCONNECTED); 2190dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent } 21913def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent } 21923def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent } 21933def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent } 21943def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent } 21953def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent 219662ef767b15a712bab31cc0d5508a330906f535c2Eric Laurent private void checkScoAudioState() { 219762ef767b15a712bab31cc0d5508a330906f535c2Eric Laurent if (mBluetoothHeadset != null && mBluetoothHeadsetDevice != null && 2198dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent mScoAudioState == SCO_STATE_INACTIVE && 219962ef767b15a712bab31cc0d5508a330906f535c2Eric Laurent mBluetoothHeadset.getAudioState(mBluetoothHeadsetDevice) 220062ef767b15a712bab31cc0d5508a330906f535c2Eric Laurent != BluetoothHeadset.STATE_AUDIO_DISCONNECTED) { 220162ef767b15a712bab31cc0d5508a330906f535c2Eric Laurent mScoAudioState = SCO_STATE_ACTIVE_EXTERNAL; 220262ef767b15a712bab31cc0d5508a330906f535c2Eric Laurent } 220362ef767b15a712bab31cc0d5508a330906f535c2Eric Laurent } 220462ef767b15a712bab31cc0d5508a330906f535c2Eric Laurent 2205854938a72d968c1bc0de4e2b0ea87777cfebc045Eric Laurent private ScoClient getScoClient(IBinder cb, boolean create) { 22063def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent synchronized(mScoClients) { 2207854938a72d968c1bc0de4e2b0ea87777cfebc045Eric Laurent ScoClient client = null; 22083def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent int size = mScoClients.size(); 22093def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent for (int i = 0; i < size; i++) { 22103def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent client = mScoClients.get(i); 22113def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent if (client.getBinder() == cb) 22123def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent return client; 22133def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent } 2214854938a72d968c1bc0de4e2b0ea87777cfebc045Eric Laurent if (create) { 2215854938a72d968c1bc0de4e2b0ea87777cfebc045Eric Laurent client = new ScoClient(cb); 2216854938a72d968c1bc0de4e2b0ea87777cfebc045Eric Laurent mScoClients.add(client); 2217854938a72d968c1bc0de4e2b0ea87777cfebc045Eric Laurent } 22183def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent return client; 22193def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent } 22203def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent } 22213def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent 2222d7454be47f4111c0478a502353e11dea401378bdEric Laurent public void clearAllScoClients(int exceptPid, boolean stopSco) { 22233def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent synchronized(mScoClients) { 2224854938a72d968c1bc0de4e2b0ea87777cfebc045Eric Laurent ScoClient savedClient = null; 22253def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent int size = mScoClients.size(); 22263def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent for (int i = 0; i < size; i++) { 2227854938a72d968c1bc0de4e2b0ea87777cfebc045Eric Laurent ScoClient cl = mScoClients.get(i); 2228d7454be47f4111c0478a502353e11dea401378bdEric Laurent if (cl.getPid() != exceptPid) { 2229854938a72d968c1bc0de4e2b0ea87777cfebc045Eric Laurent cl.clearCount(stopSco); 2230854938a72d968c1bc0de4e2b0ea87777cfebc045Eric Laurent } else { 2231854938a72d968c1bc0de4e2b0ea87777cfebc045Eric Laurent savedClient = cl; 2232854938a72d968c1bc0de4e2b0ea87777cfebc045Eric Laurent } 2233854938a72d968c1bc0de4e2b0ea87777cfebc045Eric Laurent } 2234854938a72d968c1bc0de4e2b0ea87777cfebc045Eric Laurent mScoClients.clear(); 2235854938a72d968c1bc0de4e2b0ea87777cfebc045Eric Laurent if (savedClient != null) { 2236854938a72d968c1bc0de4e2b0ea87777cfebc045Eric Laurent mScoClients.add(savedClient); 22373def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent } 22383def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent } 22393def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent } 22403def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent 2241dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent private boolean getBluetoothHeadset() { 2242dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent boolean result = false; 2243dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter(); 2244dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent if (adapter != null) { 2245dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent result = adapter.getProfileProxy(mContext, mBluetoothProfileServiceListener, 2246dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent BluetoothProfile.HEADSET); 2247dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent } 2248dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent // If we could not get a bluetooth headset proxy, send a failure message 2249dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent // without delay to reset the SCO audio state and clear SCO clients. 2250dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent // If we could get a proxy, send a delayed failure message that will reset our state 2251dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent // in case we don't receive onServiceConnected(). 2252afbb047c3945e9c2b7e9bc6b25098d5fb80bba4eEric Laurent sendMsg(mAudioHandler, MSG_BT_HEADSET_CNCT_FAILED, 2253dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent SENDMSG_REPLACE, 0, 0, null, result ? BT_HEADSET_CNCT_TIMEOUT_MS : 0); 2254dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent return result; 2255dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent } 2256dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent 2257d7454be47f4111c0478a502353e11dea401378bdEric Laurent private void disconnectBluetoothSco(int exceptPid) { 2258dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent synchronized(mScoClients) { 2259dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent checkScoAudioState(); 2260dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent if (mScoAudioState == SCO_STATE_ACTIVE_EXTERNAL || 2261dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent mScoAudioState == SCO_STATE_DEACTIVATE_EXT_REQ) { 2262dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent if (mBluetoothHeadsetDevice != null) { 2263dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent if (mBluetoothHeadset != null) { 2264dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent if (!mBluetoothHeadset.stopVoiceRecognition( 2265b06ac839dd2d0437fc8314f6deb7233af5af521eEric Laurent mBluetoothHeadsetDevice)) { 2266afbb047c3945e9c2b7e9bc6b25098d5fb80bba4eEric Laurent sendMsg(mAudioHandler, MSG_BT_HEADSET_CNCT_FAILED, 2267dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent SENDMSG_REPLACE, 0, 0, null, 0); 2268dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent } 2269dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent } else if (mScoAudioState == SCO_STATE_ACTIVE_EXTERNAL && 2270dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent getBluetoothHeadset()) { 2271dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent mScoAudioState = SCO_STATE_DEACTIVATE_EXT_REQ; 2272dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent } 2273dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent } 2274dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent } else { 2275d7454be47f4111c0478a502353e11dea401378bdEric Laurent clearAllScoClients(exceptPid, true); 2276dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent } 2277dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent } 2278dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent } 2279dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent 2280dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent private void resetBluetoothSco() { 2281dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent synchronized(mScoClients) { 2282d7454be47f4111c0478a502353e11dea401378bdEric Laurent clearAllScoClients(0, false); 2283dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent mScoAudioState = SCO_STATE_INACTIVE; 2284dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent broadcastScoConnectionState(AudioManager.SCO_AUDIO_STATE_DISCONNECTED); 2285dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent } 2286dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent } 2287dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent 2288dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent private void broadcastScoConnectionState(int state) { 22892a57ca931fefe817b6110101289721acaacfc808Eric Laurent sendMsg(mAudioHandler, MSG_BROADCAST_BT_CONNECTION_STATE, 22902a57ca931fefe817b6110101289721acaacfc808Eric Laurent SENDMSG_QUEUE, state, 0, null, 0); 22912a57ca931fefe817b6110101289721acaacfc808Eric Laurent } 22922a57ca931fefe817b6110101289721acaacfc808Eric Laurent 22932a57ca931fefe817b6110101289721acaacfc808Eric Laurent private void onBroadcastScoConnectionState(int state) { 2294dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent if (state != mScoConnectionState) { 2295dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent Intent newIntent = new Intent(AudioManager.ACTION_SCO_AUDIO_STATE_UPDATED); 2296dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent newIntent.putExtra(AudioManager.EXTRA_SCO_AUDIO_STATE, state); 2297dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent newIntent.putExtra(AudioManager.EXTRA_SCO_AUDIO_PREVIOUS_STATE, 2298dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent mScoConnectionState); 22995ac72a29593ab9a20337a2225df52bdf4754be02Dianne Hackborn sendStickyBroadcastToAll(newIntent); 2300dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent mScoConnectionState = state; 2301dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent } 2302dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent } 2303dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent 230482aa7f017daaaeb96c13e6e3491d5037ab471085Jaikumar Ganesh private BluetoothProfile.ServiceListener mBluetoothProfileServiceListener = 230582aa7f017daaaeb96c13e6e3491d5037ab471085Jaikumar Ganesh new BluetoothProfile.ServiceListener() { 230682aa7f017daaaeb96c13e6e3491d5037ab471085Jaikumar Ganesh public void onServiceConnected(int profile, BluetoothProfile proxy) { 23076bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent BluetoothDevice btDevice; 23086bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent List<BluetoothDevice> deviceList; 23096bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent switch(profile) { 23106bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent case BluetoothProfile.A2DP: 23115a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du synchronized (mA2dpAvrcpLock) { 23125a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du mA2dp = (BluetoothA2dp) proxy; 23135a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du deviceList = mA2dp.getConnectedDevices(); 23145a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du if (deviceList.size() > 0) { 23155a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du btDevice = deviceList.get(0); 23165a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du synchronized (mConnectedDevices) { 23175a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du int state = mA2dp.getConnectionState(btDevice); 23185a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du int delay = checkSendBecomingNoisyIntent( 23195a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, 23205a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du (state == BluetoothA2dp.STATE_CONNECTED) ? 1 : 0); 23215a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du queueMsgUnderWakeLock(mAudioHandler, 23225a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du MSG_SET_A2DP_CONNECTION_STATE, 23235a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du state, 23245a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du 0, 23255a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du btDevice, 23265a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du delay); 23275a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du } 2328b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent } 23296bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent } 23306bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent break; 23316bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent 23326bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent case BluetoothProfile.HEADSET: 23336bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent synchronized (mScoClients) { 23346bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent // Discard timeout message 23356bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent mAudioHandler.removeMessages(MSG_BT_HEADSET_CNCT_FAILED); 23366bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent mBluetoothHeadset = (BluetoothHeadset) proxy; 23376bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent deviceList = mBluetoothHeadset.getConnectedDevices(); 23386bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent if (deviceList.size() > 0) { 23396bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent mBluetoothHeadsetDevice = deviceList.get(0); 23406bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent } else { 23416bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent mBluetoothHeadsetDevice = null; 2342dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent } 23436bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent // Refresh SCO audio state 23446bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent checkScoAudioState(); 23456bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent // Continue pending action if any 23466bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent if (mScoAudioState == SCO_STATE_ACTIVATE_REQ || 23476bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent mScoAudioState == SCO_STATE_DEACTIVATE_REQ || 23486bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent mScoAudioState == SCO_STATE_DEACTIVATE_EXT_REQ) { 23496bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent boolean status = false; 23506bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent if (mBluetoothHeadsetDevice != null) { 23516bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent switch (mScoAudioState) { 23526bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent case SCO_STATE_ACTIVATE_REQ: 23536bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent mScoAudioState = SCO_STATE_ACTIVE_INTERNAL; 2354c18c9138cee0f0859bcab636a004ce92ca4a9ab5Eric Laurent if (mScoAudioMode == SCO_MODE_RAW) { 2355c18c9138cee0f0859bcab636a004ce92ca4a9ab5Eric Laurent status = mBluetoothHeadset.connectAudio(); 2356c18c9138cee0f0859bcab636a004ce92ca4a9ab5Eric Laurent } else { 2357c18c9138cee0f0859bcab636a004ce92ca4a9ab5Eric Laurent status = mBluetoothHeadset.startScoUsingVirtualVoiceCall( 2358c18c9138cee0f0859bcab636a004ce92ca4a9ab5Eric Laurent mBluetoothHeadsetDevice); 2359c18c9138cee0f0859bcab636a004ce92ca4a9ab5Eric Laurent } 23606bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent break; 23616bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent case SCO_STATE_DEACTIVATE_REQ: 2362c18c9138cee0f0859bcab636a004ce92ca4a9ab5Eric Laurent if (mScoAudioMode == SCO_MODE_RAW) { 2363c18c9138cee0f0859bcab636a004ce92ca4a9ab5Eric Laurent status = mBluetoothHeadset.disconnectAudio(); 2364c18c9138cee0f0859bcab636a004ce92ca4a9ab5Eric Laurent } else { 2365c18c9138cee0f0859bcab636a004ce92ca4a9ab5Eric Laurent status = mBluetoothHeadset.stopScoUsingVirtualVoiceCall( 2366c18c9138cee0f0859bcab636a004ce92ca4a9ab5Eric Laurent mBluetoothHeadsetDevice); 2367c18c9138cee0f0859bcab636a004ce92ca4a9ab5Eric Laurent } 23686bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent break; 23696bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent case SCO_STATE_DEACTIVATE_EXT_REQ: 23706bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent status = mBluetoothHeadset.stopVoiceRecognition( 23716bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent mBluetoothHeadsetDevice); 23726bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent } 23736bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent } 23746bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent if (!status) { 2375afbb047c3945e9c2b7e9bc6b25098d5fb80bba4eEric Laurent sendMsg(mAudioHandler, MSG_BT_HEADSET_CNCT_FAILED, 23766bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent SENDMSG_REPLACE, 0, 0, null, 0); 23776bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent } 2378dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent } 2379dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent } 23806bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent break; 23816bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent 23826bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent default: 23836bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent break; 23843def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent } 23853def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent } 238682aa7f017daaaeb96c13e6e3491d5037ab471085Jaikumar Ganesh public void onServiceDisconnected(int profile) { 23876bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent switch(profile) { 23886bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent case BluetoothProfile.A2DP: 23895a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du synchronized (mA2dpAvrcpLock) { 23905a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du mA2dp = null; 23915a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du synchronized (mConnectedDevices) { 23925a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du if (mConnectedDevices.containsKey(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP)) { 23935a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du makeA2dpDeviceUnavailableNow( 23945a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du mConnectedDevices.get(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP)); 23955a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du } 23966bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent } 23976bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent } 23986bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent break; 23996bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent 24006bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent case BluetoothProfile.HEADSET: 24016bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent synchronized (mScoClients) { 24026bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent mBluetoothHeadset = null; 24036bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent } 24046bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent break; 24056bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent 24066bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent default: 24076bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent break; 24083def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent } 24093def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent } 24103def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent }; 2411d5176cfe6eae954e9cef1e2ec17859a5089e1330Jean-Michel Trivi 2412c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent private void onCheckMusicActive() { 2413d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent synchronized (mSafeMediaVolumeState) { 2414d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent if (mSafeMediaVolumeState == SAFE_MEDIA_VOLUME_INACTIVE) { 2415c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent int device = getDeviceForStream(AudioSystem.STREAM_MUSIC); 2416c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent 2417c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent if ((device & mSafeMediaVolumeDevices) != 0) { 2418c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent sendMsg(mAudioHandler, 2419c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent MSG_CHECK_MUSIC_ACTIVE, 2420c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent SENDMSG_REPLACE, 2421f1a457d06c53a901ea08d2d3fb6e766bc06c4d4fEric Laurent 0, 2422c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent 0, 2423c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent null, 2424c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent MUSIC_ACTIVE_POLL_PERIOD_MS); 242542b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent int index = mStreamStates[AudioSystem.STREAM_MUSIC].getIndex(device); 2426f1a457d06c53a901ea08d2d3fb6e766bc06c4d4fEric Laurent if (AudioSystem.isStreamActive(AudioSystem.STREAM_MUSIC, 0) && 2427f1a457d06c53a901ea08d2d3fb6e766bc06c4d4fEric Laurent (index > mSafeMediaVolumeIndex)) { 2428c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent // Approximate cumulative active music time 2429c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent mMusicActiveMs += MUSIC_ACTIVE_POLL_PERIOD_MS; 2430c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent if (mMusicActiveMs > UNSAFE_VOLUME_MUSIC_ACTIVE_MS_MAX) { 2431c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent setSafeMediaVolumeEnabled(true); 2432c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent mMusicActiveMs = 0; 2433c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent } 2434c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent } 2435c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent } 2436c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent } 2437c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent } 2438c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent } 2439c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent 2440d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent private void onConfigureSafeVolume(boolean force) { 2441d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent synchronized (mSafeMediaVolumeState) { 2442d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent int mcc = mContext.getResources().getConfiguration().mcc; 2443d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent if ((mMcc != mcc) || ((mMcc == 0) && force)) { 2444d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent mSafeMediaVolumeIndex = mContext.getResources().getInteger( 2445d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent com.android.internal.R.integer.config_safe_media_volume_index) * 10; 2446d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent boolean safeMediaVolumeEnabled = mContext.getResources().getBoolean( 2447d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent com.android.internal.R.bool.config_safe_media_volume_enabled); 244805274f348e12983eb8613cc6eb9ae561e8197e28Eric Laurent 244905274f348e12983eb8613cc6eb9ae561e8197e28Eric Laurent // The persisted state is either "disabled" or "active": this is the state applied 245005274f348e12983eb8613cc6eb9ae561e8197e28Eric Laurent // next time we boot and cannot be "inactive" 245105274f348e12983eb8613cc6eb9ae561e8197e28Eric Laurent int persistedState; 2452d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent if (safeMediaVolumeEnabled) { 245305274f348e12983eb8613cc6eb9ae561e8197e28Eric Laurent persistedState = SAFE_MEDIA_VOLUME_ACTIVE; 245405274f348e12983eb8613cc6eb9ae561e8197e28Eric Laurent // The state can already be "inactive" here if the user has forced it before 245505274f348e12983eb8613cc6eb9ae561e8197e28Eric Laurent // the 30 seconds timeout for forced configuration. In this case we don't reset 245605274f348e12983eb8613cc6eb9ae561e8197e28Eric Laurent // it to "active". 245705274f348e12983eb8613cc6eb9ae561e8197e28Eric Laurent if (mSafeMediaVolumeState != SAFE_MEDIA_VOLUME_INACTIVE) { 245805274f348e12983eb8613cc6eb9ae561e8197e28Eric Laurent mSafeMediaVolumeState = SAFE_MEDIA_VOLUME_ACTIVE; 245905274f348e12983eb8613cc6eb9ae561e8197e28Eric Laurent enforceSafeMediaVolume(); 246005274f348e12983eb8613cc6eb9ae561e8197e28Eric Laurent } 2461d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent } else { 246205274f348e12983eb8613cc6eb9ae561e8197e28Eric Laurent persistedState = SAFE_MEDIA_VOLUME_DISABLED; 2463d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent mSafeMediaVolumeState = SAFE_MEDIA_VOLUME_DISABLED; 2464d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent } 2465d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent mMcc = mcc; 246605274f348e12983eb8613cc6eb9ae561e8197e28Eric Laurent sendMsg(mAudioHandler, 246705274f348e12983eb8613cc6eb9ae561e8197e28Eric Laurent MSG_PERSIST_SAFE_VOLUME_STATE, 246805274f348e12983eb8613cc6eb9ae561e8197e28Eric Laurent SENDMSG_QUEUE, 246905274f348e12983eb8613cc6eb9ae561e8197e28Eric Laurent persistedState, 247005274f348e12983eb8613cc6eb9ae561e8197e28Eric Laurent 0, 247105274f348e12983eb8613cc6eb9ae561e8197e28Eric Laurent null, 247205274f348e12983eb8613cc6eb9ae561e8197e28Eric Laurent 0); 2473d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent } 2474d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent } 2475d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent } 2476d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent 24779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /////////////////////////////////////////////////////////////////////////// 24789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Internal methods 24799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /////////////////////////////////////////////////////////////////////////// 24809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 24819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 24829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Checks if the adjustment should change ringer mode instead of just 24839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * adjusting volume. If so, this will set the proper ringer mode and volume 24849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * indices on the stream states. 24859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 2486244820185269991186d07068b92985624cede4a5Eric Laurent private boolean checkForRingerModeChange(int oldIndex, int direction, int step) { 24879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project boolean adjustVolumeIndex = true; 2488ba195ebc76f23b6679443724ab58c9dc9f2df884Glenn Kasten int ringerMode = getRingerMode(); 2489bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent 2490bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent switch (ringerMode) { 2491bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent case RINGER_MODE_NORMAL: 2492bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent if (direction == AudioManager.ADJUST_LOWER) { 2493bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent if (mHasVibrator) { 2494244820185269991186d07068b92985624cede4a5Eric Laurent // "step" is the delta in internal index units corresponding to a 2495244820185269991186d07068b92985624cede4a5Eric Laurent // change of 1 in UI index units. 2496244820185269991186d07068b92985624cede4a5Eric Laurent // Because of rounding when rescaling from one stream index range to its alias 2497244820185269991186d07068b92985624cede4a5Eric Laurent // index range, we cannot simply test oldIndex == step: 2498244820185269991186d07068b92985624cede4a5Eric Laurent // (step <= oldIndex < 2 * step) is equivalent to: (old UI index == 1) 2499244820185269991186d07068b92985624cede4a5Eric Laurent if (step <= oldIndex && oldIndex < 2 * step) { 2500bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent ringerMode = RINGER_MODE_VIBRATE; 2501bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent } 2502bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent } else { 2503244820185269991186d07068b92985624cede4a5Eric Laurent // (oldIndex < step) is equivalent to (old UI index == 0) 2504244820185269991186d07068b92985624cede4a5Eric Laurent if ((oldIndex < step) && mPrevVolDirection != AudioManager.ADJUST_LOWER) { 2505bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent ringerMode = RINGER_MODE_SILENT; 2506bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent } 25073d4c06f90726a85e89dab13c41ddc15b9c912a3fEric Laurent } 25086329bf7b1e2217c6c9477bd57349a1edade18417Daniel Sandler } 2509bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent break; 2510bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent case RINGER_MODE_VIBRATE: 2511bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent if (!mHasVibrator) { 2512bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent Log.e(TAG, "checkForRingerModeChange() current ringer mode is vibrate" + 2513bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent "but no vibrator is present"); 2514bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent break; 2515bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent } 2516c696a53d1fe4d61373c5dc64dd057d322da90c8fAmith Yamasani if ((direction == AudioManager.ADJUST_LOWER)) { 2517c696a53d1fe4d61373c5dc64dd057d322da90c8fAmith Yamasani if (mPrevVolDirection != AudioManager.ADJUST_LOWER) { 2518bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent ringerMode = RINGER_MODE_SILENT; 2519c696a53d1fe4d61373c5dc64dd057d322da90c8fAmith Yamasani } 2520c696a53d1fe4d61373c5dc64dd057d322da90c8fAmith Yamasani } else if (direction == AudioManager.ADJUST_RAISE) { 2521bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent ringerMode = RINGER_MODE_NORMAL; 2522c696a53d1fe4d61373c5dc64dd057d322da90c8fAmith Yamasani } 2523c696a53d1fe4d61373c5dc64dd057d322da90c8fAmith Yamasani adjustVolumeIndex = false; 2524bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent break; 2525bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent case RINGER_MODE_SILENT: 25269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (direction == AudioManager.ADJUST_RAISE) { 2527bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent if (mHasVibrator) { 2528bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent ringerMode = RINGER_MODE_VIBRATE; 2529bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent } else { 2530bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent ringerMode = RINGER_MODE_NORMAL; 2531bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent } 25329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2533b024c30a80684ac08daef3137b7ba0d347fe3ce5Eric Laurent adjustVolumeIndex = false; 2534bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent break; 2535bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent default: 2536bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent Log.e(TAG, "checkForRingerModeChange() wrong ringer mode: "+ringerMode); 2537bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent break; 25389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 25399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2540bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent setRingerMode(ringerMode); 25419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 254225101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent mPrevVolDirection = direction; 254325101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent 25449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return adjustVolumeIndex; 25459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 25469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 25479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public boolean isStreamAffectedByRingerMode(int streamType) { 25489bcf401d13d47416043a704430388abd59aef7cdEric Laurent return (mRingerModeAffectedStreams & (1 << streamType)) != 0; 25499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 25509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 25515b4e654d0c7de8e4d58d73e73b0d5220f19b68f7Eric Laurent private boolean isStreamMutedByRingerMode(int streamType) { 25525b4e654d0c7de8e4d58d73e73b0d5220f19b68f7Eric Laurent return (mRingerModeMutedStreams & (1 << streamType)) != 0; 25535b4e654d0c7de8e4d58d73e73b0d5220f19b68f7Eric Laurent } 25545b4e654d0c7de8e4d58d73e73b0d5220f19b68f7Eric Laurent 255524e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent boolean updateRingerModeAffectedStreams() { 255624e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent int ringerModeAffectedStreams; 255724e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent // make sure settings for ringer mode are consistent with device type: non voice capable 255824e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent // devices (tablets) include media stream in silent mode whereas phones don't. 255924e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent ringerModeAffectedStreams = Settings.System.getIntForUser(mContentResolver, 256024e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent Settings.System.MODE_RINGER_STREAMS_AFFECTED, 256124e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent ((1 << AudioSystem.STREAM_RING)|(1 << AudioSystem.STREAM_NOTIFICATION)| 256224e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent (1 << AudioSystem.STREAM_SYSTEM)|(1 << AudioSystem.STREAM_SYSTEM_ENFORCED)), 256324e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent UserHandle.USER_CURRENT); 256424e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent 256524e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent // ringtone, notification and system streams are always affected by ringer mode 256624e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent ringerModeAffectedStreams |= (1 << AudioSystem.STREAM_RING)| 256724e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent (1 << AudioSystem.STREAM_NOTIFICATION)| 256824e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent (1 << AudioSystem.STREAM_SYSTEM); 256924e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent 257024e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent if (mVoiceCapable) { 257124e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent ringerModeAffectedStreams &= ~(1 << AudioSystem.STREAM_MUSIC); 257224e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent } else { 257324e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent ringerModeAffectedStreams |= (1 << AudioSystem.STREAM_MUSIC); 257424e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent } 257524e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent synchronized (mCameraSoundForced) { 257624e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent if (mCameraSoundForced) { 257724e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent ringerModeAffectedStreams &= ~(1 << AudioSystem.STREAM_SYSTEM_ENFORCED); 257824e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent } else { 257924e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent ringerModeAffectedStreams |= (1 << AudioSystem.STREAM_SYSTEM_ENFORCED); 258024e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent } 258124e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent } 258224e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent if (mStreamVolumeAlias[AudioSystem.STREAM_DTMF] == AudioSystem.STREAM_RING) { 258324e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent ringerModeAffectedStreams |= (1 << AudioSystem.STREAM_DTMF); 258424e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent } else { 258524e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent ringerModeAffectedStreams &= ~(1 << AudioSystem.STREAM_DTMF); 258624e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent } 258724e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent 258824e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent if (ringerModeAffectedStreams != mRingerModeAffectedStreams) { 258924e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent Settings.System.putIntForUser(mContentResolver, 259024e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent Settings.System.MODE_RINGER_STREAMS_AFFECTED, 259124e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent ringerModeAffectedStreams, 259224e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent UserHandle.USER_CURRENT); 259324e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent mRingerModeAffectedStreams = ringerModeAffectedStreams; 259424e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent return true; 259524e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent } 259624e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent return false; 259724e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent } 259824e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent 25999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public boolean isStreamAffectedByMute(int streamType) { 26009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return (mMuteAffectedStreams & (1 << streamType)) != 0; 26019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 26029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 26039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private void ensureValidDirection(int direction) { 26049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (direction < AudioManager.ADJUST_LOWER || direction > AudioManager.ADJUST_RAISE) { 26059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw new IllegalArgumentException("Bad direction " + direction); 26069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 26079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 26089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 26096c798970ccb8759d1e613b57111daa8da0ab44c7Lei Zhang private void ensureValidSteps(int steps) { 26106c798970ccb8759d1e613b57111daa8da0ab44c7Lei Zhang if (Math.abs(steps) > MAX_BATCH_VOLUME_ADJUST_STEPS) { 26116c798970ccb8759d1e613b57111daa8da0ab44c7Lei Zhang throw new IllegalArgumentException("Bad volume adjust steps " + steps); 26126c798970ccb8759d1e613b57111daa8da0ab44c7Lei Zhang } 26136c798970ccb8759d1e613b57111daa8da0ab44c7Lei Zhang } 26146c798970ccb8759d1e613b57111daa8da0ab44c7Lei Zhang 26159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private void ensureValidStreamType(int streamType) { 26169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (streamType < 0 || streamType >= mStreamStates.length) { 26179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw new IllegalArgumentException("Bad stream type " + streamType); 26189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 26199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 26209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 26216d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent private boolean isInCommunication() { 26226d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent boolean isOffhook = false; 262325101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent 262425101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent if (mVoiceCapable) { 262525101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent try { 262625101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent ITelephony phone = ITelephony.Stub.asInterface(ServiceManager.checkService("phone")); 262725101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent if (phone != null) isOffhook = phone.isOffhook(); 262825101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent } catch (RemoteException e) { 262925101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent Log.w(TAG, "Couldn't connect to phone service", e); 263025101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent } 26316d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent } 26326d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent return (isOffhook || getMode() == AudioManager.MODE_IN_COMMUNICATION); 26336d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent } 263425101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent 2635fca1e603236b8d1681f784e77e3719d1d59c1428Jean-Michel Trivi /** 2636fca1e603236b8d1681f784e77e3719d1d59c1428Jean-Michel Trivi * For code clarity for getActiveStreamType(int) 2637fca1e603236b8d1681f784e77e3719d1d59c1428Jean-Michel Trivi * @param delay_ms max time since last STREAM_MUSIC activity to consider 2638fca1e603236b8d1681f784e77e3719d1d59c1428Jean-Michel Trivi * @return true if STREAM_MUSIC is active in streams handled by AudioFlinger now or 2639fca1e603236b8d1681f784e77e3719d1d59c1428Jean-Michel Trivi * in the last "delay_ms" ms. 2640fca1e603236b8d1681f784e77e3719d1d59c1428Jean-Michel Trivi */ 2641fca1e603236b8d1681f784e77e3719d1d59c1428Jean-Michel Trivi private boolean isAfMusicActiveRecently(int delay_ms) { 2642fca1e603236b8d1681f784e77e3719d1d59c1428Jean-Michel Trivi return AudioSystem.isStreamActive(AudioSystem.STREAM_MUSIC, delay_ms) 2643fca1e603236b8d1681f784e77e3719d1d59c1428Jean-Michel Trivi || AudioSystem.isStreamActiveRemotely(AudioSystem.STREAM_MUSIC, delay_ms); 2644fca1e603236b8d1681f784e77e3719d1d59c1428Jean-Michel Trivi } 2645fca1e603236b8d1681f784e77e3719d1d59c1428Jean-Michel Trivi 26466d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent private int getActiveStreamType(int suggestedStreamType) { 26476d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent if (mVoiceCapable) { 26486d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent if (isInCommunication()) { 264925101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent if (AudioSystem.getForceUse(AudioSystem.FOR_COMMUNICATION) 265025101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent == AudioSystem.FORCE_BT_SCO) { 265125101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent // Log.v(TAG, "getActiveStreamType: Forcing STREAM_BLUETOOTH_SCO..."); 265225101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent return AudioSystem.STREAM_BLUETOOTH_SCO; 265325101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent } else { 265425101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent // Log.v(TAG, "getActiveStreamType: Forcing STREAM_VOICE_CALL..."); 265525101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent return AudioSystem.STREAM_VOICE_CALL; 265625101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent } 26573114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi } else if (suggestedStreamType == AudioManager.USE_DEFAULT_STREAM_TYPE) { 2658fca1e603236b8d1681f784e77e3719d1d59c1428Jean-Michel Trivi if (isAfMusicActiveRecently(DEFAULT_STREAM_TYPE_OVERRIDE_DELAY_MS)) { 26593114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi if (DEBUG_VOL) 26603114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi Log.v(TAG, "getActiveStreamType: Forcing STREAM_MUSIC stream active"); 26613114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi return AudioSystem.STREAM_MUSIC; 2662fca1e603236b8d1681f784e77e3719d1d59c1428Jean-Michel Trivi } else 2663fca1e603236b8d1681f784e77e3719d1d59c1428Jean-Michel Trivi if (mMediaFocusControl.checkUpdateRemoteStateIfActive(AudioSystem.STREAM_MUSIC)) 2664fca1e603236b8d1681f784e77e3719d1d59c1428Jean-Michel Trivi { 2665fca1e603236b8d1681f784e77e3719d1d59c1428Jean-Michel Trivi if (DEBUG_VOL) 2666fca1e603236b8d1681f784e77e3719d1d59c1428Jean-Michel Trivi Log.v(TAG, "getActiveStreamType: Forcing STREAM_REMOTE_MUSIC"); 2667fca1e603236b8d1681f784e77e3719d1d59c1428Jean-Michel Trivi return STREAM_REMOTE_MUSIC; 2668fca1e603236b8d1681f784e77e3719d1d59c1428Jean-Michel Trivi } else { 2669fca1e603236b8d1681f784e77e3719d1d59c1428Jean-Michel Trivi if (DEBUG_VOL) 2670fca1e603236b8d1681f784e77e3719d1d59c1428Jean-Michel Trivi Log.v(TAG, "getActiveStreamType: Forcing STREAM_RING b/c default"); 2671fca1e603236b8d1681f784e77e3719d1d59c1428Jean-Michel Trivi return AudioSystem.STREAM_RING; 26723114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi } 2673fca1e603236b8d1681f784e77e3719d1d59c1428Jean-Michel Trivi } else if (isAfMusicActiveRecently(0)) { 26743114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi if (DEBUG_VOL) 26753114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi Log.v(TAG, "getActiveStreamType: Forcing STREAM_MUSIC stream active"); 267625101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent return AudioSystem.STREAM_MUSIC; 2677c7fcba4b7bd3d78e7cfe975a3f8e4dde2f6738b7Joe Onorato } else { 26783114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi if (DEBUG_VOL) Log.v(TAG, "getActiveStreamType: Returning suggested type " 26793114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi + suggestedStreamType); 268025101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent return suggestedStreamType; 268125101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent } 268225101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent } else { 26836d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent if (isInCommunication()) { 268425101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent if (AudioSystem.getForceUse(AudioSystem.FOR_COMMUNICATION) 268525101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent == AudioSystem.FORCE_BT_SCO) { 26863114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi if (DEBUG_VOL) Log.v(TAG, "getActiveStreamType: Forcing STREAM_BLUETOOTH_SCO"); 268725101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent return AudioSystem.STREAM_BLUETOOTH_SCO; 268825101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent } else { 26893114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi if (DEBUG_VOL) Log.v(TAG, "getActiveStreamType: Forcing STREAM_VOICE_CALL"); 269025101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent return AudioSystem.STREAM_VOICE_CALL; 269125101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent } 269225101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent } else if (AudioSystem.isStreamActive(AudioSystem.STREAM_NOTIFICATION, 26939903e2638a6c502d96413680d3ebae4fb77fc412Eric Laurent DEFAULT_STREAM_TYPE_OVERRIDE_DELAY_MS) || 26943114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi AudioSystem.isStreamActive(AudioSystem.STREAM_RING, 26959903e2638a6c502d96413680d3ebae4fb77fc412Eric Laurent DEFAULT_STREAM_TYPE_OVERRIDE_DELAY_MS)) { 26963114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi if (DEBUG_VOL) Log.v(TAG, "getActiveStreamType: Forcing STREAM_NOTIFICATION"); 269725101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent return AudioSystem.STREAM_NOTIFICATION; 26983114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi } else if (suggestedStreamType == AudioManager.USE_DEFAULT_STREAM_TYPE) { 2699fca1e603236b8d1681f784e77e3719d1d59c1428Jean-Michel Trivi if (isAfMusicActiveRecently(DEFAULT_STREAM_TYPE_OVERRIDE_DELAY_MS)) { 2700fca1e603236b8d1681f784e77e3719d1d59c1428Jean-Michel Trivi if (DEBUG_VOL) Log.v(TAG, "getActiveStreamType: forcing STREAM_MUSIC"); 2701fca1e603236b8d1681f784e77e3719d1d59c1428Jean-Michel Trivi return AudioSystem.STREAM_MUSIC; 2702fca1e603236b8d1681f784e77e3719d1d59c1428Jean-Michel Trivi } else 2703fca1e603236b8d1681f784e77e3719d1d59c1428Jean-Michel Trivi if (mMediaFocusControl.checkUpdateRemoteStateIfActive(AudioSystem.STREAM_MUSIC)) 2704fca1e603236b8d1681f784e77e3719d1d59c1428Jean-Michel Trivi { 2705fca1e603236b8d1681f784e77e3719d1d59c1428Jean-Michel Trivi if (DEBUG_VOL) 2706fca1e603236b8d1681f784e77e3719d1d59c1428Jean-Michel Trivi Log.v(TAG, "getActiveStreamType: Forcing STREAM_REMOTE_MUSIC"); 2707fca1e603236b8d1681f784e77e3719d1d59c1428Jean-Michel Trivi return STREAM_REMOTE_MUSIC; 27083114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi } else { 2709fca1e603236b8d1681f784e77e3719d1d59c1428Jean-Michel Trivi if (DEBUG_VOL) Log.v(TAG, "getActiveStreamType: using STREAM_MUSIC as default"); 27103114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi return AudioSystem.STREAM_MUSIC; 27113114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi } 271225101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent } else { 27133114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi if (DEBUG_VOL) Log.v(TAG, "getActiveStreamType: Returning suggested type " 27143114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi + suggestedStreamType); 271525101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent return suggestedStreamType; 2716c7fcba4b7bd3d78e7cfe975a3f8e4dde2f6738b7Joe Onorato } 27179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 27189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 27199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2720ba195ebc76f23b6679443724ab58c9dc9f2df884Glenn Kasten private void broadcastRingerMode(int ringerMode) { 27219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Send sticky broadcast 27221c633fc89bae9bf0af6fe643ac7ad2e744f27bedDianne Hackborn Intent broadcast = new Intent(AudioManager.RINGER_MODE_CHANGED_ACTION); 2723ba195ebc76f23b6679443724ab58c9dc9f2df884Glenn Kasten broadcast.putExtra(AudioManager.EXTRA_RINGER_MODE, ringerMode); 27241c633fc89bae9bf0af6fe643ac7ad2e744f27bedDianne Hackborn broadcast.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT 27251c633fc89bae9bf0af6fe643ac7ad2e744f27bedDianne Hackborn | Intent.FLAG_RECEIVER_REPLACE_PENDING); 27265ac72a29593ab9a20337a2225df52bdf4754be02Dianne Hackborn sendStickyBroadcastToAll(broadcast); 27279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 27289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 27299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private void broadcastVibrateSetting(int vibrateType) { 27309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Send broadcast 27319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (ActivityManagerNative.isSystemReady()) { 27329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Intent broadcast = new Intent(AudioManager.VIBRATE_SETTING_CHANGED_ACTION); 27339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project broadcast.putExtra(AudioManager.EXTRA_VIBRATE_TYPE, vibrateType); 27349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project broadcast.putExtra(AudioManager.EXTRA_VIBRATE_SETTING, getVibrateSetting(vibrateType)); 27355ac72a29593ab9a20337a2225df52bdf4754be02Dianne Hackborn sendBroadcastToAll(broadcast); 27369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 27379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 27389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 27399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Message helper methods 27402d8dab5a549b25b6f36df4614d7c0166d4d099e2Jean-Michel Trivi /** 27412d8dab5a549b25b6f36df4614d7c0166d4d099e2Jean-Michel Trivi * Queue a message on the given handler's message queue, after acquiring the service wake lock. 27422d8dab5a549b25b6f36df4614d7c0166d4d099e2Jean-Michel Trivi * Note that the wake lock needs to be released after the message has been handled. 27432d8dab5a549b25b6f36df4614d7c0166d4d099e2Jean-Michel Trivi */ 27442d8dab5a549b25b6f36df4614d7c0166d4d099e2Jean-Michel Trivi private void queueMsgUnderWakeLock(Handler handler, int msg, 27452d8dab5a549b25b6f36df4614d7c0166d4d099e2Jean-Michel Trivi int arg1, int arg2, Object obj, int delay) { 2746a4dfbdc54d8898491d3a7d1d9d818c7db3fd773dEric Laurent final long ident = Binder.clearCallingIdentity(); 2747a4dfbdc54d8898491d3a7d1d9d818c7db3fd773dEric Laurent // Always acquire the wake lock as AudioService because it is released by the 2748a4dfbdc54d8898491d3a7d1d9d818c7db3fd773dEric Laurent // message handler. 2749fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi mAudioEventWakeLock.acquire(); 2750a4dfbdc54d8898491d3a7d1d9d818c7db3fd773dEric Laurent Binder.restoreCallingIdentity(ident); 27512d8dab5a549b25b6f36df4614d7c0166d4d099e2Jean-Michel Trivi sendMsg(handler, msg, SENDMSG_QUEUE, arg1, arg2, obj, delay); 27522d8dab5a549b25b6f36df4614d7c0166d4d099e2Jean-Michel Trivi } 27539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2754afbb047c3945e9c2b7e9bc6b25098d5fb80bba4eEric Laurent private static void sendMsg(Handler handler, int msg, 27559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int existingMsgPolicy, int arg1, int arg2, Object obj, int delay) { 27569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 27579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (existingMsgPolicy == SENDMSG_REPLACE) { 27589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project handler.removeMessages(msg); 27599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (existingMsgPolicy == SENDMSG_NOOP && handler.hasMessages(msg)) { 27609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 27619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 27629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2763afbb047c3945e9c2b7e9bc6b25098d5fb80bba4eEric Laurent handler.sendMessageDelayed(handler.obtainMessage(msg, arg1, arg2, obj), delay); 27649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 27659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 27669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project boolean checkAudioSettingsPermission(String method) { 27679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mContext.checkCallingOrSelfPermission("android.permission.MODIFY_AUDIO_SETTINGS") 27689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project == PackageManager.PERMISSION_GRANTED) { 27699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 27709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 27719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String msg = "Audio Settings Permission Denial: " + method + " from pid=" 27729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project + Binder.getCallingPid() 27739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project + ", uid=" + Binder.getCallingUid(); 27749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Log.w(TAG, msg); 27759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 27769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 27779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 27789bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent private int getDeviceForStream(int stream) { 27799bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent int device = AudioSystem.getDevicesForStream(stream); 27809bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent if ((device & (device - 1)) != 0) { 27819bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent // Multiple device selection is either: 27829bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent // - speaker + one other device: give priority to speaker in this case. 27839bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent // - one A2DP device + another device: happens with duplicated output. In this case 27849bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent // retain the device on the A2DP output as the other must not correspond to an active 27859bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent // selection if not the speaker. 27869bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent if ((device & AudioSystem.DEVICE_OUT_SPEAKER) != 0) { 27879bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent device = AudioSystem.DEVICE_OUT_SPEAKER; 27889bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent } else { 27899bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent device &= AudioSystem.DEVICE_OUT_ALL_A2DP; 27909bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent } 27919bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent } 27929bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent return device; 27939bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent } 27949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2795b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent public void setWiredDeviceConnectionState(int device, int state, String name) { 2796b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent synchronized (mConnectedDevices) { 2797b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent int delay = checkSendBecomingNoisyIntent(device, state); 27982d8dab5a549b25b6f36df4614d7c0166d4d099e2Jean-Michel Trivi queueMsgUnderWakeLock(mAudioHandler, 2799b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent MSG_SET_WIRED_DEVICE_CONNECTION_STATE, 2800b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent device, 2801b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent state, 2802b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent name, 2803b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent delay); 2804b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent } 2805b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent } 2806b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent 2807b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent public int setBluetoothA2dpDeviceConnectionState(BluetoothDevice device, int state) 2808b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent { 2809b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent int delay; 2810b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent synchronized (mConnectedDevices) { 2811b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent delay = checkSendBecomingNoisyIntent(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, 2812b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent (state == BluetoothA2dp.STATE_CONNECTED) ? 1 : 0); 28132d8dab5a549b25b6f36df4614d7c0166d4d099e2Jean-Michel Trivi queueMsgUnderWakeLock(mAudioHandler, 2814b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent MSG_SET_A2DP_CONNECTION_STATE, 2815b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent state, 2816b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent 0, 2817b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent device, 2818b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent delay); 2819b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent } 2820b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent return delay; 2821b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent } 2822b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent 28239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /////////////////////////////////////////////////////////////////////////// 28249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Inner classes 28259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /////////////////////////////////////////////////////////////////////////// 28269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 28279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public class VolumeStreamState { 28289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private final int mStreamType; 28299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 283011a74a75653197a3d31fe91590cd8312f5270c44Jean-Michel Trivi private String mVolumeIndexSettingName; 2831a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent private int mIndexMax; 28323172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent private final ConcurrentHashMap<Integer, Integer> mIndex = 28333172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent new ConcurrentHashMap<Integer, Integer>(8, 0.75f, 4); 28349bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent private ArrayList<VolumeDeathHandler> mDeathHandlers; //handles mute/solo clients death 28359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2836a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent private VolumeStreamState(String settingName, int streamType) { 28379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 28389bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent mVolumeIndexSettingName = settingName; 28399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 28409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mStreamType = streamType; 28415982013cfc8274ff0bafaba83c676b3a8890cba9Jared Suttles mIndexMax = MAX_STREAM_VOLUME[streamType]; 2842a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent AudioSystem.initStreamVolume(streamType, 0, mIndexMax); 2843a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent mIndexMax *= 10; 28449bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent 284533902db75011d863009585682bd08560c5b89a75Eric Laurent // mDeathHandlers must be created before calling readSettings() 28469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mDeathHandlers = new ArrayList<VolumeDeathHandler>(); 284733902db75011d863009585682bd08560c5b89a75Eric Laurent 284833902db75011d863009585682bd08560c5b89a75Eric Laurent readSettings(); 28499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 28509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 285142b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent public String getSettingNameForDevice(int device) { 285242b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent String name = mVolumeIndexSettingName; 28539bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent String suffix = AudioSystem.getDeviceName(device); 28549bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent if (suffix.isEmpty()) { 28559bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent return name; 28569bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent } 28579bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent return name + "_" + suffix; 28589bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent } 28599bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent 28603172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent public synchronized void readSettings() { 286183a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent // force maximum volume on all streams if fixed volume property is set 286283a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent if (mUseFixedVolume) { 286383a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent mIndex.put(AudioSystem.DEVICE_OUT_DEFAULT, mIndexMax); 286483a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent return; 286583a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent } 2866002e9d382d2daa7ed41636463ecdbddbd4897abaEric Laurent // do not read system stream volume from settings: this stream is always aliased 2867002e9d382d2daa7ed41636463ecdbddbd4897abaEric Laurent // to another stream type and its volume is never persisted. Values in settings can 2868002e9d382d2daa7ed41636463ecdbddbd4897abaEric Laurent // only be stale values 2869dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent if ((mStreamType == AudioSystem.STREAM_SYSTEM) || 2870002e9d382d2daa7ed41636463ecdbddbd4897abaEric Laurent (mStreamType == AudioSystem.STREAM_SYSTEM_ENFORCED)) { 2871dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent int index = 10 * AudioManager.DEFAULT_STREAM_VOLUME[mStreamType]; 2872dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent synchronized (mCameraSoundForced) { 2873dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent if (mCameraSoundForced) { 2874dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent index = mIndexMax; 2875dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent } 2876dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent } 287742b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent mIndex.put(AudioSystem.DEVICE_OUT_DEFAULT, index); 2878002e9d382d2daa7ed41636463ecdbddbd4897abaEric Laurent return; 2879002e9d382d2daa7ed41636463ecdbddbd4897abaEric Laurent } 2880002e9d382d2daa7ed41636463ecdbddbd4897abaEric Laurent 288183a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent int remainingDevices = AudioSystem.DEVICE_OUT_ALL; 288283a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent 28839bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent for (int i = 0; remainingDevices != 0; i++) { 28849bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent int device = (1 << i); 28859bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent if ((device & remainingDevices) == 0) { 28869bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent continue; 28879bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent } 28889bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent remainingDevices &= ~device; 28899bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent 28909bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent // retrieve current volume for device 289142b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent String name = getSettingNameForDevice(device); 28929ac8d0c445a3ccde40c05f0f3ad0ec4e8265d4c6Eric Laurent // if no volume stored for current stream and device, use default volume if default 28939ac8d0c445a3ccde40c05f0f3ad0ec4e8265d4c6Eric Laurent // device, continue otherwise 28949ac8d0c445a3ccde40c05f0f3ad0ec4e8265d4c6Eric Laurent int defaultIndex = (device == AudioSystem.DEVICE_OUT_DEFAULT) ? 28959ac8d0c445a3ccde40c05f0f3ad0ec4e8265d4c6Eric Laurent AudioManager.DEFAULT_STREAM_VOLUME[mStreamType] : -1; 2896bc0fab1fc2db832ef86d8a33466ec4d68b103ca0Eric Laurent int index = Settings.System.getIntForUser( 2897bc0fab1fc2db832ef86d8a33466ec4d68b103ca0Eric Laurent mContentResolver, name, defaultIndex, UserHandle.USER_CURRENT); 28989bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent if (index == -1) { 28999bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent continue; 29009bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent } 29019bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent 29023ef7549876a159dae1568429edcb57e4e7d08459Eric Laurent // ignore settings for fixed volume devices: volume should always be at max or 0 29033ef7549876a159dae1568429edcb57e4e7d08459Eric Laurent if ((mStreamVolumeAlias[mStreamType] == AudioSystem.STREAM_MUSIC) && 29043ef7549876a159dae1568429edcb57e4e7d08459Eric Laurent ((device & mFixedVolumeDevices) != 0)) { 290542b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent mIndex.put(device, (index != 0) ? mIndexMax : 0); 290642b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent } else { 2907dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent mIndex.put(device, getValidIndex(10 * index)); 2908dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent } 29099bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent } 29109bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent } 29119bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent 29129bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent public void applyDeviceVolume(int device) { 291342b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent int index; 291442b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent if (isMuted()) { 291542b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent index = 0; 2916c9d1d5f35091226e96fcfa91817480f589eb36e2Matthew Xie } else if (mStreamVolumeAlias[mStreamType] == AudioSystem.STREAM_MUSIC && 2917c9d1d5f35091226e96fcfa91817480f589eb36e2Matthew Xie (device & AudioSystem.DEVICE_OUT_ALL_A2DP) != 0 && 2918c9d1d5f35091226e96fcfa91817480f589eb36e2Matthew Xie mAvrcpAbsVolSupported) { 2919c9d1d5f35091226e96fcfa91817480f589eb36e2Matthew Xie index = (mIndexMax + 5)/10; 2920c9d1d5f35091226e96fcfa91817480f589eb36e2Matthew Xie } 2921c9d1d5f35091226e96fcfa91817480f589eb36e2Matthew Xie else { 292242b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent index = (getIndex(device) + 5)/10; 292342b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent } 292442b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent AudioSystem.setStreamVolumeIndex(mStreamType, index, device); 29259bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent } 29269bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent 29273172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent public synchronized void applyAllVolumes() { 29289bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent // apply default volume first: by convention this will reset all 29299bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent // devices volumes in audio policy manager to the supplied value 293042b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent int index; 293142b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent if (isMuted()) { 293242b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent index = 0; 293342b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent } else { 293442b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent index = (getIndex(AudioSystem.DEVICE_OUT_DEFAULT) + 5)/10; 293542b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent } 293642b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent AudioSystem.setStreamVolumeIndex(mStreamType, index, AudioSystem.DEVICE_OUT_DEFAULT); 29379bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent // then apply device specific volumes 29389bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent Set set = mIndex.entrySet(); 29399bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent Iterator i = set.iterator(); 29409bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent while (i.hasNext()) { 29419bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent Map.Entry entry = (Map.Entry)i.next(); 29429bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent int device = ((Integer)entry.getKey()).intValue(); 29439bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent if (device != AudioSystem.DEVICE_OUT_DEFAULT) { 294442b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent if (isMuted()) { 294542b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent index = 0; 294642b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent } else { 294742b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent index = ((Integer)entry.getValue() + 5)/10; 294842b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent } 294942b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent AudioSystem.setStreamVolumeIndex(mStreamType, index, device); 29509bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent } 29519bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent } 295211a74a75653197a3d31fe91590cd8312f5270c44Jean-Michel Trivi } 295311a74a75653197a3d31fe91590cd8312f5270c44Jean-Michel Trivi 29549bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent public boolean adjustIndex(int deltaIndex, int device) { 295542b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent return setIndex(getIndex(device) + deltaIndex, 295642b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent device); 29579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 29589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 295942b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent public synchronized boolean setIndex(int index, int device) { 296042b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent int oldIndex = getIndex(device); 29619bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent index = getValidIndex(index); 2962dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent synchronized (mCameraSoundForced) { 2963dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent if ((mStreamType == AudioSystem.STREAM_SYSTEM_ENFORCED) && mCameraSoundForced) { 2964dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent index = mIndexMax; 2965dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent } 2966dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent } 296783a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent mIndex.put(device, index); 29689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 29699bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent if (oldIndex != index) { 2970a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent // Apply change to all streams using this one as alias 2971bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent // if changing volume of current device, also change volume of current 2972bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent // device on aliased stream 2973bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent boolean currentDevice = (device == getDeviceForStream(mStreamType)); 2974a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent int numStreamTypes = AudioSystem.getNumStreamTypes(); 2975a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent for (int streamType = numStreamTypes - 1; streamType >= 0; streamType--) { 2976bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent if (streamType != mStreamType && 2977bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent mStreamVolumeAlias[streamType] == mStreamType) { 2978bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent int scaledIndex = rescaleIndex(index, mStreamType, streamType); 2979bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent mStreamStates[streamType].setIndex(scaledIndex, 298042b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent device); 2981bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent if (currentDevice) { 2982bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent mStreamStates[streamType].setIndex(scaledIndex, 298342b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent getDeviceForStream(streamType)); 2984bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent } 2985a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent } 2986a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent } 29879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 29889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 29899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 29909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 29919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 29929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 299342b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent public synchronized int getIndex(int device) { 299442b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent Integer index = mIndex.get(device); 29959bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent if (index == null) { 29969bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent // there is always an entry for AudioSystem.DEVICE_OUT_DEFAULT 299742b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent index = mIndex.get(AudioSystem.DEVICE_OUT_DEFAULT); 29989bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent } 29999bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent return index.intValue(); 30009bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent } 30019bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent 30029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int getMaxIndex() { 3003a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent return mIndexMax; 30049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 30059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 300642b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent public synchronized void setAllIndexes(VolumeStreamState srcStream) { 300724e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent int srcStreamType = srcStream.getStreamType(); 300824e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent // apply default device volume from source stream to all devices first in case 300924e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent // some devices are present in this stream state but not in source stream state 301024e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent int index = srcStream.getIndex(AudioSystem.DEVICE_OUT_DEFAULT); 301124e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent index = rescaleIndex(index, srcStreamType, mStreamType); 301224e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent Set set = mIndex.entrySet(); 30136d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent Iterator i = set.iterator(); 30146d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent while (i.hasNext()) { 30156d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent Map.Entry entry = (Map.Entry)i.next(); 301624e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent entry.setValue(index); 301724e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent } 301824e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent // Now apply actual volume for devices in source stream state 301924e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent set = srcStream.mIndex.entrySet(); 302024e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent i = set.iterator(); 302124e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent while (i.hasNext()) { 302224e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent Map.Entry entry = (Map.Entry)i.next(); 30236d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent int device = ((Integer)entry.getKey()).intValue(); 302424e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent index = ((Integer)entry.getValue()).intValue(); 302524e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent index = rescaleIndex(index, srcStreamType, mStreamType); 302633902db75011d863009585682bd08560c5b89a75Eric Laurent 302742b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent setIndex(index, device); 30286d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent } 30296d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent } 30306d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent 3031dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent public synchronized void setAllIndexesToMax() { 3032dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent Set set = mIndex.entrySet(); 3033dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent Iterator i = set.iterator(); 3034dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent while (i.hasNext()) { 3035dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent Map.Entry entry = (Map.Entry)i.next(); 3036dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent entry.setValue(mIndexMax); 3037dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent } 3038dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent } 3039dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent 30403172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent public synchronized void mute(IBinder cb, boolean state) { 30419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project VolumeDeathHandler handler = getDeathHandler(cb, state); 30429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (handler == null) { 30439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Log.e(TAG, "Could not get client death handler for stream: "+mStreamType); 30449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 30459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 30469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project handler.mute(state); 30479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 30489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 30496d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent public int getStreamType() { 30506d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent return mStreamType; 30516d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent } 30526d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent 30539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private int getValidIndex(int index) { 30549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (index < 0) { 30559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return 0; 305683a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent } else if (mUseFixedVolume || index > mIndexMax) { 3057a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent return mIndexMax; 30589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 30599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 30609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return index; 30619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 30629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 30639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private class VolumeDeathHandler implements IBinder.DeathRecipient { 30649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private IBinder mICallback; // To be notified of client's death 30659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private int mMuteCount; // Number of active mutes for this client 30669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 30679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project VolumeDeathHandler(IBinder cb) { 30689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mICallback = cb; 30699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 30709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 30713172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent // must be called while synchronized on parent VolumeStreamState 30729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void mute(boolean state) { 307342b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent boolean updateVolume = false; 30743172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent if (state) { 30753172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent if (mMuteCount == 0) { 30763172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent // Register for client death notification 30773172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent try { 30783172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent // mICallback can be 0 if muted by AudioService 30793172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent if (mICallback != null) { 30803172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent mICallback.linkToDeath(this, 0); 30813172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent } 308242b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent VolumeStreamState.this.mDeathHandlers.add(this); 30833172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent // If the stream is not yet muted by any client, set level to 0 308442b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent if (!VolumeStreamState.this.isMuted()) { 308542b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent updateVolume = true; 30863172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent } 30873172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent } catch (RemoteException e) { 30883172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent // Client has died! 30893172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent binderDied(); 30903172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent return; 30913172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent } 30923172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent } else { 30933172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent Log.w(TAG, "stream: "+mStreamType+" was already muted by this client"); 30943172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent } 30953172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent mMuteCount++; 30963172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent } else { 30973172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent if (mMuteCount == 0) { 30983172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent Log.e(TAG, "unexpected unmute for stream: "+mStreamType); 30993172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent } else { 31003172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent mMuteCount--; 31013172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent if (mMuteCount == 0) { 31023172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent // Unregister from client death notification 310342b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent VolumeStreamState.this.mDeathHandlers.remove(this); 31043172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent // mICallback can be 0 if muted by AudioService 31053172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent if (mICallback != null) { 31063172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent mICallback.unlinkToDeath(this, 0); 31073172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent } 310842b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent if (!VolumeStreamState.this.isMuted()) { 310942b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent updateVolume = true; 31109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 31119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 31129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 31139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 311442b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent if (updateVolume) { 311542b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent sendMsg(mAudioHandler, 311642b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent MSG_SET_ALL_VOLUMES, 311742b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent SENDMSG_QUEUE, 311842b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent 0, 311942b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent 0, 312042b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent VolumeStreamState.this, 0); 312142b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent } 31229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 31239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 31249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void binderDied() { 31259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Log.w(TAG, "Volume service client died for stream: "+mStreamType); 31269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mMuteCount != 0) { 31279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Reset all active mute requests from this client. 31289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mMuteCount = 1; 31299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mute(false); 31309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 31319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 31329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 31339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 31343172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent private synchronized int muteCount() { 31359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int count = 0; 31369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int size = mDeathHandlers.size(); 31379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = 0; i < size; i++) { 31389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project count += mDeathHandlers.get(i).mMuteCount; 31399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 31409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return count; 31419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 31429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 314342b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent private synchronized boolean isMuted() { 314442b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent return muteCount() != 0; 314542b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent } 314642b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent 31473172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent // only called by mute() which is already synchronized 31489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private VolumeDeathHandler getDeathHandler(IBinder cb, boolean state) { 31493172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent VolumeDeathHandler handler; 31503172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent int size = mDeathHandlers.size(); 31513172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent for (int i = 0; i < size; i++) { 31523172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent handler = mDeathHandlers.get(i); 31533172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent if (cb == handler.mICallback) { 31543172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent return handler; 3155ce952c8e13c535bedde77bcdb94dfcc7508475aaMike Lockwood } 3156ce952c8e13c535bedde77bcdb94dfcc7508475aaMike Lockwood } 31573172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent // If this is the first mute request for this client, create a new 31583172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent // client death handler. Otherwise, it is an out of sequence unmute request. 31593172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent if (state) { 31603172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent handler = new VolumeDeathHandler(cb); 31613172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent } else { 31623172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent Log.w(TAG, "stream was not muted by this client"); 31633172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent handler = null; 31643172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent } 31653172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent return handler; 3166ce952c8e13c535bedde77bcdb94dfcc7508475aaMike Lockwood } 3167bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent 3168bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent private void dump(PrintWriter pw) { 3169dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent pw.print(" Mute count: "); 3170dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent pw.println(muteCount()); 3171bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent pw.print(" Current: "); 3172bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent Set set = mIndex.entrySet(); 3173bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent Iterator i = set.iterator(); 3174bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent while (i.hasNext()) { 3175bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent Map.Entry entry = (Map.Entry)i.next(); 3176bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent pw.print(Integer.toHexString(((Integer)entry.getKey()).intValue()) 3177bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent + ": " + ((((Integer)entry.getValue()).intValue() + 5) / 10)+", "); 3178bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent } 3179bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent } 3180ce952c8e13c535bedde77bcdb94dfcc7508475aaMike Lockwood } 3181ce952c8e13c535bedde77bcdb94dfcc7508475aaMike Lockwood 31829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** Thread that handles native AudioSystem control. */ 31839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private class AudioSystemThread extends Thread { 31849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project AudioSystemThread() { 31859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project super("AudioService"); 31869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 31879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 31889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 31899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void run() { 31909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Set this thread up so the handler will work on it 31919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Looper.prepare(); 31929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 31939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project synchronized(AudioService.this) { 31949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mAudioHandler = new AudioHandler(); 31959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 31969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Notify that the handler has been created 31979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project AudioService.this.notify(); 31989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 31999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 32009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Listen for volume change requests that are set by VolumePanel 32019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Looper.loop(); 32029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 32039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 32049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 32059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** Handles internal volume messages in separate volume thread. */ 32069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private class AudioHandler extends Handler { 32079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 32089bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent private void setDeviceVolume(VolumeStreamState streamState, int device) { 32099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 32109bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent // Apply volume 32119bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent streamState.applyDeviceVolume(device); 3212a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent 3213a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent // Apply change to all streams using this one as alias 3214a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent int numStreamTypes = AudioSystem.getNumStreamTypes(); 3215a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent for (int streamType = numStreamTypes - 1; streamType >= 0; streamType--) { 3216a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent if (streamType != streamState.mStreamType && 32176d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent mStreamVolumeAlias[streamType] == streamState.mStreamType) { 32186d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent mStreamStates[streamType].applyDeviceVolume(getDeviceForStream(streamType)); 3219a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent } 3220a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent } 32219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 32229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Post a persist volume msg 3223afbb047c3945e9c2b7e9bc6b25098d5fb80bba4eEric Laurent sendMsg(mAudioHandler, 3224afbb047c3945e9c2b7e9bc6b25098d5fb80bba4eEric Laurent MSG_PERSIST_VOLUME, 322598ad9b9d6fd34aad487933170f50b5519313df61Eric Laurent SENDMSG_QUEUE, 32269bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent device, 322742b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent 0, 3228afbb047c3945e9c2b7e9bc6b25098d5fb80bba4eEric Laurent streamState, 3229afbb047c3945e9c2b7e9bc6b25098d5fb80bba4eEric Laurent PERSIST_DELAY); 3230afbb047c3945e9c2b7e9bc6b25098d5fb80bba4eEric Laurent 32319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 32329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 32339bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent private void setAllVolumes(VolumeStreamState streamState) { 32349bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent 32359bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent // Apply volume 32369bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent streamState.applyAllVolumes(); 32379bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent 32389bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent // Apply change to all streams using this one as alias 32399bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent int numStreamTypes = AudioSystem.getNumStreamTypes(); 32409bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent for (int streamType = numStreamTypes - 1; streamType >= 0; streamType--) { 32419bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent if (streamType != streamState.mStreamType && 32426d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent mStreamVolumeAlias[streamType] == streamState.mStreamType) { 32439bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent mStreamStates[streamType].applyAllVolumes(); 32449bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent } 32459bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent } 32469bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent } 32479bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent 324842b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent private void persistVolume(VolumeStreamState streamState, int device) { 324983a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent if (mUseFixedVolume) { 325083a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent return; 325183a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent } 325242b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent System.putIntForUser(mContentResolver, 325342b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent streamState.getSettingNameForDevice(device), 325442b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent (streamState.getIndex(device) + 5)/ 10, 325542b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent UserHandle.USER_CURRENT); 32569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 32579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3258ba195ebc76f23b6679443724ab58c9dc9f2df884Glenn Kasten private void persistRingerMode(int ringerMode) { 325983a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent if (mUseFixedVolume) { 326083a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent return; 326183a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent } 32628d9a1f66d9d3dbbd45a56d441a746ec11dba7645Jeff Sharkey Settings.Global.putInt(mContentResolver, Settings.Global.MODE_RINGER, ringerMode); 32639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 32649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 32655d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent private boolean onLoadSoundEffects() { 32665d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent int status; 32675d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent 32685d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent synchronized (mSoundEffectsLock) { 32695d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent if (!mBootCompleted) { 32705d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent Log.w(TAG, "onLoadSoundEffects() called before boot complete"); 32715d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent return false; 32725d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent } 32735d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent 32745d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent if (mSoundPool != null) { 32755d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent return true; 32765d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent } 32775d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent 32785d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent loadTouchSoundAssets(); 32795d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent 32805d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent mSoundPool = new SoundPool(NUM_SOUNDPOOL_CHANNELS, AudioSystem.STREAM_SYSTEM, 0); 32815d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent mSoundPoolCallBack = null; 32825d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent mSoundPoolListenerThread = new SoundPoolListenerThread(); 32835d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent mSoundPoolListenerThread.start(); 32845d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent int attempts = 3; 32855d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent while ((mSoundPoolCallBack == null) && (attempts-- > 0)) { 32865d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent try { 32875d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent // Wait for mSoundPoolCallBack to be set by the other thread 32885d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent mSoundEffectsLock.wait(SOUND_EFECTS_LOAD_TIMEOUT_MS); 32895d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent } catch (InterruptedException e) { 32905d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent Log.w(TAG, "Interrupted while waiting sound pool listener thread."); 32915d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent } 32925d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent } 32935d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent 32945d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent if (mSoundPoolCallBack == null) { 32955d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent Log.w(TAG, "onLoadSoundEffects() SoundPool listener or thread creation error"); 32965d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent if (mSoundPoolLooper != null) { 32975d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent mSoundPoolLooper.quit(); 32985d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent mSoundPoolLooper = null; 32995d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent } 33005d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent mSoundPoolListenerThread = null; 33015d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent mSoundPool.release(); 33025d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent mSoundPool = null; 33035d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent return false; 33045d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent } 33055d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent /* 33065d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent * poolId table: The value -1 in this table indicates that corresponding 33075d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent * file (same index in SOUND_EFFECT_FILES[] has not been loaded. 33085d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent * Once loaded, the value in poolId is the sample ID and the same 33095d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent * sample can be reused for another effect using the same file. 33105d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent */ 33115d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent int[] poolId = new int[SOUND_EFFECT_FILES.size()]; 33125d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent for (int fileIdx = 0; fileIdx < SOUND_EFFECT_FILES.size(); fileIdx++) { 33135d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent poolId[fileIdx] = -1; 33145d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent } 33155d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent /* 33165d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent * Effects whose value in SOUND_EFFECT_FILES_MAP[effect][1] is -1 must be loaded. 33175d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent * If load succeeds, value in SOUND_EFFECT_FILES_MAP[effect][1] is > 0: 33185d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent * this indicates we have a valid sample loaded for this effect. 33195d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent */ 33205d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent 33215d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent int numSamples = 0; 33225d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent for (int effect = 0; effect < AudioManager.NUM_SOUND_EFFECTS; effect++) { 33235d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent // Do not load sample if this effect uses the MediaPlayer 33245d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent if (SOUND_EFFECT_FILES_MAP[effect][1] == 0) { 33255d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent continue; 33265d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent } 33275d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent if (poolId[SOUND_EFFECT_FILES_MAP[effect][0]] == -1) { 33285d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent String filePath = Environment.getRootDirectory() 33295d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent + SOUND_EFFECTS_PATH 33305d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent + SOUND_EFFECT_FILES.get(SOUND_EFFECT_FILES_MAP[effect][0]); 33315d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent int sampleId = mSoundPool.load(filePath, 0); 33325d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent if (sampleId <= 0) { 33335d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent Log.w(TAG, "Soundpool could not load file: "+filePath); 33345d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent } else { 33355d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent SOUND_EFFECT_FILES_MAP[effect][1] = sampleId; 33365d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent poolId[SOUND_EFFECT_FILES_MAP[effect][0]] = sampleId; 33375d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent numSamples++; 33385d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent } 33395d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent } else { 33405d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent SOUND_EFFECT_FILES_MAP[effect][1] = 33415d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent poolId[SOUND_EFFECT_FILES_MAP[effect][0]]; 33425d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent } 33435d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent } 33445d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent // wait for all samples to be loaded 33455d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent if (numSamples > 0) { 33465d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent mSoundPoolCallBack.setSamples(poolId); 33475d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent 33485d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent attempts = 3; 33495d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent status = 1; 33505d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent while ((status == 1) && (attempts-- > 0)) { 33515d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent try { 33525d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent mSoundEffectsLock.wait(SOUND_EFECTS_LOAD_TIMEOUT_MS); 33535d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent status = mSoundPoolCallBack.status(); 33545d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent } catch (InterruptedException e) { 33555d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent Log.w(TAG, "Interrupted while waiting sound pool callback."); 33565d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent } 33575d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent } 33585d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent } else { 33595d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent status = -1; 33605d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent } 33615d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent 33625d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent if (mSoundPoolLooper != null) { 33635d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent mSoundPoolLooper.quit(); 33645d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent mSoundPoolLooper = null; 33655d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent } 33665d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent mSoundPoolListenerThread = null; 33675d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent if (status != 0) { 33685d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent Log.w(TAG, 33695d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent "onLoadSoundEffects(), Error "+status+ " while loading samples"); 33705d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent for (int effect = 0; effect < AudioManager.NUM_SOUND_EFFECTS; effect++) { 33715d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent if (SOUND_EFFECT_FILES_MAP[effect][1] > 0) { 33725d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent SOUND_EFFECT_FILES_MAP[effect][1] = -1; 33735d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent } 33745d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent } 33755d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent 33765d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent mSoundPool.release(); 33775d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent mSoundPool = null; 33785d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent } 33795d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent } 33805d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent return (status == 0); 33815d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent } 33825d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent 33835d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent /** 33845d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent * Unloads samples from the sound pool. 33855d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent * This method can be called to free some memory when 33865d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent * sound effects are disabled. 33875d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent */ 33885d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent private void onUnloadSoundEffects() { 33895d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent synchronized (mSoundEffectsLock) { 33905d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent if (mSoundPool == null) { 33915d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent return; 33925d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent } 33935d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent 33945d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent int[] poolId = new int[SOUND_EFFECT_FILES.size()]; 33955d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent for (int fileIdx = 0; fileIdx < SOUND_EFFECT_FILES.size(); fileIdx++) { 33965d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent poolId[fileIdx] = 0; 33975d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent } 33985d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent 33995d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent for (int effect = 0; effect < AudioManager.NUM_SOUND_EFFECTS; effect++) { 34005d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent if (SOUND_EFFECT_FILES_MAP[effect][1] <= 0) { 34015d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent continue; 34025d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent } 34035d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent if (poolId[SOUND_EFFECT_FILES_MAP[effect][0]] == 0) { 34045d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent mSoundPool.unload(SOUND_EFFECT_FILES_MAP[effect][1]); 34055d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent SOUND_EFFECT_FILES_MAP[effect][1] = -1; 34065d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent poolId[SOUND_EFFECT_FILES_MAP[effect][0]] = -1; 34075d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent } 34085d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent } 34095d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent mSoundPool.release(); 34105d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent mSoundPool = null; 34115d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent } 34125d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent } 34135d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent 34145d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent private void onPlaySoundEffect(int effectType, int volume) { 34159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project synchronized (mSoundEffectsLock) { 34165d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent 34175d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent onLoadSoundEffects(); 34185d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent 34199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mSoundPool == null) { 34209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 34219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3422a2ef57dba9ac77d8eccacd646b2b8a8d99fe9d8bEric Laurent float volFloat; 342325101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent // use default if volume is not specified by caller 3424a2ef57dba9ac77d8eccacd646b2b8a8d99fe9d8bEric Laurent if (volume < 0) { 3425f2b0c11f4e797e183131261724d8de310dac5431Jean-Michel Trivi volFloat = (float)Math.pow(10, (float)sSoundEffectVolumeDb/20); 3426a2ef57dba9ac77d8eccacd646b2b8a8d99fe9d8bEric Laurent } else { 3427a2ef57dba9ac77d8eccacd646b2b8a8d99fe9d8bEric Laurent volFloat = (float) volume / 1000.0f; 3428a2ef57dba9ac77d8eccacd646b2b8a8d99fe9d8bEric Laurent } 34299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 34309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (SOUND_EFFECT_FILES_MAP[effectType][1] > 0) { 34315d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent mSoundPool.play(SOUND_EFFECT_FILES_MAP[effectType][1], 34325d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent volFloat, volFloat, 0, 0, 1.0f); 34339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 34349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project MediaPlayer mediaPlayer = new MediaPlayer(); 343562b9aec7a0a4e1cf8cfec7e39ea3103ab510d72eGlenn Kasten try { 3436e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent String filePath = Environment.getRootDirectory() + SOUND_EFFECTS_PATH + 3437e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent SOUND_EFFECT_FILES.get(SOUND_EFFECT_FILES_MAP[effectType][0]); 343862b9aec7a0a4e1cf8cfec7e39ea3103ab510d72eGlenn Kasten mediaPlayer.setDataSource(filePath); 343962b9aec7a0a4e1cf8cfec7e39ea3103ab510d72eGlenn Kasten mediaPlayer.setAudioStreamType(AudioSystem.STREAM_SYSTEM); 344062b9aec7a0a4e1cf8cfec7e39ea3103ab510d72eGlenn Kasten mediaPlayer.prepare(); 3441068225de0197df07a0247b2877666ea91c22c992Glenn Kasten mediaPlayer.setVolume(volFloat); 344262b9aec7a0a4e1cf8cfec7e39ea3103ab510d72eGlenn Kasten mediaPlayer.setOnCompletionListener(new OnCompletionListener() { 344362b9aec7a0a4e1cf8cfec7e39ea3103ab510d72eGlenn Kasten public void onCompletion(MediaPlayer mp) { 344462b9aec7a0a4e1cf8cfec7e39ea3103ab510d72eGlenn Kasten cleanupPlayer(mp); 344562b9aec7a0a4e1cf8cfec7e39ea3103ab510d72eGlenn Kasten } 344662b9aec7a0a4e1cf8cfec7e39ea3103ab510d72eGlenn Kasten }); 344762b9aec7a0a4e1cf8cfec7e39ea3103ab510d72eGlenn Kasten mediaPlayer.setOnErrorListener(new OnErrorListener() { 344862b9aec7a0a4e1cf8cfec7e39ea3103ab510d72eGlenn Kasten public boolean onError(MediaPlayer mp, int what, int extra) { 344962b9aec7a0a4e1cf8cfec7e39ea3103ab510d72eGlenn Kasten cleanupPlayer(mp); 345062b9aec7a0a4e1cf8cfec7e39ea3103ab510d72eGlenn Kasten return true; 345162b9aec7a0a4e1cf8cfec7e39ea3103ab510d72eGlenn Kasten } 345262b9aec7a0a4e1cf8cfec7e39ea3103ab510d72eGlenn Kasten }); 345362b9aec7a0a4e1cf8cfec7e39ea3103ab510d72eGlenn Kasten mediaPlayer.start(); 345462b9aec7a0a4e1cf8cfec7e39ea3103ab510d72eGlenn Kasten } catch (IOException ex) { 345562b9aec7a0a4e1cf8cfec7e39ea3103ab510d72eGlenn Kasten Log.w(TAG, "MediaPlayer IOException: "+ex); 345662b9aec7a0a4e1cf8cfec7e39ea3103ab510d72eGlenn Kasten } catch (IllegalArgumentException ex) { 345762b9aec7a0a4e1cf8cfec7e39ea3103ab510d72eGlenn Kasten Log.w(TAG, "MediaPlayer IllegalArgumentException: "+ex); 345862b9aec7a0a4e1cf8cfec7e39ea3103ab510d72eGlenn Kasten } catch (IllegalStateException ex) { 345962b9aec7a0a4e1cf8cfec7e39ea3103ab510d72eGlenn Kasten Log.w(TAG, "MediaPlayer IllegalStateException: "+ex); 34609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 34619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 34629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 34639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 34649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 34659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private void cleanupPlayer(MediaPlayer mp) { 34669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mp != null) { 34679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 34689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mp.stop(); 34699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mp.release(); 34709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } catch (IllegalStateException ex) { 34719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Log.w(TAG, "MediaPlayer IllegalStateException: "+ex); 34729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 34739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 34749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 34759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3476fa640154f1f42121d81242b2f1a10f03e52f0014Eric Laurent private void setForceUse(int usage, int config) { 3477fa640154f1f42121d81242b2f1a10f03e52f0014Eric Laurent AudioSystem.setForceUse(usage, config); 3478fa640154f1f42121d81242b2f1a10f03e52f0014Eric Laurent } 3479fa640154f1f42121d81242b2f1a10f03e52f0014Eric Laurent 348005274f348e12983eb8613cc6eb9ae561e8197e28Eric Laurent private void onPersistSafeVolumeState(int state) { 348105274f348e12983eb8613cc6eb9ae561e8197e28Eric Laurent Settings.Global.putInt(mContentResolver, 348205274f348e12983eb8613cc6eb9ae561e8197e28Eric Laurent Settings.Global.AUDIO_SAFE_VOLUME_STATE, 348305274f348e12983eb8613cc6eb9ae561e8197e28Eric Laurent state); 348405274f348e12983eb8613cc6eb9ae561e8197e28Eric Laurent } 348505274f348e12983eb8613cc6eb9ae561e8197e28Eric Laurent 34869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 34879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void handleMessage(Message msg) { 34889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3489afbb047c3945e9c2b7e9bc6b25098d5fb80bba4eEric Laurent switch (msg.what) { 34909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 34919bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent case MSG_SET_DEVICE_VOLUME: 34929bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent setDeviceVolume((VolumeStreamState) msg.obj, msg.arg1); 34939bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent break; 34949bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent 34959bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent case MSG_SET_ALL_VOLUMES: 34969bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent setAllVolumes((VolumeStreamState) msg.obj); 34979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 34989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 34999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case MSG_PERSIST_VOLUME: 350042b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent persistVolume((VolumeStreamState) msg.obj, msg.arg1); 35019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 35029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 35035c55a051ad7d86a464fb91426f1ea3c0250e38b3Mike Lockwood case MSG_PERSIST_MASTER_VOLUME: 350483a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent if (mUseFixedVolume) { 350583a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent return; 350683a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent } 3507bc0fab1fc2db832ef86d8a33466ec4d68b103ca0Eric Laurent Settings.System.putFloatForUser(mContentResolver, 3508bc0fab1fc2db832ef86d8a33466ec4d68b103ca0Eric Laurent Settings.System.VOLUME_MASTER, 3509bc0fab1fc2db832ef86d8a33466ec4d68b103ca0Eric Laurent (float)msg.arg1 / (float)1000.0, 3510bc0fab1fc2db832ef86d8a33466ec4d68b103ca0Eric Laurent UserHandle.USER_CURRENT); 35115c55a051ad7d86a464fb91426f1ea3c0250e38b3Mike Lockwood break; 35125c55a051ad7d86a464fb91426f1ea3c0250e38b3Mike Lockwood 351357978ed86286a33d5b1a0fd000ca3406ba9d87b3Justin Koh case MSG_PERSIST_MASTER_VOLUME_MUTE: 351483a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent if (mUseFixedVolume) { 351583a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent return; 351683a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent } 3517bc0fab1fc2db832ef86d8a33466ec4d68b103ca0Eric Laurent Settings.System.putIntForUser(mContentResolver, 3518bc0fab1fc2db832ef86d8a33466ec4d68b103ca0Eric Laurent Settings.System.VOLUME_MASTER_MUTE, 3519bc0fab1fc2db832ef86d8a33466ec4d68b103ca0Eric Laurent msg.arg1, 3520bc0fab1fc2db832ef86d8a33466ec4d68b103ca0Eric Laurent UserHandle.USER_CURRENT); 352157978ed86286a33d5b1a0fd000ca3406ba9d87b3Justin Koh break; 352257978ed86286a33d5b1a0fd000ca3406ba9d87b3Justin Koh 35239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case MSG_PERSIST_RINGER_MODE: 3524ba195ebc76f23b6679443724ab58c9dc9f2df884Glenn Kasten // note that the value persisted is the current ringer mode, not the 3525ba195ebc76f23b6679443724ab58c9dc9f2df884Glenn Kasten // value of ringer mode as of the time the request was made to persist 3526ba195ebc76f23b6679443724ab58c9dc9f2df884Glenn Kasten persistRingerMode(getRingerMode()); 35279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 35289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 35299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case MSG_MEDIA_SERVER_DIED: 3530dfb881f96af7898151940a4bbc52e45e6043d38bEric Laurent if (AudioSystem.checkAudioFlinger() != AudioSystem.AUDIO_STATUS_OK) { 353189e74ba1419732dd5c7f939e48d4aa7989fd3a51Eric Laurent Log.e(TAG, "Media server died."); 3532afbb047c3945e9c2b7e9bc6b25098d5fb80bba4eEric Laurent sendMsg(mAudioHandler, MSG_MEDIA_SERVER_DIED, SENDMSG_NOOP, 0, 0, 353389e74ba1419732dd5c7f939e48d4aa7989fd3a51Eric Laurent null, 500); 3534dfb881f96af7898151940a4bbc52e45e6043d38bEric Laurent break; 353589e74ba1419732dd5c7f939e48d4aa7989fd3a51Eric Laurent } 35369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Log.e(TAG, "Media server started."); 3537dfb881f96af7898151940a4bbc52e45e6043d38bEric Laurent 35383c652ca5a546e7227a5f4bdbf0f81552b2c91383Eric Laurent // indicate to audio HAL that we start the reconfiguration phase after a media 35393c652ca5a546e7227a5f4bdbf0f81552b2c91383Eric Laurent // server crash 3540dfb881f96af7898151940a4bbc52e45e6043d38bEric Laurent // Note that we only execute this when the media server 35413c652ca5a546e7227a5f4bdbf0f81552b2c91383Eric Laurent // process restarts after a crash, not the first time it is started. 35423c652ca5a546e7227a5f4bdbf0f81552b2c91383Eric Laurent AudioSystem.setParameters("restarting=true"); 35433c652ca5a546e7227a5f4bdbf0f81552b2c91383Eric Laurent 3544fd116ad1ab02f6060a0b2201f018317fa32e28b4Glenn Kasten readAndSetLowRamDevice(); 3545fd116ad1ab02f6060a0b2201f018317fa32e28b4Glenn Kasten 3546c42ac9d4d03f62c3a1ba197a28a81fda44bd8b7fEric Laurent // Restore device connection states 35476bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent synchronized (mConnectedDevices) { 35486bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent Set set = mConnectedDevices.entrySet(); 35496bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent Iterator i = set.iterator(); 35509bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent while (i.hasNext()) { 35516bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent Map.Entry device = (Map.Entry)i.next(); 35526bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent AudioSystem.setDeviceConnectionState( 35536bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent ((Integer)device.getKey()).intValue(), 35546bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent AudioSystem.DEVICE_STATE_AVAILABLE, 35556bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent (String)device.getValue()); 35566bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent } 3557c42ac9d4d03f62c3a1ba197a28a81fda44bd8b7fEric Laurent } 3558c42ac9d4d03f62c3a1ba197a28a81fda44bd8b7fEric Laurent // Restore call state 3559c42ac9d4d03f62c3a1ba197a28a81fda44bd8b7fEric Laurent AudioSystem.setPhoneState(mMode); 3560c42ac9d4d03f62c3a1ba197a28a81fda44bd8b7fEric Laurent 3561d5603c126acdd94d9f7400bb1d04188020a425b4Eric Laurent // Restore forced usage for communcations and record 3562c42ac9d4d03f62c3a1ba197a28a81fda44bd8b7fEric Laurent AudioSystem.setForceUse(AudioSystem.FOR_COMMUNICATION, mForcedUseForComm); 3563d5603c126acdd94d9f7400bb1d04188020a425b4Eric Laurent AudioSystem.setForceUse(AudioSystem.FOR_RECORD, mForcedUseForComm); 3564dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent AudioSystem.setForceUse(AudioSystem.FOR_SYSTEM, mCameraSoundForced ? 3565dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent AudioSystem.FORCE_SYSTEM_ENFORCED : AudioSystem.FORCE_NONE); 3566c42ac9d4d03f62c3a1ba197a28a81fda44bd8b7fEric Laurent 3567a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent // Restore stream volumes 35689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int numStreamTypes = AudioSystem.getNumStreamTypes(); 35699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int streamType = numStreamTypes - 1; streamType >= 0; streamType--) { 35709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project VolumeStreamState streamState = mStreamStates[streamType]; 3571c42ac9d4d03f62c3a1ba197a28a81fda44bd8b7fEric Laurent AudioSystem.initStreamVolume(streamType, 0, (streamState.mIndexMax + 5) / 10); 35729bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent 35739bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent streamState.applyAllVolumes(); 35749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3575c42ac9d4d03f62c3a1ba197a28a81fda44bd8b7fEric Laurent 3576c42ac9d4d03f62c3a1ba197a28a81fda44bd8b7fEric Laurent // Restore ringer mode 3577c42ac9d4d03f62c3a1ba197a28a81fda44bd8b7fEric Laurent setRingerModeInt(getRingerMode(), false); 35783c652ca5a546e7227a5f4bdbf0f81552b2c91383Eric Laurent 35799063154a793b0ab38b3c5992cbaed046427b4a82Mike Lockwood // Restore master volume 35809063154a793b0ab38b3c5992cbaed046427b4a82Mike Lockwood restoreMasterVolume(); 35819063154a793b0ab38b3c5992cbaed046427b4a82Mike Lockwood 3582f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi // Reset device orientation (if monitored for this device) 3583d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent if (mMonitorOrientation) { 3584f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi setOrientationForAudioSystem(); 3585f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi } 3586bb6f8711a7f804d39c45218db2d6339940cc5d35Jean-Michel Trivi if (mMonitorRotation) { 3587bb6f8711a7f804d39c45218db2d6339940cc5d35Jean-Michel Trivi setRotationForAudioSystem(); 3588bb6f8711a7f804d39c45218db2d6339940cc5d35Jean-Michel Trivi } 3589f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi 35907847211fb4699bf6018e29d214a918ed6657319bEric Laurent synchronized (mBluetoothA2dpEnabledLock) { 35917847211fb4699bf6018e29d214a918ed6657319bEric Laurent AudioSystem.setForceUse(AudioSystem.FOR_MEDIA, 35927847211fb4699bf6018e29d214a918ed6657319bEric Laurent mBluetoothA2dpEnabled ? 35937847211fb4699bf6018e29d214a918ed6657319bEric Laurent AudioSystem.FORCE_NONE : AudioSystem.FORCE_NO_BT_A2DP); 35947847211fb4699bf6018e29d214a918ed6657319bEric Laurent } 3595bff5ca576ef55bfdd51a0d2ff39f4bac614fa728Eric Laurent 3596bff5ca576ef55bfdd51a0d2ff39f4bac614fa728Eric Laurent synchronized (mSettingsLock) { 3597bff5ca576ef55bfdd51a0d2ff39f4bac614fa728Eric Laurent AudioSystem.setForceUse(AudioSystem.FOR_DOCK, 3598bff5ca576ef55bfdd51a0d2ff39f4bac614fa728Eric Laurent mDockAudioMediaEnabled ? 3599bff5ca576ef55bfdd51a0d2ff39f4bac614fa728Eric Laurent AudioSystem.FORCE_ANALOG_DOCK : AudioSystem.FORCE_NONE); 3600bff5ca576ef55bfdd51a0d2ff39f4bac614fa728Eric Laurent } 3601bff5ca576ef55bfdd51a0d2ff39f4bac614fa728Eric Laurent 36023c652ca5a546e7227a5f4bdbf0f81552b2c91383Eric Laurent // indicate the end of reconfiguration phase to audio HAL 36033c652ca5a546e7227a5f4bdbf0f81552b2c91383Eric Laurent AudioSystem.setParameters("restarting=false"); 36049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 36059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 36065d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent case MSG_UNLOAD_SOUND_EFFECTS: 36075d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent onUnloadSoundEffects(); 36085d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent break; 36095d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent 3610117b7bb5b5a4457711f59bde3dcc83d8f111c524Eric Laurent case MSG_LOAD_SOUND_EFFECTS: 36115d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent //FIXME: onLoadSoundEffects() should be executed in a separate thread as it 36125d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent // can take several dozens of milliseconds to complete 36135d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent boolean loaded = onLoadSoundEffects(); 36145d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent if (msg.obj != null) { 36155d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent LoadSoundEffectReply reply = (LoadSoundEffectReply)msg.obj; 36165d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent synchronized (reply) { 36175d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent reply.mStatus = loaded ? 0 : -1; 36185d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent reply.notify(); 36195d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent } 36205d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent } 3621117b7bb5b5a4457711f59bde3dcc83d8f111c524Eric Laurent break; 3622117b7bb5b5a4457711f59bde3dcc83d8f111c524Eric Laurent 36239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case MSG_PLAY_SOUND_EFFECT: 36245d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent onPlaySoundEffect(msg.arg1, msg.arg2); 36259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 36264c637b9e34f4c8db69a64ad21a4e2bcfa7485b5fJean-Michel Trivi 36274c637b9e34f4c8db69a64ad21a4e2bcfa7485b5fJean-Michel Trivi case MSG_BTA2DP_DOCK_TIMEOUT: 36284c637b9e34f4c8db69a64ad21a4e2bcfa7485b5fJean-Michel Trivi // msg.obj == address of BTA2DP device 36296bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent synchronized (mConnectedDevices) { 36306bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent makeA2dpDeviceUnavailableNow( (String) msg.obj ); 36316bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent } 36324c637b9e34f4c8db69a64ad21a4e2bcfa7485b5fJean-Michel Trivi break; 3633fa640154f1f42121d81242b2f1a10f03e52f0014Eric Laurent 3634fa640154f1f42121d81242b2f1a10f03e52f0014Eric Laurent case MSG_SET_FORCE_USE: 3635c390bed06b4a572e273ead1254da9a932e04dce3Eric Laurent case MSG_SET_FORCE_BT_A2DP_USE: 3636fa640154f1f42121d81242b2f1a10f03e52f0014Eric Laurent setForceUse(msg.arg1, msg.arg2); 3637fa640154f1f42121d81242b2f1a10f03e52f0014Eric Laurent break; 3638d589fea865e90859324f00d21765fa7d7759e465Jean-Michel Trivi 3639dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent case MSG_BT_HEADSET_CNCT_FAILED: 3640dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent resetBluetoothSco(); 3641dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent break; 3642b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent 3643b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent case MSG_SET_WIRED_DEVICE_CONNECTION_STATE: 3644b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent onSetWiredDeviceConnectionState(msg.arg1, msg.arg2, (String)msg.obj); 3645fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi mAudioEventWakeLock.release(); 3646b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent break; 3647b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent 3648b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent case MSG_SET_A2DP_CONNECTION_STATE: 3649b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent onSetA2dpConnectionState((BluetoothDevice)msg.obj, msg.arg1); 3650fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi mAudioEventWakeLock.release(); 3651b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent break; 3652632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn 3653632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn case MSG_REPORT_NEW_ROUTES: { 3654632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn int N = mRoutesObservers.beginBroadcast(); 3655632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn if (N > 0) { 3656632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn AudioRoutesInfo routes; 3657632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn synchronized (mCurAudioRoutes) { 3658632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn routes = new AudioRoutesInfo(mCurAudioRoutes); 3659632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn } 3660632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn while (N > 0) { 3661632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn N--; 3662632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn IAudioRoutesObserver obs = mRoutesObservers.getBroadcastItem(N); 3663632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn try { 3664632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn obs.dispatchAudioRoutesChanged(routes); 3665632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn } catch (RemoteException e) { 3666632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn } 3667632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn } 3668632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn } 3669632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn mRoutesObservers.finishBroadcast(); 3670632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn break; 3671632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn } 36723114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi 3673c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent case MSG_CHECK_MUSIC_ACTIVE: 3674c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent onCheckMusicActive(); 3675c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent break; 36765bfaeaef3fc348d66f48b86be08655e91dff910aEric Laurent 36775bfaeaef3fc348d66f48b86be08655e91dff910aEric Laurent case MSG_BROADCAST_AUDIO_BECOMING_NOISY: 36785bfaeaef3fc348d66f48b86be08655e91dff910aEric Laurent onSendBecomingNoisyIntent(); 36795bfaeaef3fc348d66f48b86be08655e91dff910aEric Laurent break; 3680d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent 3681d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent case MSG_CONFIGURE_SAFE_MEDIA_VOLUME_FORCED: 3682d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent case MSG_CONFIGURE_SAFE_MEDIA_VOLUME: 3683d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent onConfigureSafeVolume((msg.what == MSG_CONFIGURE_SAFE_MEDIA_VOLUME_FORCED)); 3684d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent break; 368505274f348e12983eb8613cc6eb9ae561e8197e28Eric Laurent case MSG_PERSIST_SAFE_VOLUME_STATE: 368605274f348e12983eb8613cc6eb9ae561e8197e28Eric Laurent onPersistSafeVolumeState(msg.arg1); 368705274f348e12983eb8613cc6eb9ae561e8197e28Eric Laurent break; 3688a578c48e6c8677bcb54340aadb9470f8a275e56cJean-Michel Trivi 36892a57ca931fefe817b6110101289721acaacfc808Eric Laurent case MSG_BROADCAST_BT_CONNECTION_STATE: 36902a57ca931fefe817b6110101289721acaacfc808Eric Laurent onBroadcastScoConnectionState(msg.arg1); 36912a57ca931fefe817b6110101289721acaacfc808Eric Laurent break; 36929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 36939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 36949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 36959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3696b109615ebebd6f3b9ae789412279f576c3ace46bJason Parekh private class SettingsObserver extends ContentObserver { 3697a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent 3698b109615ebebd6f3b9ae789412279f576c3ace46bJason Parekh SettingsObserver() { 3699b109615ebebd6f3b9ae789412279f576c3ace46bJason Parekh super(new Handler()); 3700b109615ebebd6f3b9ae789412279f576c3ace46bJason Parekh mContentResolver.registerContentObserver(Settings.System.getUriFor( 3701b109615ebebd6f3b9ae789412279f576c3ace46bJason Parekh Settings.System.MODE_RINGER_STREAMS_AFFECTED), false, this); 37027ee1e4ff7346a278a6722108fbc1869240b3e866Eric Laurent mContentResolver.registerContentObserver(Settings.Global.getUriFor( 37037ee1e4ff7346a278a6722108fbc1869240b3e866Eric Laurent Settings.Global.DOCK_AUDIO_MEDIA_ENABLED), false, this); 3704b109615ebebd6f3b9ae789412279f576c3ace46bJason Parekh } 3705b109615ebebd6f3b9ae789412279f576c3ace46bJason Parekh 3706b109615ebebd6f3b9ae789412279f576c3ace46bJason Parekh @Override 3707b109615ebebd6f3b9ae789412279f576c3ace46bJason Parekh public void onChange(boolean selfChange) { 3708b109615ebebd6f3b9ae789412279f576c3ace46bJason Parekh super.onChange(selfChange); 3709ba195ebc76f23b6679443724ab58c9dc9f2df884Glenn Kasten // FIXME This synchronized is not necessary if mSettingsLock only protects mRingerMode. 3710ba195ebc76f23b6679443724ab58c9dc9f2df884Glenn Kasten // However there appear to be some missing locks around mRingerModeMutedStreams 3711ba195ebc76f23b6679443724ab58c9dc9f2df884Glenn Kasten // and mRingerModeAffectedStreams, so will leave this synchronized for now. 3712ba195ebc76f23b6679443724ab58c9dc9f2df884Glenn Kasten // mRingerModeMutedStreams and mMuteAffectedStreams are safe (only accessed once). 3713a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent synchronized (mSettingsLock) { 371424e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent if (updateRingerModeAffectedStreams()) { 3715a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent /* 3716a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent * Ensure all stream types that should be affected by ringer mode 3717a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent * are in the proper state. 3718a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent */ 3719a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent setRingerModeInt(getRingerMode(), false); 3720a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent } 37217ee1e4ff7346a278a6722108fbc1869240b3e866Eric Laurent readDockAudioSettings(mContentResolver); 3722a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent } 3723b109615ebebd6f3b9ae789412279f576c3ace46bJason Parekh } 3724b109615ebebd6f3b9ae789412279f576c3ace46bJason Parekh } 3725a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent 37266bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent // must be called synchronized on mConnectedDevices 37274c637b9e34f4c8db69a64ad21a4e2bcfa7485b5fJean-Michel Trivi private void makeA2dpDeviceAvailable(String address) { 37287847211fb4699bf6018e29d214a918ed6657319bEric Laurent // enable A2DP before notifying A2DP connection to avoid unecessary processing in 37297847211fb4699bf6018e29d214a918ed6657319bEric Laurent // audio policy manager 3730c9d1d5f35091226e96fcfa91817480f589eb36e2Matthew Xie VolumeStreamState streamState = mStreamStates[AudioSystem.STREAM_MUSIC]; 3731c9d1d5f35091226e96fcfa91817480f589eb36e2Matthew Xie sendMsg(mAudioHandler, MSG_SET_DEVICE_VOLUME, SENDMSG_QUEUE, 3732c9d1d5f35091226e96fcfa91817480f589eb36e2Matthew Xie AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, 0, streamState, 0); 37337847211fb4699bf6018e29d214a918ed6657319bEric Laurent setBluetoothA2dpOnInt(true); 37344c637b9e34f4c8db69a64ad21a4e2bcfa7485b5fJean-Michel Trivi AudioSystem.setDeviceConnectionState(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, 37354c637b9e34f4c8db69a64ad21a4e2bcfa7485b5fJean-Michel Trivi AudioSystem.DEVICE_STATE_AVAILABLE, 37364c637b9e34f4c8db69a64ad21a4e2bcfa7485b5fJean-Michel Trivi address); 37374c637b9e34f4c8db69a64ad21a4e2bcfa7485b5fJean-Michel Trivi // Reset A2DP suspend state each time a new sink is connected 37384c637b9e34f4c8db69a64ad21a4e2bcfa7485b5fJean-Michel Trivi AudioSystem.setParameters("A2dpSuspended=false"); 37394c637b9e34f4c8db69a64ad21a4e2bcfa7485b5fJean-Michel Trivi mConnectedDevices.put( new Integer(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP), 37404c637b9e34f4c8db69a64ad21a4e2bcfa7485b5fJean-Michel Trivi address); 37414c637b9e34f4c8db69a64ad21a4e2bcfa7485b5fJean-Michel Trivi } 37424c637b9e34f4c8db69a64ad21a4e2bcfa7485b5fJean-Michel Trivi 37435bfaeaef3fc348d66f48b86be08655e91dff910aEric Laurent private void onSendBecomingNoisyIntent() { 37445ac72a29593ab9a20337a2225df52bdf4754be02Dianne Hackborn sendBroadcastToAll(new Intent(AudioManager.ACTION_AUDIO_BECOMING_NOISY)); 37459841818b9a0280abf59343c9e00a2976dbc084faMike Lockwood } 37469841818b9a0280abf59343c9e00a2976dbc084faMike Lockwood 37476bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent // must be called synchronized on mConnectedDevices 37484c637b9e34f4c8db69a64ad21a4e2bcfa7485b5fJean-Michel Trivi private void makeA2dpDeviceUnavailableNow(String address) { 3749c9d1d5f35091226e96fcfa91817480f589eb36e2Matthew Xie synchronized (mA2dpAvrcpLock) { 3750c9d1d5f35091226e96fcfa91817480f589eb36e2Matthew Xie mAvrcpAbsVolSupported = false; 3751c9d1d5f35091226e96fcfa91817480f589eb36e2Matthew Xie } 37524c637b9e34f4c8db69a64ad21a4e2bcfa7485b5fJean-Michel Trivi AudioSystem.setDeviceConnectionState(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, 37534c637b9e34f4c8db69a64ad21a4e2bcfa7485b5fJean-Michel Trivi AudioSystem.DEVICE_STATE_UNAVAILABLE, 37544c637b9e34f4c8db69a64ad21a4e2bcfa7485b5fJean-Michel Trivi address); 37554c637b9e34f4c8db69a64ad21a4e2bcfa7485b5fJean-Michel Trivi mConnectedDevices.remove(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP); 37564c637b9e34f4c8db69a64ad21a4e2bcfa7485b5fJean-Michel Trivi } 37574c637b9e34f4c8db69a64ad21a4e2bcfa7485b5fJean-Michel Trivi 37586bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent // must be called synchronized on mConnectedDevices 37594c637b9e34f4c8db69a64ad21a4e2bcfa7485b5fJean-Michel Trivi private void makeA2dpDeviceUnavailableLater(String address) { 37603b5912602bec6ccbe8eef8a576730b1565f0067cEric Laurent // prevent any activity on the A2DP audio output to avoid unwanted 37613b5912602bec6ccbe8eef8a576730b1565f0067cEric Laurent // reconnection of the sink. 37623b5912602bec6ccbe8eef8a576730b1565f0067cEric Laurent AudioSystem.setParameters("A2dpSuspended=true"); 37634c637b9e34f4c8db69a64ad21a4e2bcfa7485b5fJean-Michel Trivi // the device will be made unavailable later, so consider it disconnected right away 37644c637b9e34f4c8db69a64ad21a4e2bcfa7485b5fJean-Michel Trivi mConnectedDevices.remove(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP); 37654c637b9e34f4c8db69a64ad21a4e2bcfa7485b5fJean-Michel Trivi // send the delayed message to make the device unavailable later 37664c637b9e34f4c8db69a64ad21a4e2bcfa7485b5fJean-Michel Trivi Message msg = mAudioHandler.obtainMessage(MSG_BTA2DP_DOCK_TIMEOUT, address); 37674c637b9e34f4c8db69a64ad21a4e2bcfa7485b5fJean-Michel Trivi mAudioHandler.sendMessageDelayed(msg, BTA2DP_DOCK_TIMEOUT_MILLIS); 37684c637b9e34f4c8db69a64ad21a4e2bcfa7485b5fJean-Michel Trivi 37694c637b9e34f4c8db69a64ad21a4e2bcfa7485b5fJean-Michel Trivi } 37704c637b9e34f4c8db69a64ad21a4e2bcfa7485b5fJean-Michel Trivi 37716bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent // must be called synchronized on mConnectedDevices 3772a847ba4080675d395de725cfac5dfd9d5a993d4eJean-Michel Trivi private void cancelA2dpDeviceTimeout() { 37734c637b9e34f4c8db69a64ad21a4e2bcfa7485b5fJean-Michel Trivi mAudioHandler.removeMessages(MSG_BTA2DP_DOCK_TIMEOUT); 37744c637b9e34f4c8db69a64ad21a4e2bcfa7485b5fJean-Michel Trivi } 37754c637b9e34f4c8db69a64ad21a4e2bcfa7485b5fJean-Michel Trivi 37766bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent // must be called synchronized on mConnectedDevices 3777a847ba4080675d395de725cfac5dfd9d5a993d4eJean-Michel Trivi private boolean hasScheduledA2dpDockTimeout() { 3778a847ba4080675d395de725cfac5dfd9d5a993d4eJean-Michel Trivi return mAudioHandler.hasMessages(MSG_BTA2DP_DOCK_TIMEOUT); 3779a847ba4080675d395de725cfac5dfd9d5a993d4eJean-Michel Trivi } 3780a847ba4080675d395de725cfac5dfd9d5a993d4eJean-Michel Trivi 3781b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent private void onSetA2dpConnectionState(BluetoothDevice btDevice, int state) 37826bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent { 37835a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du if (DEBUG_VOL) Log.d(TAG, "onSetA2dpConnectionState btDevice="+btDevice+" state="+state); 37846bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent if (btDevice == null) { 37856bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent return; 37866bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent } 37876bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent String address = btDevice.getAddress(); 37886bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent if (!BluetoothAdapter.checkBluetoothAddress(address)) { 37896bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent address = ""; 37906bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent } 37915a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du 37926bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent synchronized (mConnectedDevices) { 37936bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent boolean isConnected = 37946bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent (mConnectedDevices.containsKey(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP) && 37956bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent mConnectedDevices.get(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP).equals(address)); 37966bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent 37976bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent if (isConnected && state != BluetoothProfile.STATE_CONNECTED) { 37986bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent if (btDevice.isBluetoothDock()) { 37996bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent if (state == BluetoothProfile.STATE_DISCONNECTED) { 38006bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent // introduction of a delay for transient disconnections of docks when 38016bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent // power is rapidly turned off/on, this message will be canceled if 38026bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent // we reconnect the dock under a preset delay 38036bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent makeA2dpDeviceUnavailableLater(address); 38046bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent // the next time isConnected is evaluated, it will be false for the dock 38056bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent } 38066bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent } else { 38076bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent makeA2dpDeviceUnavailableNow(address); 38086bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent } 3809632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn synchronized (mCurAudioRoutes) { 3810632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn if (mCurAudioRoutes.mBluetoothName != null) { 3811632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn mCurAudioRoutes.mBluetoothName = null; 3812632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn sendMsg(mAudioHandler, MSG_REPORT_NEW_ROUTES, 3813632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn SENDMSG_NOOP, 0, 0, null, 0); 3814632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn } 3815632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn } 38166bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent } else if (!isConnected && state == BluetoothProfile.STATE_CONNECTED) { 38176bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent if (btDevice.isBluetoothDock()) { 38186bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent // this could be a reconnection after a transient disconnection 38196bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent cancelA2dpDeviceTimeout(); 38206bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent mDockAddress = address; 38216bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent } else { 38226bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent // this could be a connection of another A2DP device before the timeout of 38236bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent // a dock: cancel the dock timeout, and make the dock unavailable now 38246bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent if(hasScheduledA2dpDockTimeout()) { 38256bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent cancelA2dpDeviceTimeout(); 38266bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent makeA2dpDeviceUnavailableNow(mDockAddress); 38276bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent } 38286bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent } 38296bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent makeA2dpDeviceAvailable(address); 3830632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn synchronized (mCurAudioRoutes) { 3831632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn String name = btDevice.getAliasName(); 3832632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn if (!TextUtils.equals(mCurAudioRoutes.mBluetoothName, name)) { 3833632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn mCurAudioRoutes.mBluetoothName = name; 3834632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn sendMsg(mAudioHandler, MSG_REPORT_NEW_ROUTES, 3835632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn SENDMSG_NOOP, 0, 0, null, 0); 3836632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn } 3837632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn } 38386bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent } 38396bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent } 38406bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent } 38416bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent 38425a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du public void avrcpSupportsAbsoluteVolume(String address, boolean support) { 38435a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du // address is not used for now, but may be used when multiple a2dp devices are supported 38445a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du synchronized (mA2dpAvrcpLock) { 38455a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du mAvrcpAbsVolSupported = support; 3846c9d1d5f35091226e96fcfa91817480f589eb36e2Matthew Xie VolumeStreamState streamState = mStreamStates[AudioSystem.STREAM_MUSIC]; 3847c9d1d5f35091226e96fcfa91817480f589eb36e2Matthew Xie sendMsg(mAudioHandler, MSG_SET_DEVICE_VOLUME, SENDMSG_QUEUE, 3848c9d1d5f35091226e96fcfa91817480f589eb36e2Matthew Xie AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, 0, streamState, 0); 38495a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du } 38505a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du } 38515a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du 385259f482764e346a5c5ac118ee1f7b24da645c2559Eric Laurent private boolean handleDeviceConnection(boolean connected, int device, String params) { 385359f482764e346a5c5ac118ee1f7b24da645c2559Eric Laurent synchronized (mConnectedDevices) { 385459f482764e346a5c5ac118ee1f7b24da645c2559Eric Laurent boolean isConnected = (mConnectedDevices.containsKey(device) && 38559841818b9a0280abf59343c9e00a2976dbc084faMike Lockwood (params.isEmpty() || mConnectedDevices.get(device).equals(params))); 385659f482764e346a5c5ac118ee1f7b24da645c2559Eric Laurent 385759f482764e346a5c5ac118ee1f7b24da645c2559Eric Laurent if (isConnected && !connected) { 385859f482764e346a5c5ac118ee1f7b24da645c2559Eric Laurent AudioSystem.setDeviceConnectionState(device, 385959f482764e346a5c5ac118ee1f7b24da645c2559Eric Laurent AudioSystem.DEVICE_STATE_UNAVAILABLE, 38609841818b9a0280abf59343c9e00a2976dbc084faMike Lockwood mConnectedDevices.get(device)); 386159f482764e346a5c5ac118ee1f7b24da645c2559Eric Laurent mConnectedDevices.remove(device); 386259f482764e346a5c5ac118ee1f7b24da645c2559Eric Laurent return true; 386359f482764e346a5c5ac118ee1f7b24da645c2559Eric Laurent } else if (!isConnected && connected) { 386459f482764e346a5c5ac118ee1f7b24da645c2559Eric Laurent AudioSystem.setDeviceConnectionState(device, 386559f482764e346a5c5ac118ee1f7b24da645c2559Eric Laurent AudioSystem.DEVICE_STATE_AVAILABLE, 386659f482764e346a5c5ac118ee1f7b24da645c2559Eric Laurent params); 386759f482764e346a5c5ac118ee1f7b24da645c2559Eric Laurent mConnectedDevices.put(new Integer(device), params); 386859f482764e346a5c5ac118ee1f7b24da645c2559Eric Laurent return true; 386959f482764e346a5c5ac118ee1f7b24da645c2559Eric Laurent } 387059f482764e346a5c5ac118ee1f7b24da645c2559Eric Laurent } 387159f482764e346a5c5ac118ee1f7b24da645c2559Eric Laurent return false; 387259f482764e346a5c5ac118ee1f7b24da645c2559Eric Laurent } 387359f482764e346a5c5ac118ee1f7b24da645c2559Eric Laurent 3874b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent // Devices which removal triggers intent ACTION_AUDIO_BECOMING_NOISY. The intent is only 3875b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent // sent if none of these devices is connected. 3876b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent int mBecomingNoisyIntentDevices = 3877b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent AudioSystem.DEVICE_OUT_WIRED_HEADSET | AudioSystem.DEVICE_OUT_WIRED_HEADPHONE | 3878794da7a0543cbecffefb73794aa68d1a93e41adfEric Laurent AudioSystem.DEVICE_OUT_ALL_A2DP | AudioSystem.DEVICE_OUT_AUX_DIGITAL | 3879794da7a0543cbecffefb73794aa68d1a93e41adfEric Laurent AudioSystem.DEVICE_OUT_ANLG_DOCK_HEADSET | AudioSystem.DEVICE_OUT_DGTL_DOCK_HEADSET | 3880794da7a0543cbecffefb73794aa68d1a93e41adfEric Laurent AudioSystem.DEVICE_OUT_ALL_USB; 3881b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent 3882b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent // must be called before removing the device from mConnectedDevices 3883b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent private int checkSendBecomingNoisyIntent(int device, int state) { 3884b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent int delay = 0; 3885b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent if ((state == 0) && ((device & mBecomingNoisyIntentDevices) != 0)) { 3886b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent int devices = 0; 3887b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent for (int dev : mConnectedDevices.keySet()) { 3888b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent if ((dev & mBecomingNoisyIntentDevices) != 0) { 3889b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent devices |= dev; 3890b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent } 3891b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent } 3892b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent if (devices == device) { 38935bfaeaef3fc348d66f48b86be08655e91dff910aEric Laurent sendMsg(mAudioHandler, 38945bfaeaef3fc348d66f48b86be08655e91dff910aEric Laurent MSG_BROADCAST_AUDIO_BECOMING_NOISY, 38955bfaeaef3fc348d66f48b86be08655e91dff910aEric Laurent SENDMSG_REPLACE, 38965bfaeaef3fc348d66f48b86be08655e91dff910aEric Laurent 0, 38975bfaeaef3fc348d66f48b86be08655e91dff910aEric Laurent 0, 38985bfaeaef3fc348d66f48b86be08655e91dff910aEric Laurent null, 38995bfaeaef3fc348d66f48b86be08655e91dff910aEric Laurent 0); 3900b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent delay = 1000; 3901b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent } 3902b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent } 3903b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent 3904b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent if (mAudioHandler.hasMessages(MSG_SET_A2DP_CONNECTION_STATE) || 3905b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent mAudioHandler.hasMessages(MSG_SET_WIRED_DEVICE_CONNECTION_STATE)) { 3906b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent delay = 1000; 3907b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent } 3908b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent return delay; 3909b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent } 3910b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent 3911b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent private void sendDeviceConnectionIntent(int device, int state, String name) 3912b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent { 3913b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent Intent intent = new Intent(); 3914b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent 3915b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent intent.putExtra("state", state); 3916b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent intent.putExtra("name", name); 3917b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY); 3918b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent 3919632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn int connType = 0; 3920632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn 3921b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent if (device == AudioSystem.DEVICE_OUT_WIRED_HEADSET) { 3922632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn connType = AudioRoutesInfo.MAIN_HEADSET; 3923b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent intent.setAction(Intent.ACTION_HEADSET_PLUG); 3924b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent intent.putExtra("microphone", 1); 3925b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent } else if (device == AudioSystem.DEVICE_OUT_WIRED_HEADPHONE) { 3926632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn connType = AudioRoutesInfo.MAIN_HEADPHONES; 3927b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent intent.setAction(Intent.ACTION_HEADSET_PLUG); 3928b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent intent.putExtra("microphone", 0); 3929b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent } else if (device == AudioSystem.DEVICE_OUT_ANLG_DOCK_HEADSET) { 3930632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn connType = AudioRoutesInfo.MAIN_DOCK_SPEAKERS; 3931b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent intent.setAction(Intent.ACTION_ANALOG_AUDIO_DOCK_PLUG); 3932b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent } else if (device == AudioSystem.DEVICE_OUT_DGTL_DOCK_HEADSET) { 3933632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn connType = AudioRoutesInfo.MAIN_DOCK_SPEAKERS; 3934b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent intent.setAction(Intent.ACTION_DIGITAL_AUDIO_DOCK_PLUG); 3935b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent } else if (device == AudioSystem.DEVICE_OUT_AUX_DIGITAL) { 3936632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn connType = AudioRoutesInfo.MAIN_HDMI; 3937b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent intent.setAction(Intent.ACTION_HDMI_AUDIO_PLUG); 3938b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent } 3939b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent 3940632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn synchronized (mCurAudioRoutes) { 3941632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn if (connType != 0) { 3942632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn int newConn = mCurAudioRoutes.mMainType; 3943632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn if (state != 0) { 3944632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn newConn |= connType; 3945632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn } else { 3946632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn newConn &= ~connType; 3947632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn } 3948632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn if (newConn != mCurAudioRoutes.mMainType) { 3949632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn mCurAudioRoutes.mMainType = newConn; 3950632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn sendMsg(mAudioHandler, MSG_REPORT_NEW_ROUTES, 3951632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn SENDMSG_NOOP, 0, 0, null, 0); 3952632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn } 3953632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn } 3954632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn } 3955632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn 39565ac72a29593ab9a20337a2225df52bdf4754be02Dianne Hackborn final long ident = Binder.clearCallingIdentity(); 39575ac72a29593ab9a20337a2225df52bdf4754be02Dianne Hackborn try { 39585ac72a29593ab9a20337a2225df52bdf4754be02Dianne Hackborn ActivityManagerNative.broadcastStickyIntent(intent, null, UserHandle.USER_ALL); 39595ac72a29593ab9a20337a2225df52bdf4754be02Dianne Hackborn } finally { 39605ac72a29593ab9a20337a2225df52bdf4754be02Dianne Hackborn Binder.restoreCallingIdentity(ident); 39615ac72a29593ab9a20337a2225df52bdf4754be02Dianne Hackborn } 3962b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent } 3963b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent 3964b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent private void onSetWiredDeviceConnectionState(int device, int state, String name) 3965b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent { 3966b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent synchronized (mConnectedDevices) { 3967b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent if ((state == 0) && ((device == AudioSystem.DEVICE_OUT_WIRED_HEADSET) || 3968b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent (device == AudioSystem.DEVICE_OUT_WIRED_HEADPHONE))) { 3969b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent setBluetoothA2dpOnInt(true); 3970b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent } 3971db45484e4b5858d14da93d3a06311b93bf0cf320Mike Lockwood boolean isUsb = ((device & AudioSystem.DEVICE_OUT_ALL_USB) != 0); 3972db45484e4b5858d14da93d3a06311b93bf0cf320Mike Lockwood handleDeviceConnection((state == 1), device, (isUsb ? name : "")); 3973f1a457d06c53a901ea08d2d3fb6e766bc06c4d4fEric Laurent if (state != 0) { 3974f1a457d06c53a901ea08d2d3fb6e766bc06c4d4fEric Laurent if ((device == AudioSystem.DEVICE_OUT_WIRED_HEADSET) || 3975f1a457d06c53a901ea08d2d3fb6e766bc06c4d4fEric Laurent (device == AudioSystem.DEVICE_OUT_WIRED_HEADPHONE)) { 3976f1a457d06c53a901ea08d2d3fb6e766bc06c4d4fEric Laurent setBluetoothA2dpOnInt(false); 3977f1a457d06c53a901ea08d2d3fb6e766bc06c4d4fEric Laurent } 3978f1a457d06c53a901ea08d2d3fb6e766bc06c4d4fEric Laurent if ((device & mSafeMediaVolumeDevices) != 0) { 3979f1a457d06c53a901ea08d2d3fb6e766bc06c4d4fEric Laurent sendMsg(mAudioHandler, 3980f1a457d06c53a901ea08d2d3fb6e766bc06c4d4fEric Laurent MSG_CHECK_MUSIC_ACTIVE, 3981f1a457d06c53a901ea08d2d3fb6e766bc06c4d4fEric Laurent SENDMSG_REPLACE, 3982f1a457d06c53a901ea08d2d3fb6e766bc06c4d4fEric Laurent 0, 3983f1a457d06c53a901ea08d2d3fb6e766bc06c4d4fEric Laurent 0, 3984f1a457d06c53a901ea08d2d3fb6e766bc06c4d4fEric Laurent null, 3985f1a457d06c53a901ea08d2d3fb6e766bc06c4d4fEric Laurent MUSIC_ACTIVE_POLL_PERIOD_MS); 3986f1a457d06c53a901ea08d2d3fb6e766bc06c4d4fEric Laurent } 3987b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent } 3988db45484e4b5858d14da93d3a06311b93bf0cf320Mike Lockwood if (!isUsb) { 3989db45484e4b5858d14da93d3a06311b93bf0cf320Mike Lockwood sendDeviceConnectionIntent(device, state, name); 3990db45484e4b5858d14da93d3a06311b93bf0cf320Mike Lockwood } 3991b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent } 3992b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent } 3993b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent 3994a847ba4080675d395de725cfac5dfd9d5a993d4eJean-Michel Trivi /* cache of the address of the last dock the device was connected to */ 3995a847ba4080675d395de725cfac5dfd9d5a993d4eJean-Michel Trivi private String mDockAddress; 3996a847ba4080675d395de725cfac5dfd9d5a993d4eJean-Michel Trivi 3997a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent /** 3998a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent * Receiver for misc intent broadcasts the Phone app cares about. 3999a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent */ 4000a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent private class AudioServiceBroadcastReceiver extends BroadcastReceiver { 4001a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent @Override 4002a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent public void onReceive(Context context, Intent intent) { 4003a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent String action = intent.getAction(); 400459f482764e346a5c5ac118ee1f7b24da645c2559Eric Laurent int device; 400559f482764e346a5c5ac118ee1f7b24da645c2559Eric Laurent int state; 4006a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent 4007758559e6b7e310cf46cc269437f44decd58d68d6Jean-Michel Trivi if (action.equals(Intent.ACTION_DOCK_EVENT)) { 4008758559e6b7e310cf46cc269437f44decd58d68d6Jean-Michel Trivi int dockState = intent.getIntExtra(Intent.EXTRA_DOCK_STATE, 4009758559e6b7e310cf46cc269437f44decd58d68d6Jean-Michel Trivi Intent.EXTRA_DOCK_STATE_UNDOCKED); 4010758559e6b7e310cf46cc269437f44decd58d68d6Jean-Michel Trivi int config; 4011758559e6b7e310cf46cc269437f44decd58d68d6Jean-Michel Trivi switch (dockState) { 4012758559e6b7e310cf46cc269437f44decd58d68d6Jean-Michel Trivi case Intent.EXTRA_DOCK_STATE_DESK: 4013758559e6b7e310cf46cc269437f44decd58d68d6Jean-Michel Trivi config = AudioSystem.FORCE_BT_DESK_DOCK; 4014758559e6b7e310cf46cc269437f44decd58d68d6Jean-Michel Trivi break; 4015758559e6b7e310cf46cc269437f44decd58d68d6Jean-Michel Trivi case Intent.EXTRA_DOCK_STATE_CAR: 4016758559e6b7e310cf46cc269437f44decd58d68d6Jean-Michel Trivi config = AudioSystem.FORCE_BT_CAR_DOCK; 4017758559e6b7e310cf46cc269437f44decd58d68d6Jean-Michel Trivi break; 401821e941bf43362ddc6639a9f2d0828053360f53d7Praveen Bharathi case Intent.EXTRA_DOCK_STATE_LE_DESK: 401908ed1b9d2099ec8231b21353b33b901492ea9885Eric Laurent config = AudioSystem.FORCE_ANALOG_DOCK; 402021e941bf43362ddc6639a9f2d0828053360f53d7Praveen Bharathi break; 402121e941bf43362ddc6639a9f2d0828053360f53d7Praveen Bharathi case Intent.EXTRA_DOCK_STATE_HE_DESK: 402221e941bf43362ddc6639a9f2d0828053360f53d7Praveen Bharathi config = AudioSystem.FORCE_DIGITAL_DOCK; 402321e941bf43362ddc6639a9f2d0828053360f53d7Praveen Bharathi break; 4024758559e6b7e310cf46cc269437f44decd58d68d6Jean-Michel Trivi case Intent.EXTRA_DOCK_STATE_UNDOCKED: 4025758559e6b7e310cf46cc269437f44decd58d68d6Jean-Michel Trivi default: 4026758559e6b7e310cf46cc269437f44decd58d68d6Jean-Michel Trivi config = AudioSystem.FORCE_NONE; 4027758559e6b7e310cf46cc269437f44decd58d68d6Jean-Michel Trivi } 402808ed1b9d2099ec8231b21353b33b901492ea9885Eric Laurent // Low end docks have a menu to enable or disable audio 402908ed1b9d2099ec8231b21353b33b901492ea9885Eric Laurent // (see mDockAudioMediaEnabled) 403008ed1b9d2099ec8231b21353b33b901492ea9885Eric Laurent if (!((dockState == Intent.EXTRA_DOCK_STATE_LE_DESK) || 403108ed1b9d2099ec8231b21353b33b901492ea9885Eric Laurent ((dockState == Intent.EXTRA_DOCK_STATE_UNDOCKED) && 403208ed1b9d2099ec8231b21353b33b901492ea9885Eric Laurent (mDockState == Intent.EXTRA_DOCK_STATE_LE_DESK)))) { 403308ed1b9d2099ec8231b21353b33b901492ea9885Eric Laurent AudioSystem.setForceUse(AudioSystem.FOR_DOCK, config); 403408ed1b9d2099ec8231b21353b33b901492ea9885Eric Laurent } 403508ed1b9d2099ec8231b21353b33b901492ea9885Eric Laurent mDockState = dockState; 403682aa7f017daaaeb96c13e6e3491d5037ab471085Jaikumar Ganesh } else if (action.equals(BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED)) { 403759f482764e346a5c5ac118ee1f7b24da645c2559Eric Laurent state = intent.getIntExtra(BluetoothProfile.EXTRA_STATE, 403882aa7f017daaaeb96c13e6e3491d5037ab471085Jaikumar Ganesh BluetoothProfile.STATE_DISCONNECTED); 403959f482764e346a5c5ac118ee1f7b24da645c2559Eric Laurent device = AudioSystem.DEVICE_OUT_BLUETOOTH_SCO; 4040a56d1c72190462aa9e377906583eceb58e0efcddNick Pelly String address = null; 4041dca56b9432e2cc851d1a58920071fed2e1e3d142Eric Laurent 4042dca56b9432e2cc851d1a58920071fed2e1e3d142Eric Laurent BluetoothDevice btDevice = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE); 4043dca56b9432e2cc851d1a58920071fed2e1e3d142Eric Laurent if (btDevice == null) { 4044dca56b9432e2cc851d1a58920071fed2e1e3d142Eric Laurent return; 4045dca56b9432e2cc851d1a58920071fed2e1e3d142Eric Laurent } 4046dca56b9432e2cc851d1a58920071fed2e1e3d142Eric Laurent 4047dca56b9432e2cc851d1a58920071fed2e1e3d142Eric Laurent address = btDevice.getAddress(); 4048dca56b9432e2cc851d1a58920071fed2e1e3d142Eric Laurent BluetoothClass btClass = btDevice.getBluetoothClass(); 4049dca56b9432e2cc851d1a58920071fed2e1e3d142Eric Laurent if (btClass != null) { 4050dca56b9432e2cc851d1a58920071fed2e1e3d142Eric Laurent switch (btClass.getDeviceClass()) { 4051dca56b9432e2cc851d1a58920071fed2e1e3d142Eric Laurent case BluetoothClass.Device.AUDIO_VIDEO_WEARABLE_HEADSET: 4052dca56b9432e2cc851d1a58920071fed2e1e3d142Eric Laurent case BluetoothClass.Device.AUDIO_VIDEO_HANDSFREE: 4053dca56b9432e2cc851d1a58920071fed2e1e3d142Eric Laurent device = AudioSystem.DEVICE_OUT_BLUETOOTH_SCO_HEADSET; 4054dca56b9432e2cc851d1a58920071fed2e1e3d142Eric Laurent break; 4055dca56b9432e2cc851d1a58920071fed2e1e3d142Eric Laurent case BluetoothClass.Device.AUDIO_VIDEO_CAR_AUDIO: 4056dca56b9432e2cc851d1a58920071fed2e1e3d142Eric Laurent device = AudioSystem.DEVICE_OUT_BLUETOOTH_SCO_CARKIT; 4057dca56b9432e2cc851d1a58920071fed2e1e3d142Eric Laurent break; 4058d5603c126acdd94d9f7400bb1d04188020a425b4Eric Laurent } 4059d5603c126acdd94d9f7400bb1d04188020a425b4Eric Laurent } 4060d5603c126acdd94d9f7400bb1d04188020a425b4Eric Laurent 4061dca56b9432e2cc851d1a58920071fed2e1e3d142Eric Laurent if (!BluetoothAdapter.checkBluetoothAddress(address)) { 4062dca56b9432e2cc851d1a58920071fed2e1e3d142Eric Laurent address = ""; 4063dca56b9432e2cc851d1a58920071fed2e1e3d142Eric Laurent } 4064d5603c126acdd94d9f7400bb1d04188020a425b4Eric Laurent 406559f482764e346a5c5ac118ee1f7b24da645c2559Eric Laurent boolean connected = (state == BluetoothProfile.STATE_CONNECTED); 406659f482764e346a5c5ac118ee1f7b24da645c2559Eric Laurent if (handleDeviceConnection(connected, device, address)) { 40676bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent synchronized (mScoClients) { 406859f482764e346a5c5ac118ee1f7b24da645c2559Eric Laurent if (connected) { 406959f482764e346a5c5ac118ee1f7b24da645c2559Eric Laurent mBluetoothHeadsetDevice = btDevice; 407059f482764e346a5c5ac118ee1f7b24da645c2559Eric Laurent } else { 40716bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent mBluetoothHeadsetDevice = null; 40726bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent resetBluetoothSco(); 40736bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent } 407462ef767b15a712bab31cc0d5508a330906f535c2Eric Laurent } 4075a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent } 407659f482764e346a5c5ac118ee1f7b24da645c2559Eric Laurent } else if (action.equals(Intent.ACTION_USB_AUDIO_ACCESSORY_PLUG) || 407759f482764e346a5c5ac118ee1f7b24da645c2559Eric Laurent action.equals(Intent.ACTION_USB_AUDIO_DEVICE_PLUG)) { 407859f482764e346a5c5ac118ee1f7b24da645c2559Eric Laurent state = intent.getIntExtra("state", 0); 407959f482764e346a5c5ac118ee1f7b24da645c2559Eric Laurent int alsaCard = intent.getIntExtra("card", -1); 408059f482764e346a5c5ac118ee1f7b24da645c2559Eric Laurent int alsaDevice = intent.getIntExtra("device", -1); 40819841818b9a0280abf59343c9e00a2976dbc084faMike Lockwood String params = (alsaCard == -1 && alsaDevice == -1 ? "" 40829841818b9a0280abf59343c9e00a2976dbc084faMike Lockwood : "card=" + alsaCard + ";device=" + alsaDevice); 408359f482764e346a5c5ac118ee1f7b24da645c2559Eric Laurent device = action.equals(Intent.ACTION_USB_AUDIO_ACCESSORY_PLUG) ? 408459f482764e346a5c5ac118ee1f7b24da645c2559Eric Laurent AudioSystem.DEVICE_OUT_USB_ACCESSORY : AudioSystem.DEVICE_OUT_USB_DEVICE; 408559f482764e346a5c5ac118ee1f7b24da645c2559Eric Laurent Log.v(TAG, "Broadcast Receiver: Got " 408659f482764e346a5c5ac118ee1f7b24da645c2559Eric Laurent + (action.equals(Intent.ACTION_USB_AUDIO_ACCESSORY_PLUG) ? 408759f482764e346a5c5ac118ee1f7b24da645c2559Eric Laurent "ACTION_USB_AUDIO_ACCESSORY_PLUG" : "ACTION_USB_AUDIO_DEVICE_PLUG") 408859f482764e346a5c5ac118ee1f7b24da645c2559Eric Laurent + ", state = " + state + ", card: " + alsaCard + ", device: " + alsaDevice); 4089db45484e4b5858d14da93d3a06311b93bf0cf320Mike Lockwood setWiredDeviceConnectionState(device, state, params); 40903def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent } else if (action.equals(BluetoothHeadset.ACTION_AUDIO_STATE_CHANGED)) { 409162ef767b15a712bab31cc0d5508a330906f535c2Eric Laurent boolean broadcast = false; 409259f482764e346a5c5ac118ee1f7b24da645c2559Eric Laurent int scoAudioState = AudioManager.SCO_AUDIO_STATE_ERROR; 40933def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent synchronized (mScoClients) { 409462ef767b15a712bab31cc0d5508a330906f535c2Eric Laurent int btState = intent.getIntExtra(BluetoothProfile.EXTRA_STATE, -1); 4095dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent // broadcast intent if the connection was initated by AudioService 4096dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent if (!mScoClients.isEmpty() && 4097dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent (mScoAudioState == SCO_STATE_ACTIVE_INTERNAL || 4098dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent mScoAudioState == SCO_STATE_ACTIVATE_REQ || 4099dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent mScoAudioState == SCO_STATE_DEACTIVATE_REQ)) { 410062ef767b15a712bab31cc0d5508a330906f535c2Eric Laurent broadcast = true; 410162ef767b15a712bab31cc0d5508a330906f535c2Eric Laurent } 410262ef767b15a712bab31cc0d5508a330906f535c2Eric Laurent switch (btState) { 410362ef767b15a712bab31cc0d5508a330906f535c2Eric Laurent case BluetoothHeadset.STATE_AUDIO_CONNECTED: 410459f482764e346a5c5ac118ee1f7b24da645c2559Eric Laurent scoAudioState = AudioManager.SCO_AUDIO_STATE_CONNECTED; 4105dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent if (mScoAudioState != SCO_STATE_ACTIVE_INTERNAL && 4106dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent mScoAudioState != SCO_STATE_DEACTIVATE_REQ && 4107dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent mScoAudioState != SCO_STATE_DEACTIVATE_EXT_REQ) { 410862ef767b15a712bab31cc0d5508a330906f535c2Eric Laurent mScoAudioState = SCO_STATE_ACTIVE_EXTERNAL; 41093def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent } 411062ef767b15a712bab31cc0d5508a330906f535c2Eric Laurent break; 411162ef767b15a712bab31cc0d5508a330906f535c2Eric Laurent case BluetoothHeadset.STATE_AUDIO_DISCONNECTED: 411259f482764e346a5c5ac118ee1f7b24da645c2559Eric Laurent scoAudioState = AudioManager.SCO_AUDIO_STATE_DISCONNECTED; 411362ef767b15a712bab31cc0d5508a330906f535c2Eric Laurent mScoAudioState = SCO_STATE_INACTIVE; 4114d7454be47f4111c0478a502353e11dea401378bdEric Laurent clearAllScoClients(0, false); 411562ef767b15a712bab31cc0d5508a330906f535c2Eric Laurent break; 411662ef767b15a712bab31cc0d5508a330906f535c2Eric Laurent case BluetoothHeadset.STATE_AUDIO_CONNECTING: 4117dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent if (mScoAudioState != SCO_STATE_ACTIVE_INTERNAL && 4118dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent mScoAudioState != SCO_STATE_DEACTIVATE_REQ && 4119dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent mScoAudioState != SCO_STATE_DEACTIVATE_EXT_REQ) { 412062ef767b15a712bab31cc0d5508a330906f535c2Eric Laurent mScoAudioState = SCO_STATE_ACTIVE_EXTERNAL; 41213def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent } 412262ef767b15a712bab31cc0d5508a330906f535c2Eric Laurent default: 412362ef767b15a712bab31cc0d5508a330906f535c2Eric Laurent // do not broadcast CONNECTING or invalid state 412462ef767b15a712bab31cc0d5508a330906f535c2Eric Laurent broadcast = false; 412562ef767b15a712bab31cc0d5508a330906f535c2Eric Laurent break; 41263def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent } 41273def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent } 412862ef767b15a712bab31cc0d5508a330906f535c2Eric Laurent if (broadcast) { 412959f482764e346a5c5ac118ee1f7b24da645c2559Eric Laurent broadcastScoConnectionState(scoAudioState); 4130dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent //FIXME: this is to maintain compatibility with deprecated intent 4131dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent // AudioManager.ACTION_SCO_AUDIO_STATE_CHANGED. Remove when appropriate. 413262ef767b15a712bab31cc0d5508a330906f535c2Eric Laurent Intent newIntent = new Intent(AudioManager.ACTION_SCO_AUDIO_STATE_CHANGED); 413359f482764e346a5c5ac118ee1f7b24da645c2559Eric Laurent newIntent.putExtra(AudioManager.EXTRA_SCO_AUDIO_STATE, scoAudioState); 41345ac72a29593ab9a20337a2225df52bdf4754be02Dianne Hackborn sendStickyBroadcastToAll(newIntent); 413562ef767b15a712bab31cc0d5508a330906f535c2Eric Laurent } 413662ef767b15a712bab31cc0d5508a330906f535c2Eric Laurent } else if (action.equals(Intent.ACTION_BOOT_COMPLETED)) { 4137a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent mBootCompleted = true; 41385d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent sendMsg(mAudioHandler, MSG_LOAD_SOUND_EFFECTS, SENDMSG_QUEUE, 4139117b7bb5b5a4457711f59bde3dcc83d8f111c524Eric Laurent 0, 0, null, 0); 4140dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent 41416243edd818b84adfbe712d5d233d6414b33653acAmith Yamasani mKeyguardManager = 41426243edd818b84adfbe712d5d233d6414b33653acAmith Yamasani (KeyguardManager) mContext.getSystemService(Context.KEYGUARD_SERVICE); 4143dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent mScoConnectionState = AudioManager.SCO_AUDIO_STATE_ERROR; 4144dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent resetBluetoothSco(); 4145dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent getBluetoothHeadset(); 4146dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent //FIXME: this is to maintain compatibility with deprecated intent 4147dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent // AudioManager.ACTION_SCO_AUDIO_STATE_CHANGED. Remove when appropriate. 414862ef767b15a712bab31cc0d5508a330906f535c2Eric Laurent Intent newIntent = new Intent(AudioManager.ACTION_SCO_AUDIO_STATE_CHANGED); 414962ef767b15a712bab31cc0d5508a330906f535c2Eric Laurent newIntent.putExtra(AudioManager.EXTRA_SCO_AUDIO_STATE, 415062ef767b15a712bab31cc0d5508a330906f535c2Eric Laurent AudioManager.SCO_AUDIO_STATE_DISCONNECTED); 41515ac72a29593ab9a20337a2225df52bdf4754be02Dianne Hackborn sendStickyBroadcastToAll(newIntent); 41526bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent 41536bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter(); 41546bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent if (adapter != null) { 41556bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent adapter.getProfileProxy(mContext, mBluetoothProfileServiceListener, 41566bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent BluetoothProfile.A2DP); 41576bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent } 4158d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent 4159d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent sendMsg(mAudioHandler, 4160d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent MSG_CONFIGURE_SAFE_MEDIA_VOLUME_FORCED, 4161d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent SENDMSG_REPLACE, 4162d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent 0, 4163d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent 0, 4164d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent null, 4165d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent SAFE_VOLUME_CONFIGURE_TIMEOUT_MS); 4166950e8cb40a6d826af4cc2eef9d3908c1b70486e6Eric Laurent } else if (action.equals(Intent.ACTION_SCREEN_ON)) { 4167950e8cb40a6d826af4cc2eef9d3908c1b70486e6Eric Laurent AudioSystem.setParameters("screen_state=on"); 4168950e8cb40a6d826af4cc2eef9d3908c1b70486e6Eric Laurent } else if (action.equals(Intent.ACTION_SCREEN_OFF)) { 4169950e8cb40a6d826af4cc2eef9d3908c1b70486e6Eric Laurent AudioSystem.setParameters("screen_state=off"); 4170961cae92540763226648813d111c5b5c3b0f1597Dianne Hackborn } else if (action.equals(Intent.ACTION_CONFIGURATION_CHANGED)) { 4171f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi handleConfigurationChanged(context); 4172bc0fab1fc2db832ef86d8a33466ec4d68b103ca0Eric Laurent } else if (action.equals(Intent.ACTION_USER_SWITCHED)) { 4173f4a8eb22112c534f436357b50f231778c5c15c25Jean-Michel Trivi // attempt to stop music playback for background user 41745bfaeaef3fc348d66f48b86be08655e91dff910aEric Laurent sendMsg(mAudioHandler, 41755bfaeaef3fc348d66f48b86be08655e91dff910aEric Laurent MSG_BROADCAST_AUDIO_BECOMING_NOISY, 41765bfaeaef3fc348d66f48b86be08655e91dff910aEric Laurent SENDMSG_REPLACE, 41775bfaeaef3fc348d66f48b86be08655e91dff910aEric Laurent 0, 41785bfaeaef3fc348d66f48b86be08655e91dff910aEric Laurent 0, 41795bfaeaef3fc348d66f48b86be08655e91dff910aEric Laurent null, 41805bfaeaef3fc348d66f48b86be08655e91dff910aEric Laurent 0); 4181f4a8eb22112c534f436357b50f231778c5c15c25Jean-Michel Trivi // the current audio focus owner is no longer valid 4182fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi mMediaFocusControl.discardAudioFocusOwner(); 4183f4a8eb22112c534f436357b50f231778c5c15c25Jean-Michel Trivi 41845bfaeaef3fc348d66f48b86be08655e91dff910aEric Laurent // load volume settings for new user 4185bc0fab1fc2db832ef86d8a33466ec4d68b103ca0Eric Laurent readAudioSettings(true /*userSwitch*/); 4186bc0fab1fc2db832ef86d8a33466ec4d68b103ca0Eric Laurent // preserve STREAM_MUSIC volume from one user to the next. 4187bc0fab1fc2db832ef86d8a33466ec4d68b103ca0Eric Laurent sendMsg(mAudioHandler, 4188bc0fab1fc2db832ef86d8a33466ec4d68b103ca0Eric Laurent MSG_SET_ALL_VOLUMES, 4189bc0fab1fc2db832ef86d8a33466ec4d68b103ca0Eric Laurent SENDMSG_QUEUE, 4190bc0fab1fc2db832ef86d8a33466ec4d68b103ca0Eric Laurent 0, 4191bc0fab1fc2db832ef86d8a33466ec4d68b103ca0Eric Laurent 0, 4192bc0fab1fc2db832ef86d8a33466ec4d68b103ca0Eric Laurent mStreamStates[AudioSystem.STREAM_MUSIC], 0); 4193a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent } 4194a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent } 4195a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent } 4196d5176cfe6eae954e9cef1e2ec17859a5089e1330Jean-Michel Trivi 4197d5176cfe6eae954e9cef1e2ec17859a5089e1330Jean-Michel Trivi //========================================================================================== 4198fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi // RemoteControlDisplay / RemoteControlClient / Remote info 4199d5176cfe6eae954e9cef1e2ec17859a5089e1330Jean-Michel Trivi //========================================================================================== 4200f108cdd9ee5efe354d87edd02a07b323298c116cJean-Michel Trivi public boolean registerRemoteController(IRemoteControlDisplay rcd, int w, int h, 4201f108cdd9ee5efe354d87edd02a07b323298c116cJean-Michel Trivi ComponentName listenerComp) { 4202f108cdd9ee5efe354d87edd02a07b323298c116cJean-Michel Trivi return mMediaFocusControl.registerRemoteController(rcd, w, h, listenerComp); 4203f108cdd9ee5efe354d87edd02a07b323298c116cJean-Michel Trivi } 4204f108cdd9ee5efe354d87edd02a07b323298c116cJean-Michel Trivi 42057ddd226e7c6e759feaf2747a90be1cc06acf37a3Jean-Michel Trivi public boolean registerRemoteControlDisplay(IRemoteControlDisplay rcd, int w, int h) { 4206f108cdd9ee5efe354d87edd02a07b323298c116cJean-Michel Trivi return mMediaFocusControl.registerRemoteControlDisplay(rcd, w, h); 4207e5e1e870fdb35f5291790e6d178bde7126f6fe35Jean-Michel Trivi } 4208e5e1e870fdb35f5291790e6d178bde7126f6fe35Jean-Michel Trivi 4209fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi public void unregisterRemoteControlDisplay(IRemoteControlDisplay rcd) { 4210fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi mMediaFocusControl.unregisterRemoteControlDisplay(rcd); 4211d5176cfe6eae954e9cef1e2ec17859a5089e1330Jean-Michel Trivi } 4212d5176cfe6eae954e9cef1e2ec17859a5089e1330Jean-Michel Trivi 4213fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi public void remoteControlDisplayUsesBitmapSize(IRemoteControlDisplay rcd, int w, int h) { 4214fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi mMediaFocusControl.remoteControlDisplayUsesBitmapSize(rcd, w, h); 4215d5176cfe6eae954e9cef1e2ec17859a5089e1330Jean-Michel Trivi } 4216d5176cfe6eae954e9cef1e2ec17859a5089e1330Jean-Michel Trivi 4217fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi public void remoteControlDisplayWantsPlaybackPositionSync(IRemoteControlDisplay rcd, 4218fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi boolean wantsSync) { 4219fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi mMediaFocusControl.remoteControlDisplayWantsPlaybackPositionSync(rcd, wantsSync); 4220d5176cfe6eae954e9cef1e2ec17859a5089e1330Jean-Michel Trivi } 4221d5176cfe6eae954e9cef1e2ec17859a5089e1330Jean-Michel Trivi 4222fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi public void registerMediaButtonEventReceiverForCalls(ComponentName c) { 4223fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi mMediaFocusControl.registerMediaButtonEventReceiverForCalls(c); 4224d5176cfe6eae954e9cef1e2ec17859a5089e1330Jean-Michel Trivi } 4225d5176cfe6eae954e9cef1e2ec17859a5089e1330Jean-Michel Trivi 4226fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi public void unregisterMediaButtonEventReceiverForCalls() { 4227fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi mMediaFocusControl.unregisterMediaButtonEventReceiverForCalls(); 4228d5176cfe6eae954e9cef1e2ec17859a5089e1330Jean-Michel Trivi } 4229d5176cfe6eae954e9cef1e2ec17859a5089e1330Jean-Michel Trivi 4230fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi public void registerMediaButtonIntent(PendingIntent pi, ComponentName c, IBinder token) { 4231fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi mMediaFocusControl.registerMediaButtonIntent(pi, c, token); 4232d5176cfe6eae954e9cef1e2ec17859a5089e1330Jean-Michel Trivi } 4233d5176cfe6eae954e9cef1e2ec17859a5089e1330Jean-Michel Trivi 4234fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi public void unregisterMediaButtonIntent(PendingIntent pi) { 4235fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi mMediaFocusControl.unregisterMediaButtonIntent(pi); 4236d5176cfe6eae954e9cef1e2ec17859a5089e1330Jean-Michel Trivi } 4237f823fc4dba2df5cf5f00e13361f2db93c81f6961Jean-Michel Trivi 4238fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi public int registerRemoteControlClient(PendingIntent mediaIntent, 4239fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi IRemoteControlClient rcClient, String callingPckg) { 4240fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi return mMediaFocusControl.registerRemoteControlClient(mediaIntent, rcClient, callingPckg); 4241d5176cfe6eae954e9cef1e2ec17859a5089e1330Jean-Michel Trivi } 4242d5176cfe6eae954e9cef1e2ec17859a5089e1330Jean-Michel Trivi 4243fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi public void unregisterRemoteControlClient(PendingIntent mediaIntent, 4244fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi IRemoteControlClient rcClient) { 4245fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi mMediaFocusControl.unregisterRemoteControlClient(mediaIntent, rcClient); 4246d5176cfe6eae954e9cef1e2ec17859a5089e1330Jean-Michel Trivi } 4247d5176cfe6eae954e9cef1e2ec17859a5089e1330Jean-Michel Trivi 4248fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi public void setRemoteControlClientPlaybackPosition(int generationId, long timeMs) { 4249fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi mMediaFocusControl.setRemoteControlClientPlaybackPosition(generationId, timeMs); 4250c68022258ebd3dd97a5079ba99f4f3cd12b223b0Jean-Michel Trivi } 4251c68022258ebd3dd97a5079ba99f4f3cd12b223b0Jean-Michel Trivi 42527ddd226e7c6e759feaf2747a90be1cc06acf37a3Jean-Michel Trivi public void updateRemoteControlClientMetadata(int generationId, int key, Rating value) { 4253f823fc4dba2df5cf5f00e13361f2db93c81f6961Jean-Michel Trivi mMediaFocusControl.updateRemoteControlClientMetadata(generationId, key, value); 4254f823fc4dba2df5cf5f00e13361f2db93c81f6961Jean-Michel Trivi } 4255f823fc4dba2df5cf5f00e13361f2db93c81f6961Jean-Michel Trivi 4256fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi public void registerRemoteVolumeObserverForRcc(int rccId, IRemoteVolumeObserver rvo) { 4257fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi mMediaFocusControl.registerRemoteVolumeObserverForRcc(rccId, rvo); 4258c68022258ebd3dd97a5079ba99f4f3cd12b223b0Jean-Michel Trivi } 4259c68022258ebd3dd97a5079ba99f4f3cd12b223b0Jean-Michel Trivi 4260fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi public int getRemoteStreamVolume() { 4261fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi return mMediaFocusControl.getRemoteStreamVolume(); 42624294b83927f51e5c115ebaafd2e185ba5de91436Jean-Michel Trivi } 42634294b83927f51e5c115ebaafd2e185ba5de91436Jean-Michel Trivi 4264fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi public int getRemoteStreamMaxVolume() { 4265fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi return mMediaFocusControl.getRemoteStreamMaxVolume(); 4266722b808662eb20fa91151f1e3aa05fd911d1d226Jean-Michel Trivi } 4267722b808662eb20fa91151f1e3aa05fd911d1d226Jean-Michel Trivi 4268fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi public void setRemoteStreamVolume(int index) { 4269fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi mMediaFocusControl.setRemoteStreamVolume(index); 4270d327f21626217aa3c9c0cdb7a84a742c531e59a3Jean-Michel Trivi } 4271d327f21626217aa3c9c0cdb7a84a742c531e59a3Jean-Michel Trivi 4272fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi public void setPlaybackStateForRcc(int rccId, int state, long timeMs, float speed) { 4273fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi mMediaFocusControl.setPlaybackStateForRcc(rccId, state, timeMs, speed); 42744294b83927f51e5c115ebaafd2e185ba5de91436Jean-Michel Trivi } 42754294b83927f51e5c115ebaafd2e185ba5de91436Jean-Michel Trivi 4276fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi public void setPlaybackInfoForRcc(int rccId, int what, int value) { 4277fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi mMediaFocusControl.setPlaybackInfoForRcc(rccId, what, value); 42784294b83927f51e5c115ebaafd2e185ba5de91436Jean-Michel Trivi } 42794294b83927f51e5c115ebaafd2e185ba5de91436Jean-Michel Trivi 4280fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi public void dispatchMediaKeyEvent(KeyEvent keyEvent) { 4281fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi mMediaFocusControl.dispatchMediaKeyEvent(keyEvent); 4282c68022258ebd3dd97a5079ba99f4f3cd12b223b0Jean-Michel Trivi } 4283c68022258ebd3dd97a5079ba99f4f3cd12b223b0Jean-Michel Trivi 4284fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi public void dispatchMediaKeyEventUnderWakelock(KeyEvent keyEvent) { 4285fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi mMediaFocusControl.dispatchMediaKeyEventUnderWakelock(keyEvent); 42864294b83927f51e5c115ebaafd2e185ba5de91436Jean-Michel Trivi } 42874294b83927f51e5c115ebaafd2e185ba5de91436Jean-Michel Trivi 4288fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi //========================================================================================== 4289fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi // Audio Focus 4290fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi //========================================================================================== 4291fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi public int requestAudioFocus(int mainStreamType, int durationHint, IBinder cb, 4292fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi IAudioFocusDispatcher fd, String clientId, String callingPackageName) { 4293fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi return mMediaFocusControl.requestAudioFocus(mainStreamType, durationHint, cb, fd, 4294fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi clientId, callingPackageName); 42954294b83927f51e5c115ebaafd2e185ba5de91436Jean-Michel Trivi } 42964294b83927f51e5c115ebaafd2e185ba5de91436Jean-Michel Trivi 4297fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi public int abandonAudioFocus(IAudioFocusDispatcher fd, String clientId) { 4298fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi return mMediaFocusControl.abandonAudioFocus(fd, clientId); 4299c68022258ebd3dd97a5079ba99f4f3cd12b223b0Jean-Michel Trivi } 4300c68022258ebd3dd97a5079ba99f4f3cd12b223b0Jean-Michel Trivi 4301fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi public void unregisterAudioFocusClient(String clientId) { 4302fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi mMediaFocusControl.unregisterAudioFocusClient(clientId); 43033114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi } 43043114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi 43052380566debfc57eb1cc07db1306ccee23b84ddd4Jean-Michel Trivi public int getCurrentAudioFocus() { 43062380566debfc57eb1cc07db1306ccee23b84ddd4Jean-Michel Trivi return mMediaFocusControl.getCurrentAudioFocus(); 43072380566debfc57eb1cc07db1306ccee23b84ddd4Jean-Michel Trivi } 43082380566debfc57eb1cc07db1306ccee23b84ddd4Jean-Michel Trivi 4309f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi //========================================================================================== 4310f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi // Device orientation 4311f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi //========================================================================================== 4312f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi /** 4313bb6f8711a7f804d39c45218db2d6339940cc5d35Jean-Michel Trivi * Handles device configuration changes that may map to a change in the orientation 4314bb6f8711a7f804d39c45218db2d6339940cc5d35Jean-Michel Trivi * or orientation. 4315bb6f8711a7f804d39c45218db2d6339940cc5d35Jean-Michel Trivi * Monitoring orientation and rotation is optional, and is defined by the definition and value 4316bb6f8711a7f804d39c45218db2d6339940cc5d35Jean-Michel Trivi * of the "ro.audio.monitorOrientation" and "ro.audio.monitorRotation" system properties. 4317f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi */ 4318f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi private void handleConfigurationChanged(Context context) { 4319f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi try { 4320f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi // reading new orientation "safely" (i.e. under try catch) in case anything 4321f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi // goes wrong when obtaining resources and configuration 4322d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent Configuration config = context.getResources().getConfiguration(); 4323bb6f8711a7f804d39c45218db2d6339940cc5d35Jean-Michel Trivi // TODO merge rotation and orientation 4324d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent if (mMonitorOrientation) { 4325d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent int newOrientation = config.orientation; 4326d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent if (newOrientation != mDeviceOrientation) { 4327d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent mDeviceOrientation = newOrientation; 4328d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent setOrientationForAudioSystem(); 4329d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent } 4330f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi } 4331bb6f8711a7f804d39c45218db2d6339940cc5d35Jean-Michel Trivi if (mMonitorRotation) { 4332bb6f8711a7f804d39c45218db2d6339940cc5d35Jean-Michel Trivi int newRotation = ((WindowManager) context.getSystemService( 4333bb6f8711a7f804d39c45218db2d6339940cc5d35Jean-Michel Trivi Context.WINDOW_SERVICE)).getDefaultDisplay().getRotation(); 4334bb6f8711a7f804d39c45218db2d6339940cc5d35Jean-Michel Trivi if (newRotation != mDeviceRotation) { 4335bb6f8711a7f804d39c45218db2d6339940cc5d35Jean-Michel Trivi mDeviceRotation = newRotation; 4336bb6f8711a7f804d39c45218db2d6339940cc5d35Jean-Michel Trivi setRotationForAudioSystem(); 4337bb6f8711a7f804d39c45218db2d6339940cc5d35Jean-Michel Trivi } 4338bb6f8711a7f804d39c45218db2d6339940cc5d35Jean-Michel Trivi } 4339d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent sendMsg(mAudioHandler, 4340d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent MSG_CONFIGURE_SAFE_MEDIA_VOLUME, 4341d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent SENDMSG_REPLACE, 4342d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent 0, 4343d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent 0, 4344d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent null, 4345d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent 0); 4346dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent 4347dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent boolean cameraSoundForced = mContext.getResources().getBoolean( 4348dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent com.android.internal.R.bool.config_camera_sound_forced); 4349dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent synchronized (mSettingsLock) { 4350dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent synchronized (mCameraSoundForced) { 4351dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent if (cameraSoundForced != mCameraSoundForced) { 4352dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent mCameraSoundForced = cameraSoundForced; 4353dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent 4354dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent VolumeStreamState s = mStreamStates[AudioSystem.STREAM_SYSTEM_ENFORCED]; 4355dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent if (cameraSoundForced) { 4356dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent s.setAllIndexesToMax(); 4357dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent mRingerModeAffectedStreams &= 4358dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent ~(1 << AudioSystem.STREAM_SYSTEM_ENFORCED); 4359dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent } else { 436042b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent s.setAllIndexes(mStreamStates[AudioSystem.STREAM_SYSTEM]); 4361dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent mRingerModeAffectedStreams |= 4362dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent (1 << AudioSystem.STREAM_SYSTEM_ENFORCED); 4363dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent } 4364dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent // take new state into account for streams muted by ringer mode 4365dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent setRingerModeInt(getRingerMode(), false); 4366dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent 4367dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent sendMsg(mAudioHandler, 4368dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent MSG_SET_FORCE_USE, 4369dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent SENDMSG_QUEUE, 4370dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent AudioSystem.FOR_SYSTEM, 4371dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent cameraSoundForced ? 4372dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent AudioSystem.FORCE_SYSTEM_ENFORCED : AudioSystem.FORCE_NONE, 4373dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent null, 4374dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent 0); 4375dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent 4376dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent sendMsg(mAudioHandler, 4377dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent MSG_SET_ALL_VOLUMES, 4378dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent SENDMSG_QUEUE, 4379dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent 0, 4380dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent 0, 4381dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent mStreamStates[AudioSystem.STREAM_SYSTEM_ENFORCED], 0); 4382dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent } 4383dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent } 4384dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent } 43858c02884c8c3c97cdc2366ac187c8a326308b895bFabrice Di Meglio mVolumePanel.setLayoutDirection(config.getLayoutDirection()); 4386f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi } catch (Exception e) { 4387bb6f8711a7f804d39c45218db2d6339940cc5d35Jean-Michel Trivi Log.e(TAG, "Error handling configuration change: ", e); 4388f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi } 4389f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi } 4390f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi 4391f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi private void setOrientationForAudioSystem() { 4392f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi switch (mDeviceOrientation) { 4393f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi case Configuration.ORIENTATION_LANDSCAPE: 4394f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi //Log.i(TAG, "orientation is landscape"); 4395f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi AudioSystem.setParameters("orientation=landscape"); 4396f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi break; 4397f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi case Configuration.ORIENTATION_PORTRAIT: 4398f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi //Log.i(TAG, "orientation is portrait"); 4399f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi AudioSystem.setParameters("orientation=portrait"); 4400f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi break; 4401f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi case Configuration.ORIENTATION_SQUARE: 4402f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi //Log.i(TAG, "orientation is square"); 4403f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi AudioSystem.setParameters("orientation=square"); 4404f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi break; 4405f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi case Configuration.ORIENTATION_UNDEFINED: 4406f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi //Log.i(TAG, "orientation is undefined"); 4407f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi AudioSystem.setParameters("orientation=undefined"); 4408f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi break; 4409f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi default: 4410f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi Log.e(TAG, "Unknown orientation"); 4411f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi } 4412f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi } 4413f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi 4414bb6f8711a7f804d39c45218db2d6339940cc5d35Jean-Michel Trivi private void setRotationForAudioSystem() { 4415bb6f8711a7f804d39c45218db2d6339940cc5d35Jean-Michel Trivi switch (mDeviceRotation) { 4416bb6f8711a7f804d39c45218db2d6339940cc5d35Jean-Michel Trivi case Surface.ROTATION_0: 4417bb6f8711a7f804d39c45218db2d6339940cc5d35Jean-Michel Trivi AudioSystem.setParameters("rotation=0"); 4418bb6f8711a7f804d39c45218db2d6339940cc5d35Jean-Michel Trivi break; 4419bb6f8711a7f804d39c45218db2d6339940cc5d35Jean-Michel Trivi case Surface.ROTATION_90: 4420bb6f8711a7f804d39c45218db2d6339940cc5d35Jean-Michel Trivi AudioSystem.setParameters("rotation=90"); 4421bb6f8711a7f804d39c45218db2d6339940cc5d35Jean-Michel Trivi break; 4422bb6f8711a7f804d39c45218db2d6339940cc5d35Jean-Michel Trivi case Surface.ROTATION_180: 4423bb6f8711a7f804d39c45218db2d6339940cc5d35Jean-Michel Trivi AudioSystem.setParameters("rotation=180"); 4424bb6f8711a7f804d39c45218db2d6339940cc5d35Jean-Michel Trivi break; 4425bb6f8711a7f804d39c45218db2d6339940cc5d35Jean-Michel Trivi case Surface.ROTATION_270: 4426bb6f8711a7f804d39c45218db2d6339940cc5d35Jean-Michel Trivi AudioSystem.setParameters("rotation=270"); 4427bb6f8711a7f804d39c45218db2d6339940cc5d35Jean-Michel Trivi break; 4428bb6f8711a7f804d39c45218db2d6339940cc5d35Jean-Michel Trivi default: 4429bb6f8711a7f804d39c45218db2d6339940cc5d35Jean-Michel Trivi Log.e(TAG, "Unknown device rotation"); 4430bb6f8711a7f804d39c45218db2d6339940cc5d35Jean-Michel Trivi } 4431bb6f8711a7f804d39c45218db2d6339940cc5d35Jean-Michel Trivi } 4432bb6f8711a7f804d39c45218db2d6339940cc5d35Jean-Michel Trivi 4433f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi 44347847211fb4699bf6018e29d214a918ed6657319bEric Laurent // Handles request to override default use of A2DP for media. 44357847211fb4699bf6018e29d214a918ed6657319bEric Laurent public void setBluetoothA2dpOnInt(boolean on) { 44367847211fb4699bf6018e29d214a918ed6657319bEric Laurent synchronized (mBluetoothA2dpEnabledLock) { 44377847211fb4699bf6018e29d214a918ed6657319bEric Laurent mBluetoothA2dpEnabled = on; 4438c390bed06b4a572e273ead1254da9a932e04dce3Eric Laurent mAudioHandler.removeMessages(MSG_SET_FORCE_BT_A2DP_USE); 4439c390bed06b4a572e273ead1254da9a932e04dce3Eric Laurent AudioSystem.setForceUse(AudioSystem.FOR_MEDIA, 4440c390bed06b4a572e273ead1254da9a932e04dce3Eric Laurent mBluetoothA2dpEnabled ? AudioSystem.FORCE_NONE : AudioSystem.FORCE_NO_BT_A2DP); 44417847211fb4699bf6018e29d214a918ed6657319bEric Laurent } 44427847211fb4699bf6018e29d214a918ed6657319bEric Laurent } 44437847211fb4699bf6018e29d214a918ed6657319bEric Laurent 4444d5176cfe6eae954e9cef1e2ec17859a5089e1330Jean-Michel Trivi @Override 4445098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey public void setRingtonePlayer(IRingtonePlayer player) { 4446098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey mContext.enforceCallingOrSelfPermission(REMOTE_AUDIO_PLAYBACK, null); 4447098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey mRingtonePlayer = player; 4448098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey } 4449098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey 4450098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey @Override 4451098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey public IRingtonePlayer getRingtonePlayer() { 4452098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey return mRingtonePlayer; 4453098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey } 4454098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey 4455098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey @Override 4456632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn public AudioRoutesInfo startWatchingRoutes(IAudioRoutesObserver observer) { 4457632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn synchronized (mCurAudioRoutes) { 4458632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn AudioRoutesInfo routes = new AudioRoutesInfo(mCurAudioRoutes); 4459632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn mRoutesObservers.register(observer); 4460632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn return routes; 4461632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn } 4462632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn } 4463632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn 4464c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent 4465c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent //========================================================================================== 4466c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent // Safe media volume management. 4467c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent // MUSIC stream volume level is limited when headphones are connected according to safety 4468c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent // regulation. When the user attempts to raise the volume above the limit, a warning is 4469c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent // displayed and the user has to acknowlegde before the volume is actually changed. 4470c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent // The volume index corresponding to the limit is stored in config_safe_media_volume_index 4471c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent // property. Platforms with a different limit must set this property accordingly in their 4472c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent // overlay. 4473c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent //========================================================================================== 4474c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent 4475d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent // mSafeMediaVolumeState indicates whether the media volume is limited over headphones. 4476d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent // It is SAFE_MEDIA_VOLUME_NOT_CONFIGURED at boot time until a network service is connected 4477d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent // or the configure time is elapsed. It is then set to SAFE_MEDIA_VOLUME_ACTIVE or 4478d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent // SAFE_MEDIA_VOLUME_DISABLED according to country option. If not SAFE_MEDIA_VOLUME_DISABLED, it 4479d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent // can be set to SAFE_MEDIA_VOLUME_INACTIVE by calling AudioService.disableSafeMediaVolume() 4480d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent // (when user opts out). 4481d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent private final int SAFE_MEDIA_VOLUME_NOT_CONFIGURED = 0; 4482d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent private final int SAFE_MEDIA_VOLUME_DISABLED = 1; 4483d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent private final int SAFE_MEDIA_VOLUME_INACTIVE = 2; 4484d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent private final int SAFE_MEDIA_VOLUME_ACTIVE = 3; 4485d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent private Integer mSafeMediaVolumeState; 4486d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent 4487d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent private int mMcc = 0; 4488c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent // mSafeMediaVolumeIndex is the cached value of config_safe_media_volume_index property 4489d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent private int mSafeMediaVolumeIndex; 4490c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent // mSafeMediaVolumeDevices lists the devices for which safe media volume is enforced, 4491c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent private final int mSafeMediaVolumeDevices = AudioSystem.DEVICE_OUT_WIRED_HEADSET | 4492c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent AudioSystem.DEVICE_OUT_WIRED_HEADPHONE; 4493c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent // mMusicActiveMs is the cumulative time of music activity since safe volume was disabled. 4494c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent // When this time reaches UNSAFE_VOLUME_MUSIC_ACTIVE_MS_MAX, the safe media volume is re-enabled 4495c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent // automatically. mMusicActiveMs is rounded to a multiple of MUSIC_ACTIVE_POLL_PERIOD_MS. 4496c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent private int mMusicActiveMs; 4497c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent private static final int UNSAFE_VOLUME_MUSIC_ACTIVE_MS_MAX = (20 * 3600 * 1000); // 20 hours 4498c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent private static final int MUSIC_ACTIVE_POLL_PERIOD_MS = 60000; // 1 minute polling interval 4499d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent private static final int SAFE_VOLUME_CONFIGURE_TIMEOUT_MS = 30000; // 30s after boot completed 4500c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent 4501c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent private void setSafeMediaVolumeEnabled(boolean on) { 4502d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent synchronized (mSafeMediaVolumeState) { 4503d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent if ((mSafeMediaVolumeState != SAFE_MEDIA_VOLUME_NOT_CONFIGURED) && 4504d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent (mSafeMediaVolumeState != SAFE_MEDIA_VOLUME_DISABLED)) { 4505d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent if (on && (mSafeMediaVolumeState == SAFE_MEDIA_VOLUME_INACTIVE)) { 4506d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent mSafeMediaVolumeState = SAFE_MEDIA_VOLUME_ACTIVE; 4507d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent enforceSafeMediaVolume(); 4508d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent } else if (!on && (mSafeMediaVolumeState == SAFE_MEDIA_VOLUME_ACTIVE)) { 4509d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent mSafeMediaVolumeState = SAFE_MEDIA_VOLUME_INACTIVE; 4510d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent mMusicActiveMs = 0; 4511d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent sendMsg(mAudioHandler, 4512d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent MSG_CHECK_MUSIC_ACTIVE, 4513d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent SENDMSG_REPLACE, 4514d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent 0, 4515d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent 0, 4516d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent null, 4517d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent MUSIC_ACTIVE_POLL_PERIOD_MS); 4518d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent } 4519c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent } 4520c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent } 4521c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent } 4522c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent 4523c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent private void enforceSafeMediaVolume() { 4524c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent VolumeStreamState streamState = mStreamStates[AudioSystem.STREAM_MUSIC]; 4525c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent int devices = mSafeMediaVolumeDevices; 4526c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent int i = 0; 4527c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent 4528c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent while (devices != 0) { 4529c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent int device = 1 << i++; 4530c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent if ((device & devices) == 0) { 4531c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent continue; 4532c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent } 453342b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent int index = streamState.getIndex(device); 4534c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent if (index > mSafeMediaVolumeIndex) { 453542b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent streamState.setIndex(mSafeMediaVolumeIndex, device); 453642b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent sendMsg(mAudioHandler, 453742b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent MSG_SET_DEVICE_VOLUME, 453842b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent SENDMSG_QUEUE, 453942b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent device, 454042b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent 0, 454142b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent streamState, 454242b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent 0); 4543c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent } 4544c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent devices &= ~device; 4545c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent } 4546c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent } 4547c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent 4548c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent private boolean checkSafeMediaVolume(int streamType, int index, int device) { 4549d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent synchronized (mSafeMediaVolumeState) { 4550d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent if ((mSafeMediaVolumeState == SAFE_MEDIA_VOLUME_ACTIVE) && 4551c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent (mStreamVolumeAlias[streamType] == AudioSystem.STREAM_MUSIC) && 4552c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent ((device & mSafeMediaVolumeDevices) != 0) && 4553c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent (index > mSafeMediaVolumeIndex)) { 4554c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent return false; 4555c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent } 4556c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent return true; 4557c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent } 4558c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent } 4559c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent 4560c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent public void disableSafeMediaVolume() { 4561d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent synchronized (mSafeMediaVolumeState) { 4562c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent setSafeMediaVolumeEnabled(false); 4563fde16d5879ea88a971004c984093409468b6139cEric Laurent if (mPendingVolumeCommand != null) { 4564fde16d5879ea88a971004c984093409468b6139cEric Laurent onSetStreamVolume(mPendingVolumeCommand.mStreamType, 4565fde16d5879ea88a971004c984093409468b6139cEric Laurent mPendingVolumeCommand.mIndex, 4566fde16d5879ea88a971004c984093409468b6139cEric Laurent mPendingVolumeCommand.mFlags, 4567fde16d5879ea88a971004c984093409468b6139cEric Laurent mPendingVolumeCommand.mDevice); 4568fde16d5879ea88a971004c984093409468b6139cEric Laurent mPendingVolumeCommand = null; 4569fde16d5879ea88a971004c984093409468b6139cEric Laurent } 4570c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent } 4571c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent } 4572c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent 4573c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent 4574dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent //========================================================================================== 4575dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent // Camera shutter sound policy. 4576dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent // config_camera_sound_forced configuration option in config.xml defines if the camera shutter 4577dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent // sound is forced (sound even if the device is in silent mode) or not. This option is false by 4578dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent // default and can be overridden by country specific overlay in values-mccXXX/config.xml. 4579dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent //========================================================================================== 4580dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent 4581dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent // cached value of com.android.internal.R.bool.config_camera_sound_forced 4582dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent private Boolean mCameraSoundForced; 4583dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent 4584dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent // called by android.hardware.Camera to populate CameraInfo.canDisableShutterSound 4585dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent public boolean isCameraSoundForced() { 4586dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent synchronized (mCameraSoundForced) { 4587dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent return mCameraSoundForced; 4588dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent } 4589dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent } 4590dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent 4591dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent private static final String[] RINGER_MODE_NAMES = new String[] { 4592dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent "SILENT", 4593dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent "VIBRATE", 4594dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent "NORMAL" 4595dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent }; 4596dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent 4597dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent private void dumpRingerMode(PrintWriter pw) { 4598dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent pw.println("\nRinger mode: "); 4599dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent pw.println("- mode: "+RINGER_MODE_NAMES[mRingerMode]); 4600dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent pw.print("- ringer mode affected streams = 0x"); 4601dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent pw.println(Integer.toHexString(mRingerModeAffectedStreams)); 4602dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent pw.print("- ringer mode muted streams = 0x"); 4603dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent pw.println(Integer.toHexString(mRingerModeMutedStreams)); 4604dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent } 4605dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent 4606632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn @Override 4607d5176cfe6eae954e9cef1e2ec17859a5089e1330Jean-Michel Trivi protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 4608eb4cc492c93ab9635dde78b958a834120412e72aJeff Sharkey mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DUMP, TAG); 4609eb4cc492c93ab9635dde78b958a834120412e72aJeff Sharkey 4610fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi mMediaFocusControl.dump(pw); 4611bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent dumpStreamStates(pw); 4612dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent dumpRingerMode(pw); 4613632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn pw.println("\nAudio routes:"); 4614632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn pw.print(" mMainType=0x"); pw.println(Integer.toHexString(mCurAudioRoutes.mMainType)); 4615632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn pw.print(" mBluetoothName="); pw.println(mCurAudioRoutes.mBluetoothName); 4616d5176cfe6eae954e9cef1e2ec17859a5089e1330Jean-Michel Trivi } 4617fd116ad1ab02f6060a0b2201f018317fa32e28b4Glenn Kasten 4618fd116ad1ab02f6060a0b2201f018317fa32e28b4Glenn Kasten // Inform AudioFlinger of our device's low RAM attribute 4619fd116ad1ab02f6060a0b2201f018317fa32e28b4Glenn Kasten private static void readAndSetLowRamDevice() 4620fd116ad1ab02f6060a0b2201f018317fa32e28b4Glenn Kasten { 4621fd116ad1ab02f6060a0b2201f018317fa32e28b4Glenn Kasten int status = AudioSystem.setLowRamDevice(ActivityManager.isLowRamDeviceStatic()); 4622fd116ad1ab02f6060a0b2201f018317fa32e28b4Glenn Kasten if (status != 0) { 4623fd116ad1ab02f6060a0b2201f018317fa32e28b4Glenn Kasten Log.w(TAG, "AudioFlinger informed of device's low RAM attribute; status " + status); 4624fd116ad1ab02f6060a0b2201f018317fa32e28b4Glenn Kasten } 4625fd116ad1ab02f6060a0b2201f018317fa32e28b4Glenn Kasten } 46269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 4627