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 24fd116ad1ab02f6060a0b2201f018317fa32e28b4Glenn Kastenimport android.app.ActivityManager; 259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.app.ActivityManagerNative; 26ba50b97cff80e73620a0e3d13cae169e095974a7Dianne Hackbornimport android.app.AppOpsManager; 276243edd818b84adfbe712d5d233d6414b33653acAmith Yamasaniimport android.app.KeyguardManager; 2882aa7f017daaaeb96c13e6e3491d5037ab471085Jaikumar Ganeshimport android.bluetooth.BluetoothA2dp; 2982aa7f017daaaeb96c13e6e3491d5037ab471085Jaikumar Ganeshimport android.bluetooth.BluetoothAdapter; 3082aa7f017daaaeb96c13e6e3491d5037ab471085Jaikumar Ganeshimport android.bluetooth.BluetoothClass; 3182aa7f017daaaeb96c13e6e3491d5037ab471085Jaikumar Ganeshimport android.bluetooth.BluetoothDevice; 3282aa7f017daaaeb96c13e6e3491d5037ab471085Jaikumar Ganeshimport android.bluetooth.BluetoothHeadset; 3382aa7f017daaaeb96c13e6e3491d5037ab471085Jaikumar Ganeshimport android.bluetooth.BluetoothProfile; 34bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pellyimport android.content.BroadcastReceiver; 35d327f21626217aa3c9c0cdb7a84a742c531e59a3Jean-Michel Triviimport android.content.ComponentName; 369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.ContentResolver; 379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.Context; 389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.Intent; 39a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurentimport android.content.IntentFilter; 409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.pm.PackageManager; 41f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Triviimport android.content.res.Configuration; 42e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurentimport android.content.res.Resources; 43e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurentimport android.content.res.XmlResourceParser; 44b109615ebebd6f3b9ae789412279f576c3ace46bJason Parekhimport android.database.ContentObserver; 4541d974631c5f525da49c88d34cecedd5a4cfeda8Jungshik Jangimport android.hardware.hdmi.HdmiControlManager; 46212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurentimport android.hardware.hdmi.HdmiPlaybackClient; 4741d974631c5f525da49c88d34cecedd5a4cfeda8Jungshik Jangimport android.hardware.hdmi.HdmiTvClient; 48c837a451946b64d70ed7c642fbde03c182c28b6fPaul McLeanimport android.hardware.usb.UsbManager; 499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.media.MediaPlayer.OnCompletionListener; 509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.media.MediaPlayer.OnErrorListener; 518fdb0d4defb6ee2ca8057d3442ead36b408b6c17Jean-Michel Triviimport android.media.audiopolicy.AudioMix; 52958876fe55ea0fdeb73c72240a2f2bab32833443Jean-Michel Triviimport android.media.audiopolicy.AudioPolicy; 53a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Triviimport android.media.audiopolicy.AudioPolicyConfig; 540212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Triviimport android.media.audiopolicy.IAudioPolicyCallback; 559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Binder; 56c18c9138cee0f0859bcab636a004ce92ca4a9ab5Eric Laurentimport android.os.Build; 579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Environment; 589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Handler; 599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.IBinder; 609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Looper; 619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Message; 62c68022258ebd3dd97a5079ba99f4f3cd12b223b0Jean-Michel Triviimport android.os.PowerManager; 63632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackbornimport android.os.RemoteCallbackList; 649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.RemoteException; 6533f4e04e32fac42f158733d6a731e50490fa9951John Spurlockimport android.os.SystemClock; 6682aa7f017daaaeb96c13e6e3491d5037ab471085Jaikumar Ganeshimport android.os.SystemProperties; 675ac72a29593ab9a20337a2225df52bdf4754be02Dianne Hackbornimport android.os.UserHandle; 68bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurentimport android.os.Vibrator; 699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.provider.Settings; 709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.provider.Settings.System; 71ef9f6f957d897ea0ed82114185b8fa3fefd4917bTyler Gunnimport android.telecom.TelecomManager; 72632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackbornimport android.text.TextUtils; 739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.Log; 74aa5ee4d65f8788e2a0afcd198367450853fd72acJohn Spurlockimport android.util.MathUtils; 75a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Triviimport android.util.Slog; 76d327f21626217aa3c9c0cdb7a84a742c531e59a3Jean-Michel Triviimport android.view.KeyEvent; 77519c7744b522aa07e12bc3244ac3de14aa2a4ad0RoboErikimport android.view.OrientationEventListener; 78bb6f8711a7f804d39c45218db2d6339940cc5d35Jean-Michel Triviimport android.view.Surface; 79bb6f8711a7f804d39c45218db2d6339940cc5d35Jean-Michel Triviimport android.view.WindowManager; 80873cc45da2463a11182fe94a2565364d7e1709bbJean-Michel Triviimport android.view.accessibility.AccessibilityManager; 819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 82e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurentimport com.android.internal.util.XmlUtils; 830dac35af2c6aa42bcd181981b041747cfd1afa5fRoboErikimport com.android.server.LocalServices; 84e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent 85e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurentimport org.xmlpull.v1.XmlPullParserException; 869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 87d5176cfe6eae954e9cef1e2ec17859a5089e1330Jean-Michel Triviimport java.io.FileDescriptor; 889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.IOException; 89d5176cfe6eae954e9cef1e2ec17859a5089e1330Jean-Michel Triviimport java.io.PrintWriter; 90e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurentimport java.lang.reflect.Field; 919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.ArrayList; 92c42ac9d4d03f62c3a1ba197a28a81fda44bd8b7fEric Laurentimport java.util.HashMap; 93c42ac9d4d03f62c3a1ba197a28a81fda44bd8b7fEric Laurentimport java.util.Iterator; 945a1e4cf83f5be1b5d79e2643fa791aa269b6a4bcJaikumar Ganeshimport java.util.List; 95c42ac9d4d03f62c3a1ba197a28a81fda44bd8b7fEric Laurentimport java.util.Map; 9682aa7f017daaaeb96c13e6e3491d5037ab471085Jaikumar Ganeshimport java.util.NoSuchElementException; 97d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErikimport java.util.Objects; 98c42ac9d4d03f62c3a1ba197a28a81fda44bd8b7fEric Laurentimport java.util.Set; 99519c7744b522aa07e12bc3244ac3de14aa2a4ad0RoboErikimport java.util.concurrent.ConcurrentHashMap; 1009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/** 1029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * The implementation of the volume manager service. 1039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p> 1049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * This implementation focuses on delivering a responsive UI. Most methods are 1059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * asynchronous to external calls. For example, the task of setting a volume 1069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * will update our internal state, but in a separate thread will set the system 1079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * volume and later persist to the database. Similarly, setting the ringer mode 1089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * will update the state and broadcast a change and in a separate thread later 1099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * persist the ringer mode. 1109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 1119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @hide 1129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 113fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivipublic class AudioService extends IAudioService.Stub { 1149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final String TAG = "AudioService"; 1169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 117339567d5c91a8dc9228913ed1e5deb0ebb8a4a64Jean-Michel Trivi /** Debug audio mode */ 118339567d5c91a8dc9228913ed1e5deb0ebb8a4a64Jean-Michel Trivi protected static final boolean DEBUG_MODE = Log.isLoggable(TAG + ".MOD", Log.DEBUG); 1198fdb0d4defb6ee2ca8057d3442ead36b408b6c17Jean-Michel Trivi 1208fdb0d4defb6ee2ca8057d3442ead36b408b6c17Jean-Michel Trivi /** Debug audio policy feature */ 1218fdb0d4defb6ee2ca8057d3442ead36b408b6c17Jean-Michel Trivi protected static final boolean DEBUG_AP = Log.isLoggable(TAG + ".AP", Log.DEBUG); 1228fdb0d4defb6ee2ca8057d3442ead36b408b6c17Jean-Michel Trivi 1233114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi /** Debug volumes */ 124ae641c9ccd3f81214cee54a5f13804f1765187adJohn Spurlock protected static final boolean DEBUG_VOL = Log.isLoggable(TAG + ".VOL", Log.DEBUG); 12518e7bce52318f00b5023f33933a571c477f2b61cJean-Michel Trivi 126430fc48865e5a371b08f180390946b96d73848feRoboErik /** debug calls to media session apis */ 127ae641c9ccd3f81214cee54a5f13804f1765187adJohn Spurlock private static final boolean DEBUG_SESSIONS = Log.isLoggable(TAG + ".SESSIONS", Log.DEBUG); 1288a2cfc309ab9126e90022916967c65a793c034f0RoboErik 1298600534df66c2ff5846ed230b50c56229322d48aJohn Spurlock /** Allow volume changes to set ringer mode to silent? */ 1308600534df66c2ff5846ed230b50c56229322d48aJohn Spurlock private static final boolean VOLUME_SETS_RINGER_MODE_SILENT = false; 1318600534df66c2ff5846ed230b50c56229322d48aJohn Spurlock 132a11b4affcad3d255aa723a89b768ea222506f2e8John Spurlock /** In silent mode, are volume adjustments (raises) prevented? */ 133a11b4affcad3d255aa723a89b768ea222506f2e8John Spurlock private static final boolean PREVENT_VOLUME_ADJUSTMENT_IF_SILENT = true; 134a11b4affcad3d255aa723a89b768ea222506f2e8John Spurlock 1359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** How long to delay before persisting a change in volume/ringer mode. */ 13645edba1b8b0377dfe70a4f2b0afb0f04dd8e1ee9RoboErik private static final int PERSIST_DELAY = 500; 1379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1383346a802087f621c6441bc512dfcc17b07143fc6John Spurlock /** 1393346a802087f621c6441bc512dfcc17b07143fc6John Spurlock * The delay before playing a sound. This small period exists so the user 1403346a802087f621c6441bc512dfcc17b07143fc6John Spurlock * can press another key (non-volume keys, too) to have it NOT be audible. 1413346a802087f621c6441bc512dfcc17b07143fc6John Spurlock * <p> 1423346a802087f621c6441bc512dfcc17b07143fc6John Spurlock * PhoneWindow will implement this part. 1433346a802087f621c6441bc512dfcc17b07143fc6John Spurlock */ 1443346a802087f621c6441bc512dfcc17b07143fc6John Spurlock public static final int PLAY_SOUND_DELAY = 300; 1453346a802087f621c6441bc512dfcc17b07143fc6John Spurlock 146a11b4affcad3d255aa723a89b768ea222506f2e8John Spurlock /** 147a11b4affcad3d255aa723a89b768ea222506f2e8John Spurlock * Only used in the result from {@link #checkForRingerModeChange(int, int, int)} 148a11b4affcad3d255aa723a89b768ea222506f2e8John Spurlock */ 149a11b4affcad3d255aa723a89b768ea222506f2e8John Spurlock private static final int FLAG_ADJUST_VOLUME = 1; 150a11b4affcad3d255aa723a89b768ea222506f2e8John Spurlock 151ba50b97cff80e73620a0e3d13cae169e095974a7Dianne Hackborn private final Context mContext; 152ba50b97cff80e73620a0e3d13cae169e095974a7Dianne Hackborn private final ContentResolver mContentResolver; 153ba50b97cff80e73620a0e3d13cae169e095974a7Dianne Hackborn private final AppOpsManager mAppOps; 154212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent 155212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent // the platform has no specific capabilities 156212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent private static final int PLATFORM_DEFAULT = 0; 157212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent // the platform is voice call capable (a phone) 158212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent private static final int PLATFORM_VOICE = 1; 159212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent // the platform is a television or a set-top box 160212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent private static final int PLATFORM_TELEVISION = 2; 161212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent // the platform type affects volume and silent mode behavior 162212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent private final int mPlatformType; 163212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent 164212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent private boolean isPlatformVoice() { 165212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent return mPlatformType == PLATFORM_VOICE; 166212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent } 167212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent 168212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent private boolean isPlatformTelevision() { 169212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent return mPlatformType == PLATFORM_TELEVISION; 170212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent } 171d5176cfe6eae954e9cef1e2ec17859a5089e1330Jean-Michel Trivi 1723346a802087f621c6441bc512dfcc17b07143fc6John Spurlock /** The controller for the volume UI. */ 1733346a802087f621c6441bc512dfcc17b07143fc6John Spurlock private final VolumeController mVolumeController = new VolumeController(); 1749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // sendMsg() flags 1769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** If the msg is already queued, replace it with this one. */ 1779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final int SENDMSG_REPLACE = 0; 1789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** If the msg is already queued, ignore this one and leave the old. */ 1799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final int SENDMSG_NOOP = 1; 1809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** If the msg is already queued, queue this one and leave the old. */ 1819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final int SENDMSG_QUEUE = 2; 1829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1833114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi // AudioHandler messages 1849bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent private static final int MSG_SET_DEVICE_VOLUME = 0; 1859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final int MSG_PERSIST_VOLUME = 1; 1865c55a051ad7d86a464fb91426f1ea3c0250e38b3Mike Lockwood private static final int MSG_PERSIST_MASTER_VOLUME = 2; 1879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final int MSG_PERSIST_RINGER_MODE = 3; 188bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent private static final int MSG_MEDIA_SERVER_DIED = 4; 189dfb881f96af7898151940a4bbc52e45e6043d38bEric Laurent private static final int MSG_PLAY_SOUND_EFFECT = 5; 190dfb881f96af7898151940a4bbc52e45e6043d38bEric Laurent private static final int MSG_BTA2DP_DOCK_TIMEOUT = 6; 191dfb881f96af7898151940a4bbc52e45e6043d38bEric Laurent private static final int MSG_LOAD_SOUND_EFFECTS = 7; 192dfb881f96af7898151940a4bbc52e45e6043d38bEric Laurent private static final int MSG_SET_FORCE_USE = 8; 193dfb881f96af7898151940a4bbc52e45e6043d38bEric Laurent private static final int MSG_BT_HEADSET_CNCT_FAILED = 9; 194dfb881f96af7898151940a4bbc52e45e6043d38bEric Laurent private static final int MSG_SET_ALL_VOLUMES = 10; 195dfb881f96af7898151940a4bbc52e45e6043d38bEric Laurent private static final int MSG_PERSIST_MASTER_VOLUME_MUTE = 11; 196dfb881f96af7898151940a4bbc52e45e6043d38bEric Laurent private static final int MSG_REPORT_NEW_ROUTES = 12; 197dfb881f96af7898151940a4bbc52e45e6043d38bEric Laurent private static final int MSG_SET_FORCE_BT_A2DP_USE = 13; 198dfb881f96af7898151940a4bbc52e45e6043d38bEric Laurent private static final int MSG_CHECK_MUSIC_ACTIVE = 14; 199dfb881f96af7898151940a4bbc52e45e6043d38bEric Laurent private static final int MSG_BROADCAST_AUDIO_BECOMING_NOISY = 15; 200dfb881f96af7898151940a4bbc52e45e6043d38bEric Laurent private static final int MSG_CONFIGURE_SAFE_MEDIA_VOLUME = 16; 201dfb881f96af7898151940a4bbc52e45e6043d38bEric Laurent private static final int MSG_CONFIGURE_SAFE_MEDIA_VOLUME_FORCED = 17; 202dfb881f96af7898151940a4bbc52e45e6043d38bEric Laurent private static final int MSG_PERSIST_SAFE_VOLUME_STATE = 18; 203dfb881f96af7898151940a4bbc52e45e6043d38bEric Laurent private static final int MSG_BROADCAST_BT_CONNECTION_STATE = 19; 204dfb881f96af7898151940a4bbc52e45e6043d38bEric Laurent private static final int MSG_UNLOAD_SOUND_EFFECTS = 20; 2054a5eeb9c727d77bb57fef87a70c8c9cc23dbfee3Eric Laurent private static final int MSG_SYSTEM_READY = 21; 206aa5ee4d65f8788e2a0afcd198367450853fd72acJohn Spurlock private static final int MSG_PERSIST_MUSIC_ACTIVE_MS = 22; 207b53453fae037d67e421011936c8fdffe7ba43922Julia Reynolds private static final int MSG_PERSIST_MICROPHONE_MUTE = 23; 2083114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi // start of messages handled under wakelock 2093114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi // these messages can only be queued, i.e. sent with queueMsgUnderWakeLock(), 210e12c39bb9cedb8b363658979872694eb55b1386eJean-Michel Trivi // and not with sendMsg(..., ..., SENDMSG_QUEUE, ...) 211fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi private static final int MSG_SET_WIRED_DEVICE_CONNECTION_STATE = 100; 2120a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood private static final int MSG_SET_A2DP_SRC_CONNECTION_STATE = 101; 2130a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood private static final int MSG_SET_A2DP_SINK_CONNECTION_STATE = 102; 2143114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi // end of messages handled under wakelock 215afbb047c3945e9c2b7e9bc6b25098d5fb80bba4eEric Laurent 2164c637b9e34f4c8db69a64ad21a4e2bcfa7485b5fJean-Michel Trivi private static final int BTA2DP_DOCK_TIMEOUT_MILLIS = 8000; 217dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent // Timeout for connection to bluetooth headset service 218dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent private static final int BT_HEADSET_CNCT_TIMEOUT_MS = 3000; 219dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent 2209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** @see AudioSystemThread */ 2219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private AudioSystemThread mAudioSystemThread; 2229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** @see AudioHandler */ 2239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private AudioHandler mAudioHandler; 2249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** @see VolumeStreamState */ 2259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private VolumeStreamState[] mStreamStates; 226b109615ebebd6f3b9ae789412279f576c3ace46bJason Parekh private SettingsObserver mSettingsObserver; 227a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent 228fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi private int mMode = AudioSystem.MODE_NORMAL; 229ba195ebc76f23b6679443724ab58c9dc9f2df884Glenn Kasten // protects mRingerMode 230ba195ebc76f23b6679443724ab58c9dc9f2df884Glenn Kasten private final Object mSettingsLock = new Object(); 23145c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent 2329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private SoundPool mSoundPool; 23330c918ce7fbe171944b28fc91b3f22b3d631872dGlenn Kasten private final Object mSoundEffectsLock = new Object(); 2349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final int NUM_SOUNDPOOL_CHANNELS = 4; 2359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2364767690f09ea3447b8c5c32fb28d27650aa18e00Mike Lockwood // Internally master volume is a float in the 0.0 - 1.0 range, 2374767690f09ea3447b8c5c32fb28d27650aa18e00Mike Lockwood // but to support integer based AudioManager API we translate it to 0 - 100 2384767690f09ea3447b8c5c32fb28d27650aa18e00Mike Lockwood private static final int MAX_MASTER_VOLUME = 100; 2394767690f09ea3447b8c5c32fb28d27650aa18e00Mike Lockwood 2406c798970ccb8759d1e613b57111daa8da0ab44c7Lei Zhang // Maximum volume adjust steps allowed in a single batch call. 2416c798970ccb8759d1e613b57111daa8da0ab44c7Lei Zhang private static final int MAX_BATCH_VOLUME_ADJUST_STEPS = 4; 2426c798970ccb8759d1e613b57111daa8da0ab44c7Lei Zhang 2439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* Sound effect file names */ 2449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final String SOUND_EFFECTS_PATH = "/media/audio/ui/"; 245e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent private static final List<String> SOUND_EFFECT_FILES = new ArrayList<String>(); 2469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* Sound effect file name mapping sound effect id (AudioManager.FX_xxx) to 2489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * file index in SOUND_EFFECT_FILES[] (first column) and indicating if effect 2499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * uses soundpool (second column) */ 250e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent private final int[][] SOUND_EFFECT_FILES_MAP = new int[AudioManager.NUM_SOUND_EFFECTS][2]; 2519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2525982013cfc8274ff0bafaba83c676b3a8890cba9Jared Suttles /** @hide Maximum volume index values for audio streams */ 25391377de6f23af2b0b08adae22810cae6fc35cb1aEric Laurent private static int[] MAX_STREAM_VOLUME = new int[] { 2546ee9952bc20be72b9419cb653c9e2e833889a3d3Eric Laurent 5, // STREAM_VOICE_CALL 2556ee9952bc20be72b9419cb653c9e2e833889a3d3Eric Laurent 7, // STREAM_SYSTEM 2566ee9952bc20be72b9419cb653c9e2e833889a3d3Eric Laurent 7, // STREAM_RING 2576ee9952bc20be72b9419cb653c9e2e833889a3d3Eric Laurent 15, // STREAM_MUSIC 2586ee9952bc20be72b9419cb653c9e2e833889a3d3Eric Laurent 7, // STREAM_ALARM 2596ee9952bc20be72b9419cb653c9e2e833889a3d3Eric Laurent 7, // STREAM_NOTIFICATION 2606ee9952bc20be72b9419cb653c9e2e833889a3d3Eric Laurent 15, // STREAM_BLUETOOTH_SCO 2616ee9952bc20be72b9419cb653c9e2e833889a3d3Eric Laurent 7, // STREAM_SYSTEM_ENFORCED 2626ee9952bc20be72b9419cb653c9e2e833889a3d3Eric Laurent 15, // STREAM_DTMF 2636ee9952bc20be72b9419cb653c9e2e833889a3d3Eric Laurent 15 // STREAM_TTS 2645982013cfc8274ff0bafaba83c676b3a8890cba9Jared Suttles }; 26591377de6f23af2b0b08adae22810cae6fc35cb1aEric Laurent 26691377de6f23af2b0b08adae22810cae6fc35cb1aEric Laurent private static int[] DEFAULT_STREAM_VOLUME = new int[] { 26791377de6f23af2b0b08adae22810cae6fc35cb1aEric Laurent 4, // STREAM_VOICE_CALL 26891377de6f23af2b0b08adae22810cae6fc35cb1aEric Laurent 7, // STREAM_SYSTEM 26991377de6f23af2b0b08adae22810cae6fc35cb1aEric Laurent 5, // STREAM_RING 27091377de6f23af2b0b08adae22810cae6fc35cb1aEric Laurent 11, // STREAM_MUSIC 27191377de6f23af2b0b08adae22810cae6fc35cb1aEric Laurent 6, // STREAM_ALARM 27291377de6f23af2b0b08adae22810cae6fc35cb1aEric Laurent 5, // STREAM_NOTIFICATION 27391377de6f23af2b0b08adae22810cae6fc35cb1aEric Laurent 7, // STREAM_BLUETOOTH_SCO 27491377de6f23af2b0b08adae22810cae6fc35cb1aEric Laurent 7, // STREAM_SYSTEM_ENFORCED 27591377de6f23af2b0b08adae22810cae6fc35cb1aEric Laurent 11, // STREAM_DTMF 27691377de6f23af2b0b08adae22810cae6fc35cb1aEric Laurent 11 // STREAM_TTS 27791377de6f23af2b0b08adae22810cae6fc35cb1aEric Laurent }; 27891377de6f23af2b0b08adae22810cae6fc35cb1aEric Laurent 2796d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent /* mStreamVolumeAlias[] indicates for each stream if it uses the volume settings 280a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent * of another stream: This avoids multiplying the volume settings for hidden 281a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent * stream types that follow other stream behavior for volume settings 2826d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent * NOTE: do not create loops in aliases! 2836d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent * Some streams alias to different streams according to device category (phone or tablet) or 28424e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent * use case (in call vs off call...). See updateStreamVolumeAlias() for more details. 285212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent * mStreamVolumeAlias contains STREAM_VOLUME_ALIAS_VOICE aliases for a voice capable device 286212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent * (phone), STREAM_VOLUME_ALIAS_TELEVISION for a television or set-top box and 287212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent * STREAM_VOLUME_ALIAS_DEFAULT for other devices (e.g. tablets).*/ 288212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent private final int[] STREAM_VOLUME_ALIAS_VOICE = new int[] { 2896d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent AudioSystem.STREAM_VOICE_CALL, // STREAM_VOICE_CALL 2906d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent AudioSystem.STREAM_RING, // STREAM_SYSTEM 2916d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent AudioSystem.STREAM_RING, // STREAM_RING 2926d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent AudioSystem.STREAM_MUSIC, // STREAM_MUSIC 2936d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent AudioSystem.STREAM_ALARM, // STREAM_ALARM 2946d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent AudioSystem.STREAM_RING, // STREAM_NOTIFICATION 2956d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent AudioSystem.STREAM_BLUETOOTH_SCO, // STREAM_BLUETOOTH_SCO 2966d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent AudioSystem.STREAM_RING, // STREAM_SYSTEM_ENFORCED 2976d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent AudioSystem.STREAM_RING, // STREAM_DTMF 2986d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent AudioSystem.STREAM_MUSIC // STREAM_TTS 299a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent }; 300212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent private final int[] STREAM_VOLUME_ALIAS_TELEVISION = new int[] { 301212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent AudioSystem.STREAM_MUSIC, // STREAM_VOICE_CALL 302212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent AudioSystem.STREAM_MUSIC, // STREAM_SYSTEM 303212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent AudioSystem.STREAM_MUSIC, // STREAM_RING 304212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent AudioSystem.STREAM_MUSIC, // STREAM_MUSIC 305212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent AudioSystem.STREAM_MUSIC, // STREAM_ALARM 306212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent AudioSystem.STREAM_MUSIC, // STREAM_NOTIFICATION 307212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent AudioSystem.STREAM_MUSIC, // STREAM_BLUETOOTH_SCO 308212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent AudioSystem.STREAM_MUSIC, // STREAM_SYSTEM_ENFORCED 309212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent AudioSystem.STREAM_MUSIC, // STREAM_DTMF 310212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent AudioSystem.STREAM_MUSIC // STREAM_TTS 311212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent }; 312212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent private final int[] STREAM_VOLUME_ALIAS_DEFAULT = new int[] { 3136d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent AudioSystem.STREAM_VOICE_CALL, // STREAM_VOICE_CALL 3144f0f120316cfcee5880191264885772677fff921John Spurlock AudioSystem.STREAM_RING, // STREAM_SYSTEM 3156d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent AudioSystem.STREAM_RING, // STREAM_RING 3166d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent AudioSystem.STREAM_MUSIC, // STREAM_MUSIC 3176d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent AudioSystem.STREAM_ALARM, // STREAM_ALARM 3186d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent AudioSystem.STREAM_RING, // STREAM_NOTIFICATION 3196d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent AudioSystem.STREAM_BLUETOOTH_SCO, // STREAM_BLUETOOTH_SCO 3204f0f120316cfcee5880191264885772677fff921John Spurlock AudioSystem.STREAM_RING, // STREAM_SYSTEM_ENFORCED 3214f0f120316cfcee5880191264885772677fff921John Spurlock AudioSystem.STREAM_RING, // STREAM_DTMF 3226d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent AudioSystem.STREAM_MUSIC // STREAM_TTS 3236d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent }; 3246d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent private int[] mStreamVolumeAlias; 325a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent 326ba50b97cff80e73620a0e3d13cae169e095974a7Dianne Hackborn /** 327ba50b97cff80e73620a0e3d13cae169e095974a7Dianne Hackborn * Map AudioSystem.STREAM_* constants to app ops. This should be used 328ba50b97cff80e73620a0e3d13cae169e095974a7Dianne Hackborn * after mapping through mStreamVolumeAlias. 329ba50b97cff80e73620a0e3d13cae169e095974a7Dianne Hackborn */ 330ba50b97cff80e73620a0e3d13cae169e095974a7Dianne Hackborn private static final int[] STEAM_VOLUME_OPS = new int[] { 331ba50b97cff80e73620a0e3d13cae169e095974a7Dianne Hackborn AppOpsManager.OP_AUDIO_VOICE_VOLUME, // STREAM_VOICE_CALL 332ba50b97cff80e73620a0e3d13cae169e095974a7Dianne Hackborn AppOpsManager.OP_AUDIO_MEDIA_VOLUME, // STREAM_SYSTEM 333ba50b97cff80e73620a0e3d13cae169e095974a7Dianne Hackborn AppOpsManager.OP_AUDIO_RING_VOLUME, // STREAM_RING 334ba50b97cff80e73620a0e3d13cae169e095974a7Dianne Hackborn AppOpsManager.OP_AUDIO_MEDIA_VOLUME, // STREAM_MUSIC 335ba50b97cff80e73620a0e3d13cae169e095974a7Dianne Hackborn AppOpsManager.OP_AUDIO_ALARM_VOLUME, // STREAM_ALARM 336ba50b97cff80e73620a0e3d13cae169e095974a7Dianne Hackborn AppOpsManager.OP_AUDIO_NOTIFICATION_VOLUME, // STREAM_NOTIFICATION 337ba50b97cff80e73620a0e3d13cae169e095974a7Dianne Hackborn AppOpsManager.OP_AUDIO_BLUETOOTH_VOLUME, // STREAM_BLUETOOTH_SCO 338ba50b97cff80e73620a0e3d13cae169e095974a7Dianne Hackborn AppOpsManager.OP_AUDIO_MEDIA_VOLUME, // STREAM_SYSTEM_ENFORCED 339ba50b97cff80e73620a0e3d13cae169e095974a7Dianne Hackborn AppOpsManager.OP_AUDIO_MEDIA_VOLUME, // STREAM_DTMF 340ba50b97cff80e73620a0e3d13cae169e095974a7Dianne Hackborn AppOpsManager.OP_AUDIO_MEDIA_VOLUME, // STREAM_TTS 341ba50b97cff80e73620a0e3d13cae169e095974a7Dianne Hackborn }; 342ba50b97cff80e73620a0e3d13cae169e095974a7Dianne Hackborn 34383a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent private final boolean mUseFixedVolume; 34483a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent 345bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent // stream names used by dumpStreamStates() 3461af30c7ac480e5d335f267a3ac3b2e6c748ce240John Spurlock private static final String[] STREAM_NAMES = new String[] { 347bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent "STREAM_VOICE_CALL", 348bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent "STREAM_SYSTEM", 349bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent "STREAM_RING", 350bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent "STREAM_MUSIC", 351bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent "STREAM_ALARM", 352bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent "STREAM_NOTIFICATION", 353bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent "STREAM_BLUETOOTH_SCO", 354bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent "STREAM_SYSTEM_ENFORCED", 355bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent "STREAM_DTMF", 356bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent "STREAM_TTS" 357bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent }; 358bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent 35930c918ce7fbe171944b28fc91b3f22b3d631872dGlenn Kasten private final AudioSystem.ErrorCallback mAudioSystemCallback = new AudioSystem.ErrorCallback() { 3609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void onError(int error) { 3619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project switch (error) { 3629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case AudioSystem.AUDIO_STATUS_SERVER_DIED: 363dfb881f96af7898151940a4bbc52e45e6043d38bEric Laurent sendMsg(mAudioHandler, MSG_MEDIA_SERVER_DIED, 364dfb881f96af7898151940a4bbc52e45e6043d38bEric Laurent SENDMSG_NOOP, 0, 0, null, 0); 3659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 3669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project default: 3679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 3689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 369dfb881f96af7898151940a4bbc52e45e6043d38bEric Laurent } 3709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project }; 3719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 3739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Current ringer mode from one of {@link AudioManager#RINGER_MODE_NORMAL}, 3749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link AudioManager#RINGER_MODE_SILENT}, or 3759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link AudioManager#RINGER_MODE_VIBRATE}. 3769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 377ba195ebc76f23b6679443724ab58c9dc9f2df884Glenn Kasten // protected by mSettingsLock 378661f2cf45860d2e10924e6b69966a9afe255f28bJohn Spurlock private int mRingerMode; // internal ringer mode, affects muting of underlying streams 379661f2cf45860d2e10924e6b69966a9afe255f28bJohn Spurlock private int mRingerModeExternal = -1; // reported ringer mode to outside clients (AudioManager) 3809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3819bcf401d13d47416043a704430388abd59aef7cdEric Laurent /** @see System#MODE_RINGER_STREAMS_AFFECTED */ 38224e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent private int mRingerModeAffectedStreams = 0; 3839bcf401d13d47416043a704430388abd59aef7cdEric Laurent 3845b4e654d0c7de8e4d58d73e73b0d5220f19b68f7Eric Laurent // Streams currently muted by ringer mode 3855b4e654d0c7de8e4d58d73e73b0d5220f19b68f7Eric Laurent private int mRingerModeMutedStreams; 3865b4e654d0c7de8e4d58d73e73b0d5220f19b68f7Eric Laurent 3879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** @see System#MUTE_STREAMS_AFFECTED */ 3889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private int mMuteAffectedStreams; 3899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 391bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent * NOTE: setVibrateSetting(), getVibrateSetting(), shouldVibrate() are deprecated. 392bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent * mVibrateSetting is just maintained during deprecation period but vibration policy is 393bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent * now only controlled by mHasVibrator and mRingerMode 3949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 3959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private int mVibrateSetting; 3969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 397bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent // Is there a vibrator 398bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent private final boolean mHasVibrator; 399bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent 400a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent // Broadcast receiver for device connections intent broadcasts 401a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent private final BroadcastReceiver mReceiver = new AudioServiceBroadcastReceiver(); 402a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent 403c42ac9d4d03f62c3a1ba197a28a81fda44bd8b7fEric Laurent // Devices currently connected 40430c918ce7fbe171944b28fc91b3f22b3d631872dGlenn Kasten private final HashMap <Integer, String> mConnectedDevices = new HashMap <Integer, String>(); 405c42ac9d4d03f62c3a1ba197a28a81fda44bd8b7fEric Laurent 406c42ac9d4d03f62c3a1ba197a28a81fda44bd8b7fEric Laurent // Forced device usage for communications 407c42ac9d4d03f62c3a1ba197a28a81fda44bd8b7fEric Laurent private int mForcedUseForComm; 408c42ac9d4d03f62c3a1ba197a28a81fda44bd8b7fEric Laurent 4090dc37cce9d564ae43883c8dc8672b9266b881e63Mike Lockwood // True if we have master volume support 4100dc37cce9d564ae43883c8dc8672b9266b881e63Mike Lockwood private final boolean mUseMasterVolume; 4110dc37cce9d564ae43883c8dc8672b9266b881e63Mike Lockwood 4129760647dd0ee67e7c20f3e9d661d2006b1df0b54Mike Lockwood private final int[] mMasterVolumeRamp; 4139760647dd0ee67e7c20f3e9d661d2006b1df0b54Mike Lockwood 4149272b4b4a44fe1f33e3030810618194f817caaecEric Laurent // List of binder death handlers for setMode() client processes. 4159272b4b4a44fe1f33e3030810618194f817caaecEric Laurent // The last process to have called setMode() is at the top of the list. 41630c918ce7fbe171944b28fc91b3f22b3d631872dGlenn Kasten private final ArrayList <SetModeDeathHandler> mSetModeDeathHandlers = new ArrayList <SetModeDeathHandler>(); 417eb14a783be073b5fd6e8c8c9bc87d2d1919f2c9eEric Laurent 4183def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent // List of clients having issued a SCO start request 41930c918ce7fbe171944b28fc91b3f22b3d631872dGlenn Kasten private final ArrayList <ScoClient> mScoClients = new ArrayList <ScoClient>(); 4203def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent 4213def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent // BluetoothHeadset API to control SCO connection 4223def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent private BluetoothHeadset mBluetoothHeadset; 4233def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent 42482aa7f017daaaeb96c13e6e3491d5037ab471085Jaikumar Ganesh // Bluetooth headset device 42582aa7f017daaaeb96c13e6e3491d5037ab471085Jaikumar Ganesh private BluetoothDevice mBluetoothHeadsetDevice; 4263def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent 42762ef767b15a712bab31cc0d5508a330906f535c2Eric Laurent // Indicate if SCO audio connection is currently active and if the initiator is 42862ef767b15a712bab31cc0d5508a330906f535c2Eric Laurent // audio service (internal) or bluetooth headset (external) 42962ef767b15a712bab31cc0d5508a330906f535c2Eric Laurent private int mScoAudioState; 43062ef767b15a712bab31cc0d5508a330906f535c2Eric Laurent // SCO audio state is not active 43162ef767b15a712bab31cc0d5508a330906f535c2Eric Laurent private static final int SCO_STATE_INACTIVE = 0; 432dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent // SCO audio activation request waiting for headset service to connect 433dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent private static final int SCO_STATE_ACTIVATE_REQ = 1; 43425fc29b3691a1d2a84164988dc74b2e7d301868eEric Laurent // SCO audio state is active or starting due to a request from AudioManager API 435dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent private static final int SCO_STATE_ACTIVE_INTERNAL = 3; 436dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent // SCO audio deactivation request waiting for headset service to connect 437dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent private static final int SCO_STATE_DEACTIVATE_REQ = 5; 438dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent 43962ef767b15a712bab31cc0d5508a330906f535c2Eric Laurent // SCO audio state is active due to an action in BT handsfree (either voice recognition or 44062ef767b15a712bab31cc0d5508a330906f535c2Eric Laurent // in call audio) 44162ef767b15a712bab31cc0d5508a330906f535c2Eric Laurent private static final int SCO_STATE_ACTIVE_EXTERNAL = 2; 442dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent // Deactivation request for all SCO connections (initiated by audio mode change) 443dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent // waiting for headset service to connect 444dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent private static final int SCO_STATE_DEACTIVATE_EXT_REQ = 4; 445dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent 446c18c9138cee0f0859bcab636a004ce92ca4a9ab5Eric Laurent // Indicates the mode used for SCO audio connection. The mode is virtual call if the request 447c18c9138cee0f0859bcab636a004ce92ca4a9ab5Eric Laurent // originated from an app targeting an API version before JB MR2 and raw audio after that. 448c18c9138cee0f0859bcab636a004ce92ca4a9ab5Eric Laurent private int mScoAudioMode; 449f4e51d82d2e34e6832903f01eaecc15ded6c3241Liejun Tao // SCO audio mode is undefined 450f4e51d82d2e34e6832903f01eaecc15ded6c3241Liejun Tao private static final int SCO_MODE_UNDEFINED = -1; 451c18c9138cee0f0859bcab636a004ce92ca4a9ab5Eric Laurent // SCO audio mode is virtual voice call (BluetoothHeadset.startScoUsingVirtualVoiceCall()) 452c18c9138cee0f0859bcab636a004ce92ca4a9ab5Eric Laurent private static final int SCO_MODE_VIRTUAL_CALL = 0; 453c18c9138cee0f0859bcab636a004ce92ca4a9ab5Eric Laurent // SCO audio mode is raw audio (BluetoothHeadset.connectAudio()) 454c18c9138cee0f0859bcab636a004ce92ca4a9ab5Eric Laurent private static final int SCO_MODE_RAW = 1; 455f4e51d82d2e34e6832903f01eaecc15ded6c3241Liejun Tao // SCO audio mode is Voice Recognition (BluetoothHeadset.startVoiceRecognition()) 456f4e51d82d2e34e6832903f01eaecc15ded6c3241Liejun Tao private static final int SCO_MODE_VR = 2; 457f4e51d82d2e34e6832903f01eaecc15ded6c3241Liejun Tao 458f4e51d82d2e34e6832903f01eaecc15ded6c3241Liejun Tao private static final int SCO_MODE_MAX = 2; 459c18c9138cee0f0859bcab636a004ce92ca4a9ab5Eric Laurent 460dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent // Current connection state indicated by bluetooth headset 461dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent private int mScoConnectionState; 46262ef767b15a712bab31cc0d5508a330906f535c2Eric Laurent 463a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent // true if boot sequence has been completed 4644a5eeb9c727d77bb57fef87a70c8c9cc23dbfee3Eric Laurent private boolean mSystemReady; 465a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent // listener for SoundPool sample load completion indication 466a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent private SoundPoolCallback mSoundPoolCallBack; 467a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent // thread for SoundPool listener 468a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent private SoundPoolListenerThread mSoundPoolListenerThread; 469a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent // message looper for SoundPool listener 470a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent private Looper mSoundPoolLooper = null; 471c55b393efd462490cd5e27fc373bceafdd25662eJean-Michel Trivi // volume applied to sound played with playSoundEffect() 472f2b0c11f4e797e183131261724d8de310dac5431Jean-Michel Trivi private static int sSoundEffectVolumeDb; 47325101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent // previous volume adjustment direction received by checkForRingerModeChange() 47425101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent private int mPrevVolDirection = AudioManager.ADJUST_SAME; 4756243edd818b84adfbe712d5d233d6414b33653acAmith Yamasani // Keyguard manager proxy 4766243edd818b84adfbe712d5d233d6414b33653acAmith Yamasani private KeyguardManager mKeyguardManager; 47745c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent // mVolumeControlStream is set by VolumePanel to temporarily force the stream type which volume 47845c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent // is controlled by Vol keys. 47945c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent private int mVolumeControlStream = -1; 48045c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent private final Object mForceControlStreamLock = new Object(); 48145c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent // VolumePanel is currently the only client of forceVolumeControlStream() and runs in system 48245c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent // server process so in theory it is not necessary to monitor the client death. 48345c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent // However it is good to be ready for future evolutions. 48445c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent private ForceControlStreamClient mForceControlStreamClient = null; 485098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey // Used to play ringtones outside system_server 486098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey private volatile IRingtonePlayer mRingtonePlayer; 4879bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent 488f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi private int mDeviceOrientation = Configuration.ORIENTATION_UNDEFINED; 489bb6f8711a7f804d39c45218db2d6339940cc5d35Jean-Michel Trivi private int mDeviceRotation = Surface.ROTATION_0; 490f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi 4917847211fb4699bf6018e29d214a918ed6657319bEric Laurent // Request to override default use of A2DP for media. 4927847211fb4699bf6018e29d214a918ed6657319bEric Laurent private boolean mBluetoothA2dpEnabled; 4937847211fb4699bf6018e29d214a918ed6657319bEric Laurent private final Object mBluetoothA2dpEnabledLock = new Object(); 4947847211fb4699bf6018e29d214a918ed6657319bEric Laurent 495632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn // Monitoring of audio routes. Protected by mCurAudioRoutes. 496632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn final AudioRoutesInfo mCurAudioRoutes = new AudioRoutesInfo(); 497632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn final RemoteCallbackList<IAudioRoutesObserver> mRoutesObservers 498632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn = new RemoteCallbackList<IAudioRoutesObserver>(); 499632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn 5004bbcc6549738f3d69831b2bd9eb4accec3e9920eEric Laurent // Devices for which the volume is fixed and VolumePanel slider should be disabled 501212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent int mFixedVolumeDevices = AudioSystem.DEVICE_OUT_HDMI | 5024bbcc6549738f3d69831b2bd9eb4accec3e9920eEric Laurent AudioSystem.DEVICE_OUT_DGTL_DOCK_HEADSET | 503212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent AudioSystem.DEVICE_OUT_ANLG_DOCK_HEADSET | 504212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent AudioSystem.DEVICE_OUT_HDMI_ARC | 505212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent AudioSystem.DEVICE_OUT_SPDIF | 506212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent AudioSystem.DEVICE_OUT_AUX_LINE; 507ba5270b88798c66fefc17a1b25b27894e4fb7862Jean-Michel Trivi int mFullVolumeDevices = 0; 5084bbcc6549738f3d69831b2bd9eb4accec3e9920eEric Laurent 509bb6f8711a7f804d39c45218db2d6339940cc5d35Jean-Michel Trivi // TODO merge orientation and rotation 510d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent private final boolean mMonitorOrientation; 511bb6f8711a7f804d39c45218db2d6339940cc5d35Jean-Michel Trivi private final boolean mMonitorRotation; 512d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent 5137ee1e4ff7346a278a6722108fbc1869240b3e866Eric Laurent private boolean mDockAudioMediaEnabled = true; 5147ee1e4ff7346a278a6722108fbc1869240b3e866Eric Laurent 51508ed1b9d2099ec8231b21353b33b901492ea9885Eric Laurent private int mDockState = Intent.EXTRA_DOCK_STATE_UNDOCKED; 51608ed1b9d2099ec8231b21353b33b901492ea9885Eric Laurent 517fde16d5879ea88a971004c984093409468b6139cEric Laurent // Used when safe volume warning message display is requested by setStreamVolume(). In this 518fde16d5879ea88a971004c984093409468b6139cEric Laurent // case, the new requested volume, stream type and device are stored in mPendingVolumeCommand 519fde16d5879ea88a971004c984093409468b6139cEric Laurent // and used later when/if disableSafeMediaVolume() is called. 520fde16d5879ea88a971004c984093409468b6139cEric Laurent private StreamVolumeCommand mPendingVolumeCommand; 521fde16d5879ea88a971004c984093409468b6139cEric Laurent 522fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi private PowerManager.WakeLock mAudioEventWakeLock; 523fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi 524fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi private final MediaFocusControl mMediaFocusControl; 525fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi 5265a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du // Reference to BluetoothA2dp to query for AbsoluteVolume. 5275a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du private BluetoothA2dp mA2dp; 5285a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du private final Object mA2dpAvrcpLock = new Object(); 5295a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du // If absolute volume is supported in AVRCP device 5305a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du private boolean mAvrcpAbsVolSupported = false; 5315a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du 532318f0fe43bdc4b2f6764edd91d6b78d9875ffdebJon Eklund private AudioOrientationEventListener mOrientationListener; 533318f0fe43bdc4b2f6764edd91d6b78d9875ffdebJon Eklund 534adbe8bf85f3c8230d16ae5cb3f5d9736e09ed84aEric Laurent private static Long mLastDeviceConnectMsgTime = new Long(0); 535adbe8bf85f3c8230d16ae5cb3f5d9736e09ed84aEric Laurent 536661f2cf45860d2e10924e6b69966a9afe255f28bJohn Spurlock private AudioManagerInternal.RingerModeDelegate mRingerModeDelegate; 537661f2cf45860d2e10924e6b69966a9afe255f28bJohn Spurlock 5389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /////////////////////////////////////////////////////////////////////////// 5399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Construction 5409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /////////////////////////////////////////////////////////////////////////// 5419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** @hide */ 5439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public AudioService(Context context) { 5449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext = context; 5459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContentResolver = context.getContentResolver(); 546ba50b97cff80e73620a0e3d13cae169e095974a7Dianne Hackborn mAppOps = (AppOpsManager)context.getSystemService(Context.APP_OPS_SERVICE); 547212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent 548212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent if (mContext.getResources().getBoolean( 549212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent com.android.internal.R.bool.config_voice_capable)) { 550212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent mPlatformType = PLATFORM_VOICE; 551212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent } else if (context.getPackageManager().hasSystemFeature( 5520b03f9909be438f45b32ce2a6a2c2c5208a82cc9Eric Laurent PackageManager.FEATURE_LEANBACK)) { 553212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent mPlatformType = PLATFORM_TELEVISION; 554212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent } else { 555212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent mPlatformType = PLATFORM_DEFAULT; 556212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent } 5575982013cfc8274ff0bafaba83c676b3a8890cba9Jared Suttles 558c68022258ebd3dd97a5079ba99f4f3cd12b223b0Jean-Michel Trivi PowerManager pm = (PowerManager)context.getSystemService(Context.POWER_SERVICE); 559fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi mAudioEventWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "handleAudioEvent"); 560c68022258ebd3dd97a5079ba99f4f3cd12b223b0Jean-Michel Trivi 561bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent Vibrator vibrator = (Vibrator) context.getSystemService(Context.VIBRATOR_SERVICE); 562bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent mHasVibrator = vibrator == null ? false : vibrator.hasVibrator(); 563bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent 5645982013cfc8274ff0bafaba83c676b3a8890cba9Jared Suttles // Intialized volume 56591377de6f23af2b0b08adae22810cae6fc35cb1aEric Laurent int maxVolume = SystemProperties.getInt("ro.config.vc_call_vol_steps", 56691377de6f23af2b0b08adae22810cae6fc35cb1aEric Laurent MAX_STREAM_VOLUME[AudioSystem.STREAM_VOICE_CALL]); 56791377de6f23af2b0b08adae22810cae6fc35cb1aEric Laurent if (maxVolume != MAX_STREAM_VOLUME[AudioSystem.STREAM_VOICE_CALL]) { 56891377de6f23af2b0b08adae22810cae6fc35cb1aEric Laurent MAX_STREAM_VOLUME[AudioSystem.STREAM_VOICE_CALL] = maxVolume; 56991377de6f23af2b0b08adae22810cae6fc35cb1aEric Laurent DEFAULT_STREAM_VOLUME[AudioSystem.STREAM_VOICE_CALL] = (maxVolume * 3) / 4; 57091377de6f23af2b0b08adae22810cae6fc35cb1aEric Laurent } 57191377de6f23af2b0b08adae22810cae6fc35cb1aEric Laurent maxVolume = SystemProperties.getInt("ro.config.media_vol_steps", 57291377de6f23af2b0b08adae22810cae6fc35cb1aEric Laurent MAX_STREAM_VOLUME[AudioSystem.STREAM_MUSIC]); 57391377de6f23af2b0b08adae22810cae6fc35cb1aEric Laurent if (maxVolume != MAX_STREAM_VOLUME[AudioSystem.STREAM_MUSIC]) { 57491377de6f23af2b0b08adae22810cae6fc35cb1aEric Laurent MAX_STREAM_VOLUME[AudioSystem.STREAM_MUSIC] = maxVolume; 57591377de6f23af2b0b08adae22810cae6fc35cb1aEric Laurent DEFAULT_STREAM_VOLUME[AudioSystem.STREAM_MUSIC] = (maxVolume * 3) / 4; 57691377de6f23af2b0b08adae22810cae6fc35cb1aEric Laurent } 5775982013cfc8274ff0bafaba83c676b3a8890cba9Jared Suttles 578f2b0c11f4e797e183131261724d8de310dac5431Jean-Michel Trivi sSoundEffectVolumeDb = context.getResources().getInteger( 579c55b393efd462490cd5e27fc373bceafdd25662eJean-Michel Trivi com.android.internal.R.integer.config_soundEffectVolumeDb); 58025101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent 581c42ac9d4d03f62c3a1ba197a28a81fda44bd8b7fEric Laurent mForcedUseForComm = AudioSystem.FORCE_NONE; 582dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent 5839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project createAudioSystemThread(); 584dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent 585fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi mMediaFocusControl = new MediaFocusControl(mAudioHandler.getLooper(), 5863346a802087f621c6441bc512dfcc17b07143fc6John Spurlock mContext, mVolumeController, this); 587fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi 588dfb881f96af7898151940a4bbc52e45e6043d38bEric Laurent AudioSystem.setErrorCallback(mAudioSystemCallback); 589dfb881f96af7898151940a4bbc52e45e6043d38bEric Laurent 590dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent boolean cameraSoundForced = mContext.getResources().getBoolean( 591dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent com.android.internal.R.bool.config_camera_sound_forced); 592dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent mCameraSoundForced = new Boolean(cameraSoundForced); 593dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent sendMsg(mAudioHandler, 594dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent MSG_SET_FORCE_USE, 595dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent SENDMSG_QUEUE, 596dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent AudioSystem.FOR_SYSTEM, 597dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent cameraSoundForced ? 598dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent AudioSystem.FORCE_SYSTEM_ENFORCED : AudioSystem.FORCE_NONE, 599dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent null, 600dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent 0); 601dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent 60205274f348e12983eb8613cc6eb9ae561e8197e28Eric Laurent mSafeMediaVolumeState = new Integer(Settings.Global.getInt(mContentResolver, 60305274f348e12983eb8613cc6eb9ae561e8197e28Eric Laurent Settings.Global.AUDIO_SAFE_VOLUME_STATE, 60405274f348e12983eb8613cc6eb9ae561e8197e28Eric Laurent SAFE_MEDIA_VOLUME_NOT_CONFIGURED)); 60505274f348e12983eb8613cc6eb9ae561e8197e28Eric Laurent // The default safe volume index read here will be replaced by the actual value when 60605274f348e12983eb8613cc6eb9ae561e8197e28Eric Laurent // the mcc is read by onConfigureSafeVolume() 60705274f348e12983eb8613cc6eb9ae561e8197e28Eric Laurent mSafeMediaVolumeIndex = mContext.getResources().getInteger( 60805274f348e12983eb8613cc6eb9ae561e8197e28Eric Laurent com.android.internal.R.integer.config_safe_media_volume_index) * 10; 60905274f348e12983eb8613cc6eb9ae561e8197e28Eric Laurent 61083a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent mUseFixedVolume = mContext.getResources().getBoolean( 61183a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent com.android.internal.R.bool.config_useFixedVolume); 612da39290460b30e5080769f039d6dff352b3c7808Wally Yau mUseMasterVolume = context.getResources().getBoolean( 613da39290460b30e5080769f039d6dff352b3c7808Wally Yau com.android.internal.R.bool.config_useMasterVolume); 614da39290460b30e5080769f039d6dff352b3c7808Wally Yau mMasterVolumeRamp = context.getResources().getIntArray( 615da39290460b30e5080769f039d6dff352b3c7808Wally Yau com.android.internal.R.array.config_masterVolumeRamp); 61683a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent 61724e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent // must be called before readPersistedSettings() which needs a valid mStreamVolumeAlias[] 61824e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent // array initialized by updateStreamVolumeAlias() 61924e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent updateStreamVolumeAlias(false /*updateVolumes*/); 6209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project readPersistedSettings(); 621c1d4166289ce016965d1147f7e8d37862ee347ecEric Laurent mSettingsObserver = new SettingsObserver(); 622a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent createStreamStates(); 6239f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent 624fd116ad1ab02f6060a0b2201f018317fa32e28b4Glenn Kasten readAndSetLowRamDevice(); 6253891c4cc918e8062abb97c542a8625d556dccc59Eric Laurent 6263891c4cc918e8062abb97c542a8625d556dccc59Eric Laurent // Call setRingerModeInt() to apply correct mute 6273891c4cc918e8062abb97c542a8625d556dccc59Eric Laurent // state on streams affected by ringer mode. 6283891c4cc918e8062abb97c542a8625d556dccc59Eric Laurent mRingerModeMutedStreams = 0; 629661f2cf45860d2e10924e6b69966a9afe255f28bJohn Spurlock setRingerModeInt(getRingerModeInternal(), false); 6303891c4cc918e8062abb97c542a8625d556dccc59Eric Laurent 631a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent // Register for device connection intent broadcasts. 632a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent IntentFilter intentFilter = 633b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent new IntentFilter(BluetoothHeadset.ACTION_AUDIO_STATE_CHANGED); 63482aa7f017daaaeb96c13e6e3491d5037ab471085Jaikumar Ganesh intentFilter.addAction(BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED); 63582aa7f017daaaeb96c13e6e3491d5037ab471085Jaikumar Ganesh intentFilter.addAction(Intent.ACTION_DOCK_EVENT); 636c5258433dd353769ccfa2e5e769a7379378a3a0bJean-Michel Trivi intentFilter.addAction(AudioManager.ACTION_USB_AUDIO_ACCESSORY_PLUG); 637c5258433dd353769ccfa2e5e769a7379378a3a0bJean-Michel Trivi intentFilter.addAction(AudioManager.ACTION_USB_AUDIO_DEVICE_PLUG); 638950e8cb40a6d826af4cc2eef9d3908c1b70486e6Eric Laurent intentFilter.addAction(Intent.ACTION_SCREEN_ON); 639950e8cb40a6d826af4cc2eef9d3908c1b70486e6Eric Laurent intentFilter.addAction(Intent.ACTION_SCREEN_OFF); 640bc0fab1fc2db832ef86d8a33466ec4d68b103ca0Eric Laurent intentFilter.addAction(Intent.ACTION_USER_SWITCHED); 641c837a451946b64d70ed7c642fbde03c182c28b6fPaul McLean intentFilter.addAction(UsbManager.ACTION_USB_DEVICE_ATTACHED); 642f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi 643d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent intentFilter.addAction(Intent.ACTION_CONFIGURATION_CHANGED); 644bb6f8711a7f804d39c45218db2d6339940cc5d35Jean-Michel Trivi // TODO merge orientation and rotation 645d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent mMonitorOrientation = SystemProperties.getBoolean("ro.audio.monitorOrientation", false); 646d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent if (mMonitorOrientation) { 647f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi Log.v(TAG, "monitoring device orientation"); 648f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi // initialize orientation in AudioSystem 649f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi setOrientationForAudioSystem(); 650f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi } 651bb6f8711a7f804d39c45218db2d6339940cc5d35Jean-Michel Trivi mMonitorRotation = SystemProperties.getBoolean("ro.audio.monitorRotation", false); 652bb6f8711a7f804d39c45218db2d6339940cc5d35Jean-Michel Trivi if (mMonitorRotation) { 653bb6f8711a7f804d39c45218db2d6339940cc5d35Jean-Michel Trivi mDeviceRotation = ((WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE)) 654bb6f8711a7f804d39c45218db2d6339940cc5d35Jean-Michel Trivi .getDefaultDisplay().getRotation(); 655bb6f8711a7f804d39c45218db2d6339940cc5d35Jean-Michel Trivi Log.v(TAG, "monitoring device rotation, initial=" + mDeviceRotation); 656318f0fe43bdc4b2f6764edd91d6b78d9875ffdebJon Eklund 657318f0fe43bdc4b2f6764edd91d6b78d9875ffdebJon Eklund mOrientationListener = new AudioOrientationEventListener(mContext); 658318f0fe43bdc4b2f6764edd91d6b78d9875ffdebJon Eklund mOrientationListener.enable(); 659318f0fe43bdc4b2f6764edd91d6b78d9875ffdebJon Eklund 660bb6f8711a7f804d39c45218db2d6339940cc5d35Jean-Michel Trivi // initialize rotation in AudioSystem 661bb6f8711a7f804d39c45218db2d6339940cc5d35Jean-Michel Trivi setRotationForAudioSystem(); 662bb6f8711a7f804d39c45218db2d6339940cc5d35Jean-Michel Trivi } 663f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi 664a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent context.registerReceiver(mReceiver, intentFilter); 6655982013cfc8274ff0bafaba83c676b3a8890cba9Jared Suttles 6669063154a793b0ab38b3c5992cbaed046427b4a82Mike Lockwood restoreMasterVolume(); 6679760647dd0ee67e7c20f3e9d661d2006b1df0b54Mike Lockwood 6680dac35af2c6aa42bcd181981b041747cfd1afa5fRoboErik LocalServices.addService(AudioManagerInternal.class, new AudioServiceInternal()); 6699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6714a5eeb9c727d77bb57fef87a70c8c9cc23dbfee3Eric Laurent public void systemReady() { 6724a5eeb9c727d77bb57fef87a70c8c9cc23dbfee3Eric Laurent sendMsg(mAudioHandler, MSG_SYSTEM_READY, SENDMSG_QUEUE, 6734a5eeb9c727d77bb57fef87a70c8c9cc23dbfee3Eric Laurent 0, 0, null, 0); 6744a5eeb9c727d77bb57fef87a70c8c9cc23dbfee3Eric Laurent } 6754a5eeb9c727d77bb57fef87a70c8c9cc23dbfee3Eric Laurent 6764a5eeb9c727d77bb57fef87a70c8c9cc23dbfee3Eric Laurent public void onSystemReady() { 6774a5eeb9c727d77bb57fef87a70c8c9cc23dbfee3Eric Laurent mSystemReady = true; 6784a5eeb9c727d77bb57fef87a70c8c9cc23dbfee3Eric Laurent sendMsg(mAudioHandler, MSG_LOAD_SOUND_EFFECTS, SENDMSG_QUEUE, 6794a5eeb9c727d77bb57fef87a70c8c9cc23dbfee3Eric Laurent 0, 0, null, 0); 6804a5eeb9c727d77bb57fef87a70c8c9cc23dbfee3Eric Laurent 6814a5eeb9c727d77bb57fef87a70c8c9cc23dbfee3Eric Laurent mKeyguardManager = 6824a5eeb9c727d77bb57fef87a70c8c9cc23dbfee3Eric Laurent (KeyguardManager) mContext.getSystemService(Context.KEYGUARD_SERVICE); 6834a5eeb9c727d77bb57fef87a70c8c9cc23dbfee3Eric Laurent mScoConnectionState = AudioManager.SCO_AUDIO_STATE_ERROR; 6844a5eeb9c727d77bb57fef87a70c8c9cc23dbfee3Eric Laurent resetBluetoothSco(); 6854a5eeb9c727d77bb57fef87a70c8c9cc23dbfee3Eric Laurent getBluetoothHeadset(); 6864a5eeb9c727d77bb57fef87a70c8c9cc23dbfee3Eric Laurent //FIXME: this is to maintain compatibility with deprecated intent 6874a5eeb9c727d77bb57fef87a70c8c9cc23dbfee3Eric Laurent // AudioManager.ACTION_SCO_AUDIO_STATE_CHANGED. Remove when appropriate. 6884a5eeb9c727d77bb57fef87a70c8c9cc23dbfee3Eric Laurent Intent newIntent = new Intent(AudioManager.ACTION_SCO_AUDIO_STATE_CHANGED); 6894a5eeb9c727d77bb57fef87a70c8c9cc23dbfee3Eric Laurent newIntent.putExtra(AudioManager.EXTRA_SCO_AUDIO_STATE, 6904a5eeb9c727d77bb57fef87a70c8c9cc23dbfee3Eric Laurent AudioManager.SCO_AUDIO_STATE_DISCONNECTED); 6914a5eeb9c727d77bb57fef87a70c8c9cc23dbfee3Eric Laurent sendStickyBroadcastToAll(newIntent); 6924a5eeb9c727d77bb57fef87a70c8c9cc23dbfee3Eric Laurent 6934a5eeb9c727d77bb57fef87a70c8c9cc23dbfee3Eric Laurent BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter(); 6944a5eeb9c727d77bb57fef87a70c8c9cc23dbfee3Eric Laurent if (adapter != null) { 6954a5eeb9c727d77bb57fef87a70c8c9cc23dbfee3Eric Laurent adapter.getProfileProxy(mContext, mBluetoothProfileServiceListener, 6964a5eeb9c727d77bb57fef87a70c8c9cc23dbfee3Eric Laurent BluetoothProfile.A2DP); 6974a5eeb9c727d77bb57fef87a70c8c9cc23dbfee3Eric Laurent } 6984a5eeb9c727d77bb57fef87a70c8c9cc23dbfee3Eric Laurent 699212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent mHdmiManager = 7007f4342e5b8e086fc96a4cb4d6df7e4d0bd3256baWonsik Kim (HdmiControlManager) mContext.getSystemService(Context.HDMI_CONTROL_SERVICE); 701212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent if (mHdmiManager != null) { 702212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent synchronized (mHdmiManager) { 703212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent mHdmiTvClient = mHdmiManager.getTvClient(); 704c9ff968787d4744194f9985ebaf8ce7efdd12256Jungshik Jang if (mHdmiTvClient != null) { 705c9ff968787d4744194f9985ebaf8ce7efdd12256Jungshik Jang mFixedVolumeDevices &= ~AudioSystem.DEVICE_ALL_HDMI_SYSTEM_AUDIO_AND_SPEAKER; 706c9ff968787d4744194f9985ebaf8ce7efdd12256Jungshik Jang } 707212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent mHdmiPlaybackClient = mHdmiManager.getPlaybackClient(); 708212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent mHdmiCecSink = false; 709212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent } 710212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent } 7117f4342e5b8e086fc96a4cb4d6df7e4d0bd3256baWonsik Kim 7124a5eeb9c727d77bb57fef87a70c8c9cc23dbfee3Eric Laurent sendMsg(mAudioHandler, 7134a5eeb9c727d77bb57fef87a70c8c9cc23dbfee3Eric Laurent MSG_CONFIGURE_SAFE_MEDIA_VOLUME_FORCED, 7144a5eeb9c727d77bb57fef87a70c8c9cc23dbfee3Eric Laurent SENDMSG_REPLACE, 7154a5eeb9c727d77bb57fef87a70c8c9cc23dbfee3Eric Laurent 0, 7164a5eeb9c727d77bb57fef87a70c8c9cc23dbfee3Eric Laurent 0, 7174a5eeb9c727d77bb57fef87a70c8c9cc23dbfee3Eric Laurent null, 7184a5eeb9c727d77bb57fef87a70c8c9cc23dbfee3Eric Laurent SAFE_VOLUME_CONFIGURE_TIMEOUT_MS); 719873cc45da2463a11182fe94a2565364d7e1709bbJean-Michel Trivi 720873cc45da2463a11182fe94a2565364d7e1709bbJean-Michel Trivi StreamOverride.init(mContext); 7214a5eeb9c727d77bb57fef87a70c8c9cc23dbfee3Eric Laurent } 7224a5eeb9c727d77bb57fef87a70c8c9cc23dbfee3Eric Laurent 7239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private void createAudioSystemThread() { 7249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mAudioSystemThread = new AudioSystemThread(); 7259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mAudioSystemThread.start(); 7269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project waitForAudioHandlerCreation(); 7279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** Waits for the volume handler to be created by the other thread. */ 7309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private void waitForAudioHandlerCreation() { 7319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project synchronized(this) { 7329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project while (mAudioHandler == null) { 7339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 7349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Wait for mAudioHandler to be set by the other thread 7359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project wait(); 7369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } catch (InterruptedException e) { 7379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Log.e(TAG, "Interrupted while waiting on volume handler."); 7389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 743244820185269991186d07068b92985624cede4a5Eric Laurent private void checkAllAliasStreamVolumes() { 7448fa4d6f585f40ff5cf5f9bed316d92c64a306f21Eric Laurent synchronized (VolumeStreamState.class) { 7458fa4d6f585f40ff5cf5f9bed316d92c64a306f21Eric Laurent int numStreamTypes = AudioSystem.getNumStreamTypes(); 7468fa4d6f585f40ff5cf5f9bed316d92c64a306f21Eric Laurent for (int streamType = 0; streamType < numStreamTypes; streamType++) { 7478fa4d6f585f40ff5cf5f9bed316d92c64a306f21Eric Laurent if (streamType != mStreamVolumeAlias[streamType]) { 7488fa4d6f585f40ff5cf5f9bed316d92c64a306f21Eric Laurent mStreamStates[streamType]. 74942b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent setAllIndexes(mStreamStates[mStreamVolumeAlias[streamType]]); 7508fa4d6f585f40ff5cf5f9bed316d92c64a306f21Eric Laurent } 7518fa4d6f585f40ff5cf5f9bed316d92c64a306f21Eric Laurent // apply stream volume 7528fa4d6f585f40ff5cf5f9bed316d92c64a306f21Eric Laurent if (!mStreamStates[streamType].isMuted_syncVSS()) { 7538fa4d6f585f40ff5cf5f9bed316d92c64a306f21Eric Laurent mStreamStates[streamType].applyAllVolumes(); 7548fa4d6f585f40ff5cf5f9bed316d92c64a306f21Eric Laurent } 755244820185269991186d07068b92985624cede4a5Eric Laurent } 756244820185269991186d07068b92985624cede4a5Eric Laurent } 757244820185269991186d07068b92985624cede4a5Eric Laurent } 758244820185269991186d07068b92985624cede4a5Eric Laurent 759212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent private void checkAllFixedVolumeDevices() 760212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent { 761212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent int numStreamTypes = AudioSystem.getNumStreamTypes(); 762212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent for (int streamType = 0; streamType < numStreamTypes; streamType++) { 763212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent mStreamStates[streamType].checkFixedVolumeDevices(); 764212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent } 765212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent } 766212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent 767ba5270b88798c66fefc17a1b25b27894e4fb7862Jean-Michel Trivi private void checkAllFixedVolumeDevices(int streamType) { 768ba5270b88798c66fefc17a1b25b27894e4fb7862Jean-Michel Trivi mStreamStates[streamType].checkFixedVolumeDevices(); 769ba5270b88798c66fefc17a1b25b27894e4fb7862Jean-Michel Trivi } 770ba5270b88798c66fefc17a1b25b27894e4fb7862Jean-Michel Trivi 7719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private void createStreamStates() { 7729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int numStreamTypes = AudioSystem.getNumStreamTypes(); 7739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project VolumeStreamState[] streams = mStreamStates = new VolumeStreamState[numStreamTypes]; 7749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = 0; i < numStreamTypes; i++) { 7766d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent streams[i] = new VolumeStreamState(System.VOLUME_SETTINGS[mStreamVolumeAlias[i]], i); 7779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 779212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent checkAllFixedVolumeDevices(); 780244820185269991186d07068b92985624cede4a5Eric Laurent checkAllAliasStreamVolumes(); 7819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 783bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent private void dumpStreamStates(PrintWriter pw) { 784bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent pw.println("\nStream volumes (device: index)"); 785bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent int numStreamTypes = AudioSystem.getNumStreamTypes(); 786bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent for (int i = 0; i < numStreamTypes; i++) { 787bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent pw.println("- "+STREAM_NAMES[i]+":"); 788bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent mStreamStates[i].dump(pw); 789bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent pw.println(""); 790bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent } 791dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent pw.print("\n- mute affected streams = 0x"); 792dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent pw.println(Integer.toHexString(mMuteAffectedStreams)); 793bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent } 794bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent 7951af30c7ac480e5d335f267a3ac3b2e6c748ce240John Spurlock /** @hide */ 7961af30c7ac480e5d335f267a3ac3b2e6c748ce240John Spurlock public static String streamToString(int stream) { 7971af30c7ac480e5d335f267a3ac3b2e6c748ce240John Spurlock if (stream >= 0 && stream < STREAM_NAMES.length) return STREAM_NAMES[stream]; 7981af30c7ac480e5d335f267a3ac3b2e6c748ce240John Spurlock if (stream == AudioManager.USE_DEFAULT_STREAM_TYPE) return "USE_DEFAULT_STREAM_TYPE"; 7991af30c7ac480e5d335f267a3ac3b2e6c748ce240John Spurlock return "UNKNOWN_STREAM_" + stream; 8001af30c7ac480e5d335f267a3ac3b2e6c748ce240John Spurlock } 8016d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent 8026d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent private void updateStreamVolumeAlias(boolean updateVolumes) { 8036d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent int dtmfStreamAlias; 804212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent 805212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent switch (mPlatformType) { 806212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent case PLATFORM_VOICE: 807212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent mStreamVolumeAlias = STREAM_VOLUME_ALIAS_VOICE; 8086d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent dtmfStreamAlias = AudioSystem.STREAM_RING; 809212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent break; 810212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent case PLATFORM_TELEVISION: 811212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent mStreamVolumeAlias = STREAM_VOLUME_ALIAS_TELEVISION; 812212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent dtmfStreamAlias = AudioSystem.STREAM_MUSIC; 813212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent break; 814212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent default: 815212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent mStreamVolumeAlias = STREAM_VOLUME_ALIAS_DEFAULT; 8166d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent dtmfStreamAlias = AudioSystem.STREAM_MUSIC; 8176d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent } 818212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent 819212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent if (isPlatformTelevision()) { 820212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent mRingerModeAffectedStreams = 0; 82124e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent } else { 822212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent if (isInCommunication()) { 823212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent dtmfStreamAlias = AudioSystem.STREAM_VOICE_CALL; 824212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent mRingerModeAffectedStreams &= ~(1 << AudioSystem.STREAM_DTMF); 825212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent } else { 826212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent mRingerModeAffectedStreams |= (1 << AudioSystem.STREAM_DTMF); 827212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent } 8286d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent } 829212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent 8306d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent mStreamVolumeAlias[AudioSystem.STREAM_DTMF] = dtmfStreamAlias; 8316d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent if (updateVolumes) { 83242b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent mStreamStates[AudioSystem.STREAM_DTMF].setAllIndexes(mStreamStates[dtmfStreamAlias]); 83324e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent // apply stream mute states according to new value of mRingerModeAffectedStreams 834661f2cf45860d2e10924e6b69966a9afe255f28bJohn Spurlock setRingerModeInt(getRingerModeInternal(), false); 8356d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent sendMsg(mAudioHandler, 8366d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent MSG_SET_ALL_VOLUMES, 8376d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent SENDMSG_QUEUE, 8386d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent 0, 8396d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent 0, 8406d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent mStreamStates[AudioSystem.STREAM_DTMF], 0); 8416d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent } 8426d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent } 8436d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent 8447ee1e4ff7346a278a6722108fbc1869240b3e866Eric Laurent private void readDockAudioSettings(ContentResolver cr) 8457ee1e4ff7346a278a6722108fbc1869240b3e866Eric Laurent { 8467ee1e4ff7346a278a6722108fbc1869240b3e866Eric Laurent mDockAudioMediaEnabled = Settings.Global.getInt( 8475ba0ffa0237a5c300545e4c72591613c6e5b2ed9Eric Laurent cr, Settings.Global.DOCK_AUDIO_MEDIA_ENABLED, 0) == 1; 8487ee1e4ff7346a278a6722108fbc1869240b3e866Eric Laurent 8497ee1e4ff7346a278a6722108fbc1869240b3e866Eric Laurent if (mDockAudioMediaEnabled) { 8507ee1e4ff7346a278a6722108fbc1869240b3e866Eric Laurent mBecomingNoisyIntentDevices |= AudioSystem.DEVICE_OUT_ANLG_DOCK_HEADSET; 8517ee1e4ff7346a278a6722108fbc1869240b3e866Eric Laurent } else { 8527ee1e4ff7346a278a6722108fbc1869240b3e866Eric Laurent mBecomingNoisyIntentDevices &= ~AudioSystem.DEVICE_OUT_ANLG_DOCK_HEADSET; 8537ee1e4ff7346a278a6722108fbc1869240b3e866Eric Laurent } 8547ee1e4ff7346a278a6722108fbc1869240b3e866Eric Laurent 8557ee1e4ff7346a278a6722108fbc1869240b3e866Eric Laurent sendMsg(mAudioHandler, 8567ee1e4ff7346a278a6722108fbc1869240b3e866Eric Laurent MSG_SET_FORCE_USE, 8577ee1e4ff7346a278a6722108fbc1869240b3e866Eric Laurent SENDMSG_QUEUE, 8587ee1e4ff7346a278a6722108fbc1869240b3e866Eric Laurent AudioSystem.FOR_DOCK, 8597ee1e4ff7346a278a6722108fbc1869240b3e866Eric Laurent mDockAudioMediaEnabled ? 8607ee1e4ff7346a278a6722108fbc1869240b3e866Eric Laurent AudioSystem.FORCE_ANALOG_DOCK : AudioSystem.FORCE_NONE, 8617ee1e4ff7346a278a6722108fbc1869240b3e866Eric Laurent null, 8627ee1e4ff7346a278a6722108fbc1869240b3e866Eric Laurent 0); 8637ee1e4ff7346a278a6722108fbc1869240b3e866Eric Laurent } 8647ee1e4ff7346a278a6722108fbc1869240b3e866Eric Laurent 8659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private void readPersistedSettings() { 8669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final ContentResolver cr = mContentResolver; 8679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 868bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent int ringerModeFromSettings = 8698d9a1f66d9d3dbbd45a56d441a746ec11dba7645Jeff Sharkey Settings.Global.getInt( 8708d9a1f66d9d3dbbd45a56d441a746ec11dba7645Jeff Sharkey cr, Settings.Global.MODE_RINGER, AudioManager.RINGER_MODE_NORMAL); 871bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent int ringerMode = ringerModeFromSettings; 87272668b2c040b581b298b069f3b5af5ed7f212d89Eric Laurent // sanity check in case the settings are restored from a device with incompatible 87372668b2c040b581b298b069f3b5af5ed7f212d89Eric Laurent // ringer modes 8749755937ed90f06db45ff5fe4510950ae1516f8f9John Spurlock if (!isValidRingerMode(ringerMode)) { 875ba195ebc76f23b6679443724ab58c9dc9f2df884Glenn Kasten ringerMode = AudioManager.RINGER_MODE_NORMAL; 876bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent } 877bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent if ((ringerMode == AudioManager.RINGER_MODE_VIBRATE) && !mHasVibrator) { 878bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent ringerMode = AudioManager.RINGER_MODE_SILENT; 879bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent } 880bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent if (ringerMode != ringerModeFromSettings) { 8818d9a1f66d9d3dbbd45a56d441a746ec11dba7645Jeff Sharkey Settings.Global.putInt(cr, Settings.Global.MODE_RINGER, ringerMode); 882ba195ebc76f23b6679443724ab58c9dc9f2df884Glenn Kasten } 883212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent if (mUseFixedVolume || isPlatformTelevision()) { 88483a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent ringerMode = AudioManager.RINGER_MODE_NORMAL; 88583a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent } 886ba195ebc76f23b6679443724ab58c9dc9f2df884Glenn Kasten synchronized(mSettingsLock) { 887ba195ebc76f23b6679443724ab58c9dc9f2df884Glenn Kasten mRingerMode = ringerMode; 888661f2cf45860d2e10924e6b69966a9afe255f28bJohn Spurlock if (mRingerModeExternal == -1) { 889661f2cf45860d2e10924e6b69966a9afe255f28bJohn Spurlock mRingerModeExternal = mRingerMode; 890661f2cf45860d2e10924e6b69966a9afe255f28bJohn Spurlock } 8919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 892dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent // System.VIBRATE_ON is not used any more but defaults for mVibrateSetting 893dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent // are still needed while setVibrateSetting() and getVibrateSetting() are being 894dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent // deprecated. 895dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent mVibrateSetting = getValueForVibrateSetting(0, 896dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent AudioManager.VIBRATE_TYPE_NOTIFICATION, 897dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent mHasVibrator ? AudioManager.VIBRATE_SETTING_ONLY_SILENT 898dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent : AudioManager.VIBRATE_SETTING_OFF); 899dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent mVibrateSetting = getValueForVibrateSetting(mVibrateSetting, 900dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent AudioManager.VIBRATE_TYPE_RINGER, 901dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent mHasVibrator ? AudioManager.VIBRATE_SETTING_ONLY_SILENT 902dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent : AudioManager.VIBRATE_SETTING_OFF); 903dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent 90424e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent updateRingerModeAffectedStreams(); 9057ee1e4ff7346a278a6722108fbc1869240b3e866Eric Laurent readDockAudioSettings(cr); 906402f7f29634a9f68e7929be828a927a3e2f5efe9Eric Laurent } 907c1d4166289ce016965d1147f7e8d37862ee347ecEric Laurent 908bc0fab1fc2db832ef86d8a33466ec4d68b103ca0Eric Laurent mMuteAffectedStreams = System.getIntForUser(cr, 9099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project System.MUTE_STREAMS_AFFECTED, 910bc0fab1fc2db832ef86d8a33466ec4d68b103ca0Eric Laurent ((1 << AudioSystem.STREAM_MUSIC)| 911bc0fab1fc2db832ef86d8a33466ec4d68b103ca0Eric Laurent (1 << AudioSystem.STREAM_RING)| 912bc0fab1fc2db832ef86d8a33466ec4d68b103ca0Eric Laurent (1 << AudioSystem.STREAM_SYSTEM)), 913bc0fab1fc2db832ef86d8a33466ec4d68b103ca0Eric Laurent UserHandle.USER_CURRENT); 9149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 915bc0fab1fc2db832ef86d8a33466ec4d68b103ca0Eric Laurent boolean masterMute = System.getIntForUser(cr, System.VOLUME_MASTER_MUTE, 916bc0fab1fc2db832ef86d8a33466ec4d68b103ca0Eric Laurent 0, UserHandle.USER_CURRENT) == 1; 91783a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent if (mUseFixedVolume) { 91883a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent masterMute = false; 91983a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent AudioSystem.setMasterVolume(1.0f); 92083a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent } 92157978ed86286a33d5b1a0fd000ca3406ba9d87b3Justin Koh AudioSystem.setMasterMute(masterMute); 92257978ed86286a33d5b1a0fd000ca3406ba9d87b3Justin Koh broadcastMasterMuteStatus(masterMute); 92357978ed86286a33d5b1a0fd000ca3406ba9d87b3Justin Koh 924b53453fae037d67e421011936c8fdffe7ba43922Julia Reynolds boolean microphoneMute = 925b53453fae037d67e421011936c8fdffe7ba43922Julia Reynolds System.getIntForUser(cr, System.MICROPHONE_MUTE, 0, UserHandle.USER_CURRENT) == 1; 926b53453fae037d67e421011936c8fdffe7ba43922Julia Reynolds AudioSystem.muteMicrophone(microphoneMute); 927b53453fae037d67e421011936c8fdffe7ba43922Julia Reynolds 9289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Each stream will read its own persisted settings 9299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 930bcc1087af40a0e1bb35dbe8a39c830ecdea8280bJohn Spurlock // Broadcast the sticky intents 931bcc1087af40a0e1bb35dbe8a39c830ecdea8280bJohn Spurlock broadcastRingerMode(AudioManager.RINGER_MODE_CHANGED_ACTION, mRingerModeExternal); 932bcc1087af40a0e1bb35dbe8a39c830ecdea8280bJohn Spurlock broadcastRingerMode(AudioManager.INTERNAL_RINGER_MODE_CHANGED_ACTION, mRingerMode); 9339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Broadcast vibrate settings 9359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project broadcastVibrateSetting(AudioManager.VIBRATE_TYPE_RINGER); 9369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project broadcastVibrateSetting(AudioManager.VIBRATE_TYPE_NOTIFICATION); 937d589fea865e90859324f00d21765fa7d7759e465Jean-Michel Trivi 93833f4e04e32fac42f158733d6a731e50490fa9951John Spurlock // Load settings for the volume controller 93933f4e04e32fac42f158733d6a731e50490fa9951John Spurlock mVolumeController.loadSettings(cr); 9409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 942a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent private int rescaleIndex(int index, int srcStream, int dstStream) { 943a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent return (index * mStreamStates[dstStream].getMaxIndex() + mStreamStates[srcStream].getMaxIndex() / 2) / mStreamStates[srcStream].getMaxIndex(); 944a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent } 9459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 946318f0fe43bdc4b2f6764edd91d6b78d9875ffdebJon Eklund private class AudioOrientationEventListener 947318f0fe43bdc4b2f6764edd91d6b78d9875ffdebJon Eklund extends OrientationEventListener { 948318f0fe43bdc4b2f6764edd91d6b78d9875ffdebJon Eklund public AudioOrientationEventListener(Context context) { 949318f0fe43bdc4b2f6764edd91d6b78d9875ffdebJon Eklund super(context); 950318f0fe43bdc4b2f6764edd91d6b78d9875ffdebJon Eklund } 951318f0fe43bdc4b2f6764edd91d6b78d9875ffdebJon Eklund 952318f0fe43bdc4b2f6764edd91d6b78d9875ffdebJon Eklund @Override 953318f0fe43bdc4b2f6764edd91d6b78d9875ffdebJon Eklund public void onOrientationChanged(int orientation) { 954318f0fe43bdc4b2f6764edd91d6b78d9875ffdebJon Eklund //Even though we're responding to phone orientation events, 955318f0fe43bdc4b2f6764edd91d6b78d9875ffdebJon Eklund //use display rotation so audio stays in sync with video/dialogs 956318f0fe43bdc4b2f6764edd91d6b78d9875ffdebJon Eklund int newRotation = ((WindowManager) mContext.getSystemService( 957318f0fe43bdc4b2f6764edd91d6b78d9875ffdebJon Eklund Context.WINDOW_SERVICE)).getDefaultDisplay().getRotation(); 958318f0fe43bdc4b2f6764edd91d6b78d9875ffdebJon Eklund if (newRotation != mDeviceRotation) { 959318f0fe43bdc4b2f6764edd91d6b78d9875ffdebJon Eklund mDeviceRotation = newRotation; 960318f0fe43bdc4b2f6764edd91d6b78d9875ffdebJon Eklund setRotationForAudioSystem(); 961318f0fe43bdc4b2f6764edd91d6b78d9875ffdebJon Eklund } 962318f0fe43bdc4b2f6764edd91d6b78d9875ffdebJon Eklund } 963318f0fe43bdc4b2f6764edd91d6b78d9875ffdebJon Eklund } 964318f0fe43bdc4b2f6764edd91d6b78d9875ffdebJon Eklund 9659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /////////////////////////////////////////////////////////////////////////// 9669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // IPC methods 9679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /////////////////////////////////////////////////////////////////////////// 9689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** @see AudioManager#adjustVolume(int, int) */ 969ba50b97cff80e73620a0e3d13cae169e095974a7Dianne Hackborn public void adjustSuggestedStreamVolume(int direction, int suggestedStreamType, int flags, 970ba50b97cff80e73620a0e3d13cae169e095974a7Dianne Hackborn String callingPackage) { 971272e161c1a200900cb10b5b0cdab8ae1f123cabdRoboErik adjustSuggestedStreamVolume(direction, suggestedStreamType, flags, callingPackage, 972272e161c1a200900cb10b5b0cdab8ae1f123cabdRoboErik Binder.getCallingUid()); 973272e161c1a200900cb10b5b0cdab8ae1f123cabdRoboErik } 974272e161c1a200900cb10b5b0cdab8ae1f123cabdRoboErik 975272e161c1a200900cb10b5b0cdab8ae1f123cabdRoboErik private void adjustSuggestedStreamVolume(int direction, int suggestedStreamType, int flags, 976272e161c1a200900cb10b5b0cdab8ae1f123cabdRoboErik String callingPackage, int uid) { 977ae641c9ccd3f81214cee54a5f13804f1765187adJohn Spurlock if (DEBUG_VOL) Log.d(TAG, "adjustSuggestedStreamVolume() stream="+suggestedStreamType 978ae641c9ccd3f81214cee54a5f13804f1765187adJohn Spurlock + ", flags=" + flags); 979402f7f29634a9f68e7929be828a927a3e2f5efe9Eric Laurent int streamType; 98045c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent if (mVolumeControlStream != -1) { 98145c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent streamType = mVolumeControlStream; 982402f7f29634a9f68e7929be828a927a3e2f5efe9Eric Laurent } else { 983402f7f29634a9f68e7929be828a927a3e2f5efe9Eric Laurent streamType = getActiveStreamType(suggestedStreamType); 984402f7f29634a9f68e7929be828a927a3e2f5efe9Eric Laurent } 98533f4e04e32fac42f158733d6a731e50490fa9951John Spurlock final int resolvedStream = mStreamVolumeAlias[streamType]; 9869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9872811dd337262934ea82477f9598f3e49092edb5eRoboErik // Play sounds on STREAM_RING only. 9882811dd337262934ea82477f9598f3e49092edb5eRoboErik if ((flags & AudioManager.FLAG_PLAY_SOUND) != 0 && 98933f4e04e32fac42f158733d6a731e50490fa9951John Spurlock resolvedStream != AudioSystem.STREAM_RING) { 99033f4e04e32fac42f158733d6a731e50490fa9951John Spurlock flags &= ~AudioManager.FLAG_PLAY_SOUND; 99133f4e04e32fac42f158733d6a731e50490fa9951John Spurlock } 99233f4e04e32fac42f158733d6a731e50490fa9951John Spurlock 99333f4e04e32fac42f158733d6a731e50490fa9951John Spurlock // For notifications/ring, show the ui before making any adjustments 99433f4e04e32fac42f158733d6a731e50490fa9951John Spurlock if (mVolumeController.suppressAdjustment(resolvedStream, flags)) { 99533f4e04e32fac42f158733d6a731e50490fa9951John Spurlock direction = 0; 9969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project flags &= ~AudioManager.FLAG_PLAY_SOUND; 99733f4e04e32fac42f158733d6a731e50490fa9951John Spurlock flags &= ~AudioManager.FLAG_VIBRATE; 99833f4e04e32fac42f158733d6a731e50490fa9951John Spurlock if (DEBUG_VOL) Log.d(TAG, "Volume controller suppressed adjustment"); 9999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1001272e161c1a200900cb10b5b0cdab8ae1f123cabdRoboErik adjustStreamVolume(streamType, direction, flags, callingPackage, uid); 10029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** @see AudioManager#adjustStreamVolume(int, int, int) */ 1005ba50b97cff80e73620a0e3d13cae169e095974a7Dianne Hackborn public void adjustStreamVolume(int streamType, int direction, int flags, 1006ba50b97cff80e73620a0e3d13cae169e095974a7Dianne Hackborn String callingPackage) { 10070dac35af2c6aa42bcd181981b041747cfd1afa5fRoboErik adjustStreamVolume(streamType, direction, flags, callingPackage, Binder.getCallingUid()); 10080dac35af2c6aa42bcd181981b041747cfd1afa5fRoboErik } 10090dac35af2c6aa42bcd181981b041747cfd1afa5fRoboErik 10100dac35af2c6aa42bcd181981b041747cfd1afa5fRoboErik private void adjustStreamVolume(int streamType, int direction, int flags, 10110dac35af2c6aa42bcd181981b041747cfd1afa5fRoboErik String callingPackage, int uid) { 101283a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent if (mUseFixedVolume) { 101383a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent return; 101483a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent } 1015ae641c9ccd3f81214cee54a5f13804f1765187adJohn Spurlock if (DEBUG_VOL) Log.d(TAG, "adjustStreamVolume() stream="+streamType+", dir="+direction 1016ae641c9ccd3f81214cee54a5f13804f1765187adJohn Spurlock + ", flags="+flags); 10173114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi 10189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ensureValidDirection(direction); 10199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ensureValidStreamType(streamType); 10209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 102196a33d1caad2fab0bc28891cfbf553f4b050bf0bEric Laurent // use stream type alias here so that streams with same alias have the same behavior, 102296a33d1caad2fab0bc28891cfbf553f4b050bf0bEric Laurent // including with regard to silent mode control (e.g the use of STREAM_RING below and in 102396a33d1caad2fab0bc28891cfbf553f4b050bf0bEric Laurent // checkForRingerModeChange() in place of STREAM_RING or STREAM_NOTIFICATION) 10246d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent int streamTypeAlias = mStreamVolumeAlias[streamType]; 1025b024c30a80684ac08daef3137b7ba0d347fe3ce5Eric Laurent VolumeStreamState streamState = mStreamStates[streamTypeAlias]; 10269bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent 10279bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent final int device = getDeviceForStream(streamTypeAlias); 10283ef7549876a159dae1568429edcb57e4e7d08459Eric Laurent 102942b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent int aliasIndex = streamState.getIndex(device); 10309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project boolean adjustVolume = true; 10313ef7549876a159dae1568429edcb57e4e7d08459Eric Laurent int step; 1032244820185269991186d07068b92985624cede4a5Eric Laurent 1033c9d1d5f35091226e96fcfa91817480f589eb36e2Matthew Xie // skip a2dp absolute volume control request when the device 1034c9d1d5f35091226e96fcfa91817480f589eb36e2Matthew Xie // is not an a2dp device 1035c9d1d5f35091226e96fcfa91817480f589eb36e2Matthew Xie if ((device & AudioSystem.DEVICE_OUT_ALL_A2DP) == 0 && 1036c9d1d5f35091226e96fcfa91817480f589eb36e2Matthew Xie (flags & AudioManager.FLAG_BLUETOOTH_ABS_VOLUME) != 0) { 1037c9d1d5f35091226e96fcfa91817480f589eb36e2Matthew Xie return; 1038c9d1d5f35091226e96fcfa91817480f589eb36e2Matthew Xie } 1039c9d1d5f35091226e96fcfa91817480f589eb36e2Matthew Xie 10400dac35af2c6aa42bcd181981b041747cfd1afa5fRoboErik if (mAppOps.noteOp(STEAM_VOLUME_OPS[streamTypeAlias], uid, callingPackage) 10410dac35af2c6aa42bcd181981b041747cfd1afa5fRoboErik != AppOpsManager.MODE_ALLOWED) { 1042ba50b97cff80e73620a0e3d13cae169e095974a7Dianne Hackborn return; 1043ba50b97cff80e73620a0e3d13cae169e095974a7Dianne Hackborn } 1044ba50b97cff80e73620a0e3d13cae169e095974a7Dianne Hackborn 1045fde16d5879ea88a971004c984093409468b6139cEric Laurent // reset any pending volume command 1046fde16d5879ea88a971004c984093409468b6139cEric Laurent synchronized (mSafeMediaVolumeState) { 1047fde16d5879ea88a971004c984093409468b6139cEric Laurent mPendingVolumeCommand = null; 1048fde16d5879ea88a971004c984093409468b6139cEric Laurent } 1049fde16d5879ea88a971004c984093409468b6139cEric Laurent 10503ef7549876a159dae1568429edcb57e4e7d08459Eric Laurent flags &= ~AudioManager.FLAG_FIXED_VOLUME; 10513ef7549876a159dae1568429edcb57e4e7d08459Eric Laurent if ((streamTypeAlias == AudioSystem.STREAM_MUSIC) && 10523ef7549876a159dae1568429edcb57e4e7d08459Eric Laurent ((device & mFixedVolumeDevices) != 0)) { 10533ef7549876a159dae1568429edcb57e4e7d08459Eric Laurent flags |= AudioManager.FLAG_FIXED_VOLUME; 10543ef7549876a159dae1568429edcb57e4e7d08459Eric Laurent 10553ef7549876a159dae1568429edcb57e4e7d08459Eric Laurent // Always toggle between max safe volume and 0 for fixed volume devices where safe 10563ef7549876a159dae1568429edcb57e4e7d08459Eric Laurent // volume is enforced, and max and 0 for the others. 10573ef7549876a159dae1568429edcb57e4e7d08459Eric Laurent // This is simulated by stepping by the full allowed volume range 10583ef7549876a159dae1568429edcb57e4e7d08459Eric Laurent if (mSafeMediaVolumeState == SAFE_MEDIA_VOLUME_ACTIVE && 10593ef7549876a159dae1568429edcb57e4e7d08459Eric Laurent (device & mSafeMediaVolumeDevices) != 0) { 10603ef7549876a159dae1568429edcb57e4e7d08459Eric Laurent step = mSafeMediaVolumeIndex; 10613ef7549876a159dae1568429edcb57e4e7d08459Eric Laurent } else { 10623ef7549876a159dae1568429edcb57e4e7d08459Eric Laurent step = streamState.getMaxIndex(); 10633ef7549876a159dae1568429edcb57e4e7d08459Eric Laurent } 10643ef7549876a159dae1568429edcb57e4e7d08459Eric Laurent if (aliasIndex != 0) { 10653ef7549876a159dae1568429edcb57e4e7d08459Eric Laurent aliasIndex = step; 10663ef7549876a159dae1568429edcb57e4e7d08459Eric Laurent } 10673ef7549876a159dae1568429edcb57e4e7d08459Eric Laurent } else { 10683ef7549876a159dae1568429edcb57e4e7d08459Eric Laurent // convert one UI step (+/-1) into a number of internal units on the stream alias 10693ef7549876a159dae1568429edcb57e4e7d08459Eric Laurent step = rescaleIndex(10, streamType, streamTypeAlias); 10703ef7549876a159dae1568429edcb57e4e7d08459Eric Laurent } 10713ef7549876a159dae1568429edcb57e4e7d08459Eric Laurent 107242b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent // If either the client forces allowing ringer modes for this adjustment, 107342b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent // or the stream type is one that is affected by ringer modes 107442b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent if (((flags & AudioManager.FLAG_ALLOW_RINGER_MODES) != 0) || 107542b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent (streamTypeAlias == getMasterStreamType())) { 1076661f2cf45860d2e10924e6b69966a9afe255f28bJohn Spurlock int ringerMode = getRingerModeInternal(); 107742b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent // do not vibrate if already in vibrate mode 107842b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent if (ringerMode == AudioManager.RINGER_MODE_VIBRATE) { 107942b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent flags &= ~AudioManager.FLAG_VIBRATE; 108042b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent } 108142b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent // Check if the ringer mode changes with this volume adjustment. If 108242b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent // it does, it will handle adjusting the volume, so we won't below 1083a11b4affcad3d255aa723a89b768ea222506f2e8John Spurlock final int result = checkForRingerModeChange(aliasIndex, direction, step); 1084a11b4affcad3d255aa723a89b768ea222506f2e8John Spurlock adjustVolume = (result & FLAG_ADJUST_VOLUME) != 0; 1085a11b4affcad3d255aa723a89b768ea222506f2e8John Spurlock // If suppressing a volume adjustment in silent mode, display the UI hint 1086a11b4affcad3d255aa723a89b768ea222506f2e8John Spurlock if ((result & AudioManager.FLAG_SHOW_SILENT_HINT) != 0) { 1087a11b4affcad3d255aa723a89b768ea222506f2e8John Spurlock flags |= AudioManager.FLAG_SHOW_SILENT_HINT; 1088a11b4affcad3d255aa723a89b768ea222506f2e8John Spurlock } 1089661f2cf45860d2e10924e6b69966a9afe255f28bJohn Spurlock // If suppressing a volume down adjustment in vibrate mode, display the UI hint 1090661f2cf45860d2e10924e6b69966a9afe255f28bJohn Spurlock if ((result & AudioManager.FLAG_SHOW_VIBRATE_HINT) != 0) { 1091661f2cf45860d2e10924e6b69966a9afe255f28bJohn Spurlock flags |= AudioManager.FLAG_SHOW_VIBRATE_HINT; 1092661f2cf45860d2e10924e6b69966a9afe255f28bJohn Spurlock } 109342b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent } 109442b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent 109542b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent int oldIndex = mStreamStates[streamType].getIndex(device); 109642b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent 109742b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent if (adjustVolume && (direction != AudioManager.ADJUST_SAME)) { 1098c9d1d5f35091226e96fcfa91817480f589eb36e2Matthew Xie 10995a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du // Check if volume update should be send to AVRCP 1100c9d1d5f35091226e96fcfa91817480f589eb36e2Matthew Xie if (streamTypeAlias == AudioSystem.STREAM_MUSIC && 1101c9d1d5f35091226e96fcfa91817480f589eb36e2Matthew Xie (device & AudioSystem.DEVICE_OUT_ALL_A2DP) != 0 && 1102c9d1d5f35091226e96fcfa91817480f589eb36e2Matthew Xie (flags & AudioManager.FLAG_BLUETOOTH_ABS_VOLUME) == 0) { 1103c9d1d5f35091226e96fcfa91817480f589eb36e2Matthew Xie synchronized (mA2dpAvrcpLock) { 1104c9d1d5f35091226e96fcfa91817480f589eb36e2Matthew Xie if (mA2dp != null && mAvrcpAbsVolSupported) { 1105c9d1d5f35091226e96fcfa91817480f589eb36e2Matthew Xie mA2dp.adjustAvrcpAbsoluteVolume(direction); 1106c9d1d5f35091226e96fcfa91817480f589eb36e2Matthew Xie } 11075a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du } 11085a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du } 1109c9d1d5f35091226e96fcfa91817480f589eb36e2Matthew Xie 111042b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent if ((direction == AudioManager.ADJUST_RAISE) && 111142b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent !checkSafeMediaVolume(streamTypeAlias, aliasIndex + step, device)) { 111242b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent Log.e(TAG, "adjustStreamVolume() safe volume index = "+oldIndex); 11133346a802087f621c6441bc512dfcc17b07143fc6John Spurlock mVolumeController.postDisplaySafeVolumeWarning(flags); 111442b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent } else if (streamState.adjustIndex(direction * step, device)) { 111542b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent // Post message to set system volume (it in turn will post a message 111642b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent // to persist). Do not change volume if stream is muted. 111742b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent sendMsg(mAudioHandler, 111842b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent MSG_SET_DEVICE_VOLUME, 111942b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent SENDMSG_QUEUE, 112042b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent device, 112142b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent 0, 112242b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent streamState, 112342b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent 0); 11244bbcc6549738f3d69831b2bd9eb4accec3e9920eEric Laurent } 112541d974631c5f525da49c88d34cecedd5a4cfeda8Jungshik Jang 112641d974631c5f525da49c88d34cecedd5a4cfeda8Jungshik Jang // Check if volume update should be send to Hdmi system audio. 112741d974631c5f525da49c88d34cecedd5a4cfeda8Jungshik Jang int newIndex = mStreamStates[streamType].getIndex(device); 1128336cdb488ff0e5ec6709c66f55072d3ad22b82edJinsuk Kim if (streamTypeAlias == AudioSystem.STREAM_MUSIC) { 1129336cdb488ff0e5ec6709c66f55072d3ad22b82edJinsuk Kim setSystemAudioVolume(oldIndex, newIndex, getStreamMaxVolume(streamType), flags); 1130336cdb488ff0e5ec6709c66f55072d3ad22b82edJinsuk Kim } 1131212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent if (mHdmiManager != null) { 1132212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent synchronized (mHdmiManager) { 1133212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent // mHdmiCecSink true => mHdmiPlaybackClient != null 1134212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent if (mHdmiCecSink && 1135212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent streamTypeAlias == AudioSystem.STREAM_MUSIC && 1136212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent oldIndex != newIndex) { 1137212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent synchronized (mHdmiPlaybackClient) { 1138212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent int keyCode = (direction == -1) ? KeyEvent.KEYCODE_VOLUME_DOWN : 1139212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent KeyEvent.KEYCODE_VOLUME_UP; 1140212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent mHdmiPlaybackClient.sendKeyEvent(keyCode, true); 1141212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent mHdmiPlaybackClient.sendKeyEvent(keyCode, false); 1142212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent } 114341d974631c5f525da49c88d34cecedd5a4cfeda8Jungshik Jang } 114441d974631c5f525da49c88d34cecedd5a4cfeda8Jungshik Jang } 114541d974631c5f525da49c88d34cecedd5a4cfeda8Jungshik Jang } 11464bbcc6549738f3d69831b2bd9eb4accec3e9920eEric Laurent } 114742b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent int index = mStreamStates[streamType].getIndex(device); 114825101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent sendVolumeUpdate(streamType, oldIndex, index, flags); 11499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 11509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1151336cdb488ff0e5ec6709c66f55072d3ad22b82edJinsuk Kim private void setSystemAudioVolume(int oldVolume, int newVolume, int maxVolume, int flags) { 1152336cdb488ff0e5ec6709c66f55072d3ad22b82edJinsuk Kim if (mHdmiManager == null 1153336cdb488ff0e5ec6709c66f55072d3ad22b82edJinsuk Kim || mHdmiTvClient == null 1154336cdb488ff0e5ec6709c66f55072d3ad22b82edJinsuk Kim || oldVolume == newVolume 1155336cdb488ff0e5ec6709c66f55072d3ad22b82edJinsuk Kim || (flags & AudioManager.FLAG_HDMI_SYSTEM_AUDIO_VOLUME) != 0) return; 1156336cdb488ff0e5ec6709c66f55072d3ad22b82edJinsuk Kim 1157336cdb488ff0e5ec6709c66f55072d3ad22b82edJinsuk Kim // Sets the audio volume of AVR when we are in system audio mode. The new volume info 1158336cdb488ff0e5ec6709c66f55072d3ad22b82edJinsuk Kim // is tranformed to HDMI-CEC commands and passed through CEC bus. 1159336cdb488ff0e5ec6709c66f55072d3ad22b82edJinsuk Kim synchronized (mHdmiManager) { 1160336cdb488ff0e5ec6709c66f55072d3ad22b82edJinsuk Kim if (!mHdmiSystemAudioSupported) return; 1161336cdb488ff0e5ec6709c66f55072d3ad22b82edJinsuk Kim synchronized (mHdmiTvClient) { 116248cbf292ba9ad550af7e44d950a441b1812428e2Jinsuk Kim final long token = Binder.clearCallingIdentity(); 116348cbf292ba9ad550af7e44d950a441b1812428e2Jinsuk Kim try { 116448cbf292ba9ad550af7e44d950a441b1812428e2Jinsuk Kim mHdmiTvClient.setSystemAudioVolume( 116548cbf292ba9ad550af7e44d950a441b1812428e2Jinsuk Kim (oldVolume + 5) / 10, (newVolume + 5) / 10, maxVolume); 116648cbf292ba9ad550af7e44d950a441b1812428e2Jinsuk Kim } finally { 116748cbf292ba9ad550af7e44d950a441b1812428e2Jinsuk Kim Binder.restoreCallingIdentity(token); 116848cbf292ba9ad550af7e44d950a441b1812428e2Jinsuk Kim } 1169336cdb488ff0e5ec6709c66f55072d3ad22b82edJinsuk Kim } 1170336cdb488ff0e5ec6709c66f55072d3ad22b82edJinsuk Kim } 1171336cdb488ff0e5ec6709c66f55072d3ad22b82edJinsuk Kim } 1172336cdb488ff0e5ec6709c66f55072d3ad22b82edJinsuk Kim 1173961cae92540763226648813d111c5b5c3b0f1597Dianne Hackborn /** @see AudioManager#adjustMasterVolume(int, int) */ 1174ba50b97cff80e73620a0e3d13cae169e095974a7Dianne Hackborn public void adjustMasterVolume(int steps, int flags, String callingPackage) { 1175519c7744b522aa07e12bc3244ac3de14aa2a4ad0RoboErik adjustMasterVolume(steps, flags, callingPackage, Binder.getCallingUid()); 1176519c7744b522aa07e12bc3244ac3de14aa2a4ad0RoboErik } 1177519c7744b522aa07e12bc3244ac3de14aa2a4ad0RoboErik 1178519c7744b522aa07e12bc3244ac3de14aa2a4ad0RoboErik public void adjustMasterVolume(int steps, int flags, String callingPackage, int uid) { 117983a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent if (mUseFixedVolume) { 118083a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent return; 118183a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent } 11826c798970ccb8759d1e613b57111daa8da0ab44c7Lei Zhang ensureValidSteps(steps); 11839760647dd0ee67e7c20f3e9d661d2006b1df0b54Mike Lockwood int volume = Math.round(AudioSystem.getMasterVolume() * MAX_MASTER_VOLUME); 11849760647dd0ee67e7c20f3e9d661d2006b1df0b54Mike Lockwood int delta = 0; 11856c798970ccb8759d1e613b57111daa8da0ab44c7Lei Zhang int numSteps = Math.abs(steps); 11866c798970ccb8759d1e613b57111daa8da0ab44c7Lei Zhang int direction = steps > 0 ? AudioManager.ADJUST_RAISE : AudioManager.ADJUST_LOWER; 11876c798970ccb8759d1e613b57111daa8da0ab44c7Lei Zhang for (int i = 0; i < numSteps; ++i) { 11886c798970ccb8759d1e613b57111daa8da0ab44c7Lei Zhang delta = findVolumeDelta(direction, volume); 11896c798970ccb8759d1e613b57111daa8da0ab44c7Lei Zhang volume += delta; 1190cbdb49dc5e1b993a0bc5c68dbfb9486bfa0cd762Mike Lockwood } 119124b082f87e96c00d5c17d60c735423900be40e70RoboErik 11926c798970ccb8759d1e613b57111daa8da0ab44c7Lei Zhang //Log.d(TAG, "adjustMasterVolume volume: " + volume + " steps: " + steps); 1193519c7744b522aa07e12bc3244ac3de14aa2a4ad0RoboErik setMasterVolume(volume, flags, callingPackage, uid); 1194cbdb49dc5e1b993a0bc5c68dbfb9486bfa0cd762Mike Lockwood } 1195cbdb49dc5e1b993a0bc5c68dbfb9486bfa0cd762Mike Lockwood 1196fde16d5879ea88a971004c984093409468b6139cEric Laurent // StreamVolumeCommand contains the information needed to defer the process of 1197fde16d5879ea88a971004c984093409468b6139cEric Laurent // setStreamVolume() in case the user has to acknowledge the safe volume warning message. 1198fde16d5879ea88a971004c984093409468b6139cEric Laurent class StreamVolumeCommand { 1199fde16d5879ea88a971004c984093409468b6139cEric Laurent public final int mStreamType; 1200fde16d5879ea88a971004c984093409468b6139cEric Laurent public final int mIndex; 1201fde16d5879ea88a971004c984093409468b6139cEric Laurent public final int mFlags; 1202fde16d5879ea88a971004c984093409468b6139cEric Laurent public final int mDevice; 12033ef7549876a159dae1568429edcb57e4e7d08459Eric Laurent 1204fde16d5879ea88a971004c984093409468b6139cEric Laurent StreamVolumeCommand(int streamType, int index, int flags, int device) { 1205fde16d5879ea88a971004c984093409468b6139cEric Laurent mStreamType = streamType; 1206fde16d5879ea88a971004c984093409468b6139cEric Laurent mIndex = index; 1207fde16d5879ea88a971004c984093409468b6139cEric Laurent mFlags = flags; 1208fde16d5879ea88a971004c984093409468b6139cEric Laurent mDevice = device; 12094bbcc6549738f3d69831b2bd9eb4accec3e9920eEric Laurent } 1210351346092acdfbfcc1d9ebf98d539d2a1196c5e8John Spurlock 1211351346092acdfbfcc1d9ebf98d539d2a1196c5e8John Spurlock @Override 1212351346092acdfbfcc1d9ebf98d539d2a1196c5e8John Spurlock public String toString() { 1213351346092acdfbfcc1d9ebf98d539d2a1196c5e8John Spurlock return new StringBuilder().append("{streamType=").append(mStreamType).append(",index=") 1214351346092acdfbfcc1d9ebf98d539d2a1196c5e8John Spurlock .append(mIndex).append(",flags=").append(mFlags).append(",device=") 1215351346092acdfbfcc1d9ebf98d539d2a1196c5e8John Spurlock .append(mDevice).append('}').toString(); 1216351346092acdfbfcc1d9ebf98d539d2a1196c5e8John Spurlock } 1217fde16d5879ea88a971004c984093409468b6139cEric Laurent }; 12183ef7549876a159dae1568429edcb57e4e7d08459Eric Laurent 1219fde16d5879ea88a971004c984093409468b6139cEric Laurent private void onSetStreamVolume(int streamType, int index, int flags, int device) { 122042b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent setStreamVolumeInt(mStreamVolumeAlias[streamType], index, device, false); 12213ef7549876a159dae1568429edcb57e4e7d08459Eric Laurent // setting volume on master stream type also controls silent mode 12223ef7549876a159dae1568429edcb57e4e7d08459Eric Laurent if (((flags & AudioManager.FLAG_ALLOW_RINGER_MODES) != 0) || 12233ef7549876a159dae1568429edcb57e4e7d08459Eric Laurent (mStreamVolumeAlias[streamType] == getMasterStreamType())) { 12243ef7549876a159dae1568429edcb57e4e7d08459Eric Laurent int newRingerMode; 12253ef7549876a159dae1568429edcb57e4e7d08459Eric Laurent if (index == 0) { 12263ef7549876a159dae1568429edcb57e4e7d08459Eric Laurent newRingerMode = mHasVibrator ? AudioManager.RINGER_MODE_VIBRATE 12278600534df66c2ff5846ed230b50c56229322d48aJohn Spurlock : VOLUME_SETS_RINGER_MODE_SILENT ? AudioManager.RINGER_MODE_SILENT 12288600534df66c2ff5846ed230b50c56229322d48aJohn Spurlock : AudioManager.RINGER_MODE_NORMAL; 12293ef7549876a159dae1568429edcb57e4e7d08459Eric Laurent } else { 12303ef7549876a159dae1568429edcb57e4e7d08459Eric Laurent newRingerMode = AudioManager.RINGER_MODE_NORMAL; 12313ef7549876a159dae1568429edcb57e4e7d08459Eric Laurent } 1232661f2cf45860d2e10924e6b69966a9afe255f28bJohn Spurlock setRingerMode(newRingerMode, TAG + ".onSetStreamVolume", false /*external*/); 12333ef7549876a159dae1568429edcb57e4e7d08459Eric Laurent } 1234fde16d5879ea88a971004c984093409468b6139cEric Laurent } 1235fde16d5879ea88a971004c984093409468b6139cEric Laurent 1236fde16d5879ea88a971004c984093409468b6139cEric Laurent /** @see AudioManager#setStreamVolume(int, int, int) */ 1237ba50b97cff80e73620a0e3d13cae169e095974a7Dianne Hackborn public void setStreamVolume(int streamType, int index, int flags, String callingPackage) { 12380dac35af2c6aa42bcd181981b041747cfd1afa5fRoboErik setStreamVolume(streamType, index, flags, callingPackage, Binder.getCallingUid()); 12390dac35af2c6aa42bcd181981b041747cfd1afa5fRoboErik } 12400dac35af2c6aa42bcd181981b041747cfd1afa5fRoboErik 12410dac35af2c6aa42bcd181981b041747cfd1afa5fRoboErik private void setStreamVolume(int streamType, int index, int flags, String callingPackage, 12420dac35af2c6aa42bcd181981b041747cfd1afa5fRoboErik int uid) { 124383a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent if (mUseFixedVolume) { 124483a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent return; 124583a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent } 124683a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent 1247fde16d5879ea88a971004c984093409468b6139cEric Laurent ensureValidStreamType(streamType); 1248ba50b97cff80e73620a0e3d13cae169e095974a7Dianne Hackborn int streamTypeAlias = mStreamVolumeAlias[streamType]; 1249ba50b97cff80e73620a0e3d13cae169e095974a7Dianne Hackborn VolumeStreamState streamState = mStreamStates[streamTypeAlias]; 1250fde16d5879ea88a971004c984093409468b6139cEric Laurent 1251fde16d5879ea88a971004c984093409468b6139cEric Laurent final int device = getDeviceForStream(streamType); 1252fde16d5879ea88a971004c984093409468b6139cEric Laurent int oldIndex; 1253fde16d5879ea88a971004c984093409468b6139cEric Laurent 1254c9d1d5f35091226e96fcfa91817480f589eb36e2Matthew Xie // skip a2dp absolute volume control request when the device 1255c9d1d5f35091226e96fcfa91817480f589eb36e2Matthew Xie // is not an a2dp device 1256c9d1d5f35091226e96fcfa91817480f589eb36e2Matthew Xie if ((device & AudioSystem.DEVICE_OUT_ALL_A2DP) == 0 && 1257c9d1d5f35091226e96fcfa91817480f589eb36e2Matthew Xie (flags & AudioManager.FLAG_BLUETOOTH_ABS_VOLUME) != 0) { 1258c9d1d5f35091226e96fcfa91817480f589eb36e2Matthew Xie return; 1259c9d1d5f35091226e96fcfa91817480f589eb36e2Matthew Xie } 1260c9d1d5f35091226e96fcfa91817480f589eb36e2Matthew Xie 12610dac35af2c6aa42bcd181981b041747cfd1afa5fRoboErik if (mAppOps.noteOp(STEAM_VOLUME_OPS[streamTypeAlias], uid, callingPackage) 12620dac35af2c6aa42bcd181981b041747cfd1afa5fRoboErik != AppOpsManager.MODE_ALLOWED) { 1263ba50b97cff80e73620a0e3d13cae169e095974a7Dianne Hackborn return; 1264ba50b97cff80e73620a0e3d13cae169e095974a7Dianne Hackborn } 1265ba50b97cff80e73620a0e3d13cae169e095974a7Dianne Hackborn 1266fde16d5879ea88a971004c984093409468b6139cEric Laurent synchronized (mSafeMediaVolumeState) { 1267fde16d5879ea88a971004c984093409468b6139cEric Laurent // reset any pending volume command 1268fde16d5879ea88a971004c984093409468b6139cEric Laurent mPendingVolumeCommand = null; 1269fde16d5879ea88a971004c984093409468b6139cEric Laurent 127042b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent oldIndex = streamState.getIndex(device); 1271fde16d5879ea88a971004c984093409468b6139cEric Laurent 1272ba50b97cff80e73620a0e3d13cae169e095974a7Dianne Hackborn index = rescaleIndex(index * 10, streamType, streamTypeAlias); 1273fde16d5879ea88a971004c984093409468b6139cEric Laurent 1274c9d1d5f35091226e96fcfa91817480f589eb36e2Matthew Xie if (streamTypeAlias == AudioSystem.STREAM_MUSIC && 1275c9d1d5f35091226e96fcfa91817480f589eb36e2Matthew Xie (device & AudioSystem.DEVICE_OUT_ALL_A2DP) != 0 && 1276c9d1d5f35091226e96fcfa91817480f589eb36e2Matthew Xie (flags & AudioManager.FLAG_BLUETOOTH_ABS_VOLUME) == 0) { 1277c9d1d5f35091226e96fcfa91817480f589eb36e2Matthew Xie synchronized (mA2dpAvrcpLock) { 1278c9d1d5f35091226e96fcfa91817480f589eb36e2Matthew Xie if (mA2dp != null && mAvrcpAbsVolSupported) { 12792f4a2b139b4c1dde7be1d14333ad02553734c528Zhihai Xu mA2dp.setAvrcpAbsoluteVolume(index / 10); 1280c9d1d5f35091226e96fcfa91817480f589eb36e2Matthew Xie } 12815a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du } 12825a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du } 12835a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du 1284336cdb488ff0e5ec6709c66f55072d3ad22b82edJinsuk Kim if (streamTypeAlias == AudioSystem.STREAM_MUSIC) { 1285336cdb488ff0e5ec6709c66f55072d3ad22b82edJinsuk Kim setSystemAudioVolume(oldIndex, index, getStreamMaxVolume(streamType), flags); 128641d974631c5f525da49c88d34cecedd5a4cfeda8Jungshik Jang } 128741d974631c5f525da49c88d34cecedd5a4cfeda8Jungshik Jang 1288fde16d5879ea88a971004c984093409468b6139cEric Laurent flags &= ~AudioManager.FLAG_FIXED_VOLUME; 1289ba50b97cff80e73620a0e3d13cae169e095974a7Dianne Hackborn if ((streamTypeAlias == AudioSystem.STREAM_MUSIC) && 1290fde16d5879ea88a971004c984093409468b6139cEric Laurent ((device & mFixedVolumeDevices) != 0)) { 1291fde16d5879ea88a971004c984093409468b6139cEric Laurent flags |= AudioManager.FLAG_FIXED_VOLUME; 1292fde16d5879ea88a971004c984093409468b6139cEric Laurent 1293fde16d5879ea88a971004c984093409468b6139cEric Laurent // volume is either 0 or max allowed for fixed volume devices 1294fde16d5879ea88a971004c984093409468b6139cEric Laurent if (index != 0) { 1295fde16d5879ea88a971004c984093409468b6139cEric Laurent if (mSafeMediaVolumeState == SAFE_MEDIA_VOLUME_ACTIVE && 1296fde16d5879ea88a971004c984093409468b6139cEric Laurent (device & mSafeMediaVolumeDevices) != 0) { 1297fde16d5879ea88a971004c984093409468b6139cEric Laurent index = mSafeMediaVolumeIndex; 1298fde16d5879ea88a971004c984093409468b6139cEric Laurent } else { 1299fde16d5879ea88a971004c984093409468b6139cEric Laurent index = streamState.getMaxIndex(); 1300fde16d5879ea88a971004c984093409468b6139cEric Laurent } 1301fde16d5879ea88a971004c984093409468b6139cEric Laurent } 1302fde16d5879ea88a971004c984093409468b6139cEric Laurent } 1303fde16d5879ea88a971004c984093409468b6139cEric Laurent 1304ba50b97cff80e73620a0e3d13cae169e095974a7Dianne Hackborn if (!checkSafeMediaVolume(streamTypeAlias, index, device)) { 13053346a802087f621c6441bc512dfcc17b07143fc6John Spurlock mVolumeController.postDisplaySafeVolumeWarning(flags); 1306fde16d5879ea88a971004c984093409468b6139cEric Laurent mPendingVolumeCommand = new StreamVolumeCommand( 1307fde16d5879ea88a971004c984093409468b6139cEric Laurent streamType, index, flags, device); 1308fde16d5879ea88a971004c984093409468b6139cEric Laurent } else { 1309fde16d5879ea88a971004c984093409468b6139cEric Laurent onSetStreamVolume(streamType, index, flags, device); 131042b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent index = mStreamStates[streamType].getIndex(device); 1311fde16d5879ea88a971004c984093409468b6139cEric Laurent } 1312fde16d5879ea88a971004c984093409468b6139cEric Laurent } 131325101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent sendVolumeUpdate(streamType, oldIndex, index, flags); 13149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 13159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 131645c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent /** @see AudioManager#forceVolumeControlStream(int) */ 131745c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent public void forceVolumeControlStream(int streamType, IBinder cb) { 131845c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent synchronized(mForceControlStreamLock) { 131945c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent mVolumeControlStream = streamType; 132045c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent if (mVolumeControlStream == -1) { 132145c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent if (mForceControlStreamClient != null) { 132245c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent mForceControlStreamClient.release(); 132345c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent mForceControlStreamClient = null; 132445c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent } 132545c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent } else { 132645c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent mForceControlStreamClient = new ForceControlStreamClient(cb); 132745c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent } 132845c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent } 132945c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent } 133045c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent 133145c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent private class ForceControlStreamClient implements IBinder.DeathRecipient { 133245c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent private IBinder mCb; // To be notified of client's death 133345c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent 133445c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent ForceControlStreamClient(IBinder cb) { 133545c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent if (cb != null) { 133645c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent try { 133745c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent cb.linkToDeath(this, 0); 133845c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent } catch (RemoteException e) { 133945c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent // Client has died! 134045c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent Log.w(TAG, "ForceControlStreamClient() could not link to "+cb+" binder death"); 134145c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent cb = null; 134245c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent } 134345c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent } 134445c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent mCb = cb; 134545c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent } 134645c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent 134745c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent public void binderDied() { 134845c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent synchronized(mForceControlStreamLock) { 134945c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent Log.w(TAG, "SCO client died"); 135045c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent if (mForceControlStreamClient != this) { 135145c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent Log.w(TAG, "unregistered control stream client died"); 135245c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent } else { 135345c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent mForceControlStreamClient = null; 135445c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent mVolumeControlStream = -1; 135545c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent } 135645c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent } 135745c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent } 135845c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent 135945c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent public void release() { 136045c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent if (mCb != null) { 136145c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent mCb.unlinkToDeath(this, 0); 136245c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent mCb = null; 136345c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent } 136445c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent } 136545c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent } 136645c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent 13676c798970ccb8759d1e613b57111daa8da0ab44c7Lei Zhang private int findVolumeDelta(int direction, int volume) { 13686c798970ccb8759d1e613b57111daa8da0ab44c7Lei Zhang int delta = 0; 13696c798970ccb8759d1e613b57111daa8da0ab44c7Lei Zhang if (direction == AudioManager.ADJUST_RAISE) { 13706c798970ccb8759d1e613b57111daa8da0ab44c7Lei Zhang if (volume == MAX_MASTER_VOLUME) { 13716c798970ccb8759d1e613b57111daa8da0ab44c7Lei Zhang return 0; 13726c798970ccb8759d1e613b57111daa8da0ab44c7Lei Zhang } 13736c798970ccb8759d1e613b57111daa8da0ab44c7Lei Zhang // This is the default value if we make it to the end 13746c798970ccb8759d1e613b57111daa8da0ab44c7Lei Zhang delta = mMasterVolumeRamp[1]; 13756c798970ccb8759d1e613b57111daa8da0ab44c7Lei Zhang // If we're raising the volume move down the ramp array until we 13766c798970ccb8759d1e613b57111daa8da0ab44c7Lei Zhang // find the volume we're above and use that groups delta. 13776c798970ccb8759d1e613b57111daa8da0ab44c7Lei Zhang for (int i = mMasterVolumeRamp.length - 1; i > 1; i -= 2) { 13786c798970ccb8759d1e613b57111daa8da0ab44c7Lei Zhang if (volume >= mMasterVolumeRamp[i - 1]) { 13796c798970ccb8759d1e613b57111daa8da0ab44c7Lei Zhang delta = mMasterVolumeRamp[i]; 13806c798970ccb8759d1e613b57111daa8da0ab44c7Lei Zhang break; 13816c798970ccb8759d1e613b57111daa8da0ab44c7Lei Zhang } 13826c798970ccb8759d1e613b57111daa8da0ab44c7Lei Zhang } 13836c798970ccb8759d1e613b57111daa8da0ab44c7Lei Zhang } else if (direction == AudioManager.ADJUST_LOWER){ 13846c798970ccb8759d1e613b57111daa8da0ab44c7Lei Zhang if (volume == 0) { 13856c798970ccb8759d1e613b57111daa8da0ab44c7Lei Zhang return 0; 13866c798970ccb8759d1e613b57111daa8da0ab44c7Lei Zhang } 13876c798970ccb8759d1e613b57111daa8da0ab44c7Lei Zhang int length = mMasterVolumeRamp.length; 13886c798970ccb8759d1e613b57111daa8da0ab44c7Lei Zhang // This is the default value if we make it to the end 13896c798970ccb8759d1e613b57111daa8da0ab44c7Lei Zhang delta = -mMasterVolumeRamp[length - 1]; 13906c798970ccb8759d1e613b57111daa8da0ab44c7Lei Zhang // If we're lowering the volume move up the ramp array until we 13916c798970ccb8759d1e613b57111daa8da0ab44c7Lei Zhang // find the volume we're below and use the group below it's delta 13926c798970ccb8759d1e613b57111daa8da0ab44c7Lei Zhang for (int i = 2; i < length; i += 2) { 13936c798970ccb8759d1e613b57111daa8da0ab44c7Lei Zhang if (volume <= mMasterVolumeRamp[i]) { 13946c798970ccb8759d1e613b57111daa8da0ab44c7Lei Zhang delta = -mMasterVolumeRamp[i - 1]; 13956c798970ccb8759d1e613b57111daa8da0ab44c7Lei Zhang break; 13966c798970ccb8759d1e613b57111daa8da0ab44c7Lei Zhang } 13976c798970ccb8759d1e613b57111daa8da0ab44c7Lei Zhang } 13986c798970ccb8759d1e613b57111daa8da0ab44c7Lei Zhang } 13996c798970ccb8759d1e613b57111daa8da0ab44c7Lei Zhang return delta; 14006c798970ccb8759d1e613b57111daa8da0ab44c7Lei Zhang } 14016c798970ccb8759d1e613b57111daa8da0ab44c7Lei Zhang 14025ac72a29593ab9a20337a2225df52bdf4754be02Dianne Hackborn private void sendBroadcastToAll(Intent intent) { 1403267603f3bbf7a6a707aaf055297ae0c3afae51d8Christopher Tate intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); 14045ac72a29593ab9a20337a2225df52bdf4754be02Dianne Hackborn final long ident = Binder.clearCallingIdentity(); 14055ac72a29593ab9a20337a2225df52bdf4754be02Dianne Hackborn try { 14065ac72a29593ab9a20337a2225df52bdf4754be02Dianne Hackborn mContext.sendBroadcastAsUser(intent, UserHandle.ALL); 14075ac72a29593ab9a20337a2225df52bdf4754be02Dianne Hackborn } finally { 14085ac72a29593ab9a20337a2225df52bdf4754be02Dianne Hackborn Binder.restoreCallingIdentity(ident); 14095ac72a29593ab9a20337a2225df52bdf4754be02Dianne Hackborn } 14105ac72a29593ab9a20337a2225df52bdf4754be02Dianne Hackborn } 14115ac72a29593ab9a20337a2225df52bdf4754be02Dianne Hackborn 14125ac72a29593ab9a20337a2225df52bdf4754be02Dianne Hackborn private void sendStickyBroadcastToAll(Intent intent) { 14135ac72a29593ab9a20337a2225df52bdf4754be02Dianne Hackborn final long ident = Binder.clearCallingIdentity(); 14145ac72a29593ab9a20337a2225df52bdf4754be02Dianne Hackborn try { 14155ac72a29593ab9a20337a2225df52bdf4754be02Dianne Hackborn mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL); 14165ac72a29593ab9a20337a2225df52bdf4754be02Dianne Hackborn } finally { 14175ac72a29593ab9a20337a2225df52bdf4754be02Dianne Hackborn Binder.restoreCallingIdentity(ident); 14185ac72a29593ab9a20337a2225df52bdf4754be02Dianne Hackborn } 14195ac72a29593ab9a20337a2225df52bdf4754be02Dianne Hackborn } 14205ac72a29593ab9a20337a2225df52bdf4754be02Dianne Hackborn 142125101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent // UI update and Broadcast Intent 142225101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent private void sendVolumeUpdate(int streamType, int oldIndex, int index, int flags) { 1423212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent if (!isPlatformVoice() && (streamType == AudioSystem.STREAM_RING)) { 142425101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent streamType = AudioSystem.STREAM_NOTIFICATION; 142525101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent } 142625101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent 1427336cdb488ff0e5ec6709c66f55072d3ad22b82edJinsuk Kim if (streamType == AudioSystem.STREAM_MUSIC) { 1428336cdb488ff0e5ec6709c66f55072d3ad22b82edJinsuk Kim flags = updateFlagsForSystemAudio(flags); 14291a6be6ed3962735f12dbd5ce1bca758120c8fb8dJungshik Jang } 14303346a802087f621c6441bc512dfcc17b07143fc6John Spurlock mVolumeController.postVolumeChanged(streamType, flags); 143125101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent 14324bbcc6549738f3d69831b2bd9eb4accec3e9920eEric Laurent if ((flags & AudioManager.FLAG_FIXED_VOLUME) == 0) { 14334bbcc6549738f3d69831b2bd9eb4accec3e9920eEric Laurent oldIndex = (oldIndex + 5) / 10; 14344bbcc6549738f3d69831b2bd9eb4accec3e9920eEric Laurent index = (index + 5) / 10; 14354bbcc6549738f3d69831b2bd9eb4accec3e9920eEric Laurent Intent intent = new Intent(AudioManager.VOLUME_CHANGED_ACTION); 14364bbcc6549738f3d69831b2bd9eb4accec3e9920eEric Laurent intent.putExtra(AudioManager.EXTRA_VOLUME_STREAM_TYPE, streamType); 14374bbcc6549738f3d69831b2bd9eb4accec3e9920eEric Laurent intent.putExtra(AudioManager.EXTRA_VOLUME_STREAM_VALUE, index); 14384bbcc6549738f3d69831b2bd9eb4accec3e9920eEric Laurent intent.putExtra(AudioManager.EXTRA_PREV_VOLUME_STREAM_VALUE, oldIndex); 14394bbcc6549738f3d69831b2bd9eb4accec3e9920eEric Laurent sendBroadcastToAll(intent); 14404bbcc6549738f3d69831b2bd9eb4accec3e9920eEric Laurent } 14419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 14429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1443336cdb488ff0e5ec6709c66f55072d3ad22b82edJinsuk Kim // If Hdmi-CEC system audio mode is on, we show volume bar only when TV 1444336cdb488ff0e5ec6709c66f55072d3ad22b82edJinsuk Kim // receives volume notification from Audio Receiver. 1445336cdb488ff0e5ec6709c66f55072d3ad22b82edJinsuk Kim private int updateFlagsForSystemAudio(int flags) { 1446336cdb488ff0e5ec6709c66f55072d3ad22b82edJinsuk Kim if (mHdmiTvClient != null) { 1447336cdb488ff0e5ec6709c66f55072d3ad22b82edJinsuk Kim synchronized (mHdmiTvClient) { 1448336cdb488ff0e5ec6709c66f55072d3ad22b82edJinsuk Kim if (mHdmiSystemAudioSupported && 1449336cdb488ff0e5ec6709c66f55072d3ad22b82edJinsuk Kim ((flags & AudioManager.FLAG_HDMI_SYSTEM_AUDIO_VOLUME) == 0)) { 1450336cdb488ff0e5ec6709c66f55072d3ad22b82edJinsuk Kim flags &= ~AudioManager.FLAG_SHOW_UI; 1451336cdb488ff0e5ec6709c66f55072d3ad22b82edJinsuk Kim } 1452336cdb488ff0e5ec6709c66f55072d3ad22b82edJinsuk Kim } 1453336cdb488ff0e5ec6709c66f55072d3ad22b82edJinsuk Kim } 1454336cdb488ff0e5ec6709c66f55072d3ad22b82edJinsuk Kim return flags; 1455336cdb488ff0e5ec6709c66f55072d3ad22b82edJinsuk Kim } 1456336cdb488ff0e5ec6709c66f55072d3ad22b82edJinsuk Kim 14570dc37cce9d564ae43883c8dc8672b9266b881e63Mike Lockwood // UI update and Broadcast Intent 14580dc37cce9d564ae43883c8dc8672b9266b881e63Mike Lockwood private void sendMasterVolumeUpdate(int flags, int oldVolume, int newVolume) { 1459336cdb488ff0e5ec6709c66f55072d3ad22b82edJinsuk Kim mVolumeController.postMasterVolumeChanged(updateFlagsForSystemAudio(flags)); 14600dc37cce9d564ae43883c8dc8672b9266b881e63Mike Lockwood 14610dc37cce9d564ae43883c8dc8672b9266b881e63Mike Lockwood Intent intent = new Intent(AudioManager.MASTER_VOLUME_CHANGED_ACTION); 14620dc37cce9d564ae43883c8dc8672b9266b881e63Mike Lockwood intent.putExtra(AudioManager.EXTRA_PREV_MASTER_VOLUME_VALUE, oldVolume); 14630dc37cce9d564ae43883c8dc8672b9266b881e63Mike Lockwood intent.putExtra(AudioManager.EXTRA_MASTER_VOLUME_VALUE, newVolume); 14645ac72a29593ab9a20337a2225df52bdf4754be02Dianne Hackborn sendBroadcastToAll(intent); 14650dc37cce9d564ae43883c8dc8672b9266b881e63Mike Lockwood } 14660dc37cce9d564ae43883c8dc8672b9266b881e63Mike Lockwood 14670dc37cce9d564ae43883c8dc8672b9266b881e63Mike Lockwood // UI update and Broadcast Intent 14680dc37cce9d564ae43883c8dc8672b9266b881e63Mike Lockwood private void sendMasterMuteUpdate(boolean muted, int flags) { 1469336cdb488ff0e5ec6709c66f55072d3ad22b82edJinsuk Kim mVolumeController.postMasterMuteChanged(updateFlagsForSystemAudio(flags)); 147057978ed86286a33d5b1a0fd000ca3406ba9d87b3Justin Koh broadcastMasterMuteStatus(muted); 147157978ed86286a33d5b1a0fd000ca3406ba9d87b3Justin Koh } 14720dc37cce9d564ae43883c8dc8672b9266b881e63Mike Lockwood 147357978ed86286a33d5b1a0fd000ca3406ba9d87b3Justin Koh private void broadcastMasterMuteStatus(boolean muted) { 14740dc37cce9d564ae43883c8dc8672b9266b881e63Mike Lockwood Intent intent = new Intent(AudioManager.MASTER_MUTE_CHANGED_ACTION); 14750dc37cce9d564ae43883c8dc8672b9266b881e63Mike Lockwood intent.putExtra(AudioManager.EXTRA_MASTER_VOLUME_MUTED, muted); 147657978ed86286a33d5b1a0fd000ca3406ba9d87b3Justin Koh intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT 147757978ed86286a33d5b1a0fd000ca3406ba9d87b3Justin Koh | Intent.FLAG_RECEIVER_REPLACE_PENDING); 14785ac72a29593ab9a20337a2225df52bdf4754be02Dianne Hackborn sendStickyBroadcastToAll(intent); 14790dc37cce9d564ae43883c8dc8672b9266b881e63Mike Lockwood } 14800dc37cce9d564ae43883c8dc8672b9266b881e63Mike Lockwood 14819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 14829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Sets the stream state's index, and posts a message to set system volume. 14839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * This will not call out to the UI. Assumes a valid stream type. 14849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 14859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param streamType Type of the stream 14869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param index Desired volume index of the stream 14879bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent * @param device the device whose volume must be changed 14889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param force If true, set the volume even if the desired volume is same 14899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * as the current volume. 14909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 14919bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent private void setStreamVolumeInt(int streamType, 14929bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent int index, 14939bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent int device, 149442b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent boolean force) { 14959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project VolumeStreamState streamState = mStreamStates[streamType]; 14965b4e654d0c7de8e4d58d73e73b0d5220f19b68f7Eric Laurent 149742b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent if (streamState.setIndex(index, device) || force) { 149842b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent // Post message to set system volume (it in turn will post a message 149942b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent // to persist). 150042b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent sendMsg(mAudioHandler, 150142b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent MSG_SET_DEVICE_VOLUME, 150242b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent SENDMSG_QUEUE, 150342b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent device, 150442b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent 0, 150542b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent streamState, 150642b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent 0); 15079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 15089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 15099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 15109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** @see AudioManager#setStreamSolo(int, boolean) */ 15119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void setStreamSolo(int streamType, boolean state, IBinder cb) { 151283a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent if (mUseFixedVolume) { 151383a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent return; 151483a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent } 15154fb3b602156d093c1082be88f2f016f3a791a978Eric Laurent int streamAlias = mStreamVolumeAlias[streamType]; 15169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int stream = 0; stream < mStreamStates.length; stream++) { 15174fb3b602156d093c1082be88f2f016f3a791a978Eric Laurent if (!isStreamAffectedByMute(streamAlias) || streamAlias == mStreamVolumeAlias[stream]) { 15184fb3b602156d093c1082be88f2f016f3a791a978Eric Laurent continue; 15194fb3b602156d093c1082be88f2f016f3a791a978Eric Laurent } 15209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mStreamStates[stream].mute(cb, state); 15219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 15229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 15239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 15249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** @see AudioManager#setStreamMute(int, boolean) */ 15259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void setStreamMute(int streamType, boolean state, IBinder cb) { 152683a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent if (mUseFixedVolume) { 152783a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent return; 152883a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent } 15297c82ced4fc5b66c09a19eed9a5499039530142fbRoboErik if (streamType == AudioManager.USE_DEFAULT_STREAM_TYPE) { 15307c82ced4fc5b66c09a19eed9a5499039530142fbRoboErik streamType = getActiveStreamType(streamType); 15317c82ced4fc5b66c09a19eed9a5499039530142fbRoboErik } 15324fb3b602156d093c1082be88f2f016f3a791a978Eric Laurent int streamAlias = mStreamVolumeAlias[streamType]; 15334fb3b602156d093c1082be88f2f016f3a791a978Eric Laurent if (isStreamAffectedByMute(streamAlias)) { 15344fb3b602156d093c1082be88f2f016f3a791a978Eric Laurent if (streamAlias == AudioSystem.STREAM_MUSIC) { 1535336cdb488ff0e5ec6709c66f55072d3ad22b82edJinsuk Kim setSystemAudioMute(state); 1536336cdb488ff0e5ec6709c66f55072d3ad22b82edJinsuk Kim } 15374fb3b602156d093c1082be88f2f016f3a791a978Eric Laurent for (int stream = 0; stream < mStreamStates.length; stream++) { 15384fb3b602156d093c1082be88f2f016f3a791a978Eric Laurent if (streamAlias == mStreamVolumeAlias[stream]) { 15394fb3b602156d093c1082be88f2f016f3a791a978Eric Laurent mStreamStates[stream].mute(cb, state); 15404fb3b602156d093c1082be88f2f016f3a791a978Eric Laurent 15414fb3b602156d093c1082be88f2f016f3a791a978Eric Laurent Intent intent = new Intent(AudioManager.STREAM_MUTE_CHANGED_ACTION); 15424fb3b602156d093c1082be88f2f016f3a791a978Eric Laurent intent.putExtra(AudioManager.EXTRA_VOLUME_STREAM_TYPE, stream); 15434fb3b602156d093c1082be88f2f016f3a791a978Eric Laurent intent.putExtra(AudioManager.EXTRA_STREAM_VOLUME_MUTED, state); 15444fb3b602156d093c1082be88f2f016f3a791a978Eric Laurent sendBroadcastToAll(intent); 15454fb3b602156d093c1082be88f2f016f3a791a978Eric Laurent } 15464fb3b602156d093c1082be88f2f016f3a791a978Eric Laurent } 1547336cdb488ff0e5ec6709c66f55072d3ad22b82edJinsuk Kim } 1548336cdb488ff0e5ec6709c66f55072d3ad22b82edJinsuk Kim } 1549336cdb488ff0e5ec6709c66f55072d3ad22b82edJinsuk Kim 1550336cdb488ff0e5ec6709c66f55072d3ad22b82edJinsuk Kim private void setSystemAudioMute(boolean state) { 1551336cdb488ff0e5ec6709c66f55072d3ad22b82edJinsuk Kim if (mHdmiManager == null || mHdmiTvClient == null) return; 1552336cdb488ff0e5ec6709c66f55072d3ad22b82edJinsuk Kim synchronized (mHdmiManager) { 155348cbf292ba9ad550af7e44d950a441b1812428e2Jinsuk Kim if (!mHdmiSystemAudioSupported) return; 155448cbf292ba9ad550af7e44d950a441b1812428e2Jinsuk Kim synchronized (mHdmiTvClient) { 155548cbf292ba9ad550af7e44d950a441b1812428e2Jinsuk Kim final long token = Binder.clearCallingIdentity(); 155648cbf292ba9ad550af7e44d950a441b1812428e2Jinsuk Kim try { 155748cbf292ba9ad550af7e44d950a441b1812428e2Jinsuk Kim mHdmiTvClient.setSystemAudioMute(state); 155848cbf292ba9ad550af7e44d950a441b1812428e2Jinsuk Kim } finally { 155948cbf292ba9ad550af7e44d950a441b1812428e2Jinsuk Kim Binder.restoreCallingIdentity(token); 156041d974631c5f525da49c88d34cecedd5a4cfeda8Jungshik Jang } 156141d974631c5f525da49c88d34cecedd5a4cfeda8Jungshik Jang } 15629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 15639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 15649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 156525101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent /** get stream mute state. */ 156625101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent public boolean isStreamMute(int streamType) { 15677c82ced4fc5b66c09a19eed9a5499039530142fbRoboErik if (streamType == AudioManager.USE_DEFAULT_STREAM_TYPE) { 15687c82ced4fc5b66c09a19eed9a5499039530142fbRoboErik streamType = getActiveStreamType(streamType); 15697c82ced4fc5b66c09a19eed9a5499039530142fbRoboErik } 15708fa4d6f585f40ff5cf5f9bed316d92c64a306f21Eric Laurent synchronized (VolumeStreamState.class) { 15718fa4d6f585f40ff5cf5f9bed316d92c64a306f21Eric Laurent return mStreamStates[streamType].isMuted_syncVSS(); 15728fa4d6f585f40ff5cf5f9bed316d92c64a306f21Eric Laurent } 157325101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent } 157425101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent 1575ba5270b88798c66fefc17a1b25b27894e4fb7862Jean-Michel Trivi private class RmtSbmxFullVolDeathHandler implements IBinder.DeathRecipient { 1576ba5270b88798c66fefc17a1b25b27894e4fb7862Jean-Michel Trivi private IBinder mICallback; // To be notified of client's death 1577ba5270b88798c66fefc17a1b25b27894e4fb7862Jean-Michel Trivi 1578ba5270b88798c66fefc17a1b25b27894e4fb7862Jean-Michel Trivi RmtSbmxFullVolDeathHandler(IBinder cb) { 1579ba5270b88798c66fefc17a1b25b27894e4fb7862Jean-Michel Trivi mICallback = cb; 1580ba5270b88798c66fefc17a1b25b27894e4fb7862Jean-Michel Trivi try { 1581ba5270b88798c66fefc17a1b25b27894e4fb7862Jean-Michel Trivi cb.linkToDeath(this, 0/*flags*/); 1582ba5270b88798c66fefc17a1b25b27894e4fb7862Jean-Michel Trivi } catch (RemoteException e) { 1583ba5270b88798c66fefc17a1b25b27894e4fb7862Jean-Michel Trivi Log.e(TAG, "can't link to death", e); 1584ba5270b88798c66fefc17a1b25b27894e4fb7862Jean-Michel Trivi } 1585ba5270b88798c66fefc17a1b25b27894e4fb7862Jean-Michel Trivi } 1586ba5270b88798c66fefc17a1b25b27894e4fb7862Jean-Michel Trivi 1587ba5270b88798c66fefc17a1b25b27894e4fb7862Jean-Michel Trivi boolean isHandlerFor(IBinder cb) { 1588ba5270b88798c66fefc17a1b25b27894e4fb7862Jean-Michel Trivi return mICallback.equals(cb); 1589ba5270b88798c66fefc17a1b25b27894e4fb7862Jean-Michel Trivi } 1590ba5270b88798c66fefc17a1b25b27894e4fb7862Jean-Michel Trivi 1591ba5270b88798c66fefc17a1b25b27894e4fb7862Jean-Michel Trivi void forget() { 1592ba5270b88798c66fefc17a1b25b27894e4fb7862Jean-Michel Trivi try { 1593ba5270b88798c66fefc17a1b25b27894e4fb7862Jean-Michel Trivi mICallback.unlinkToDeath(this, 0/*flags*/); 1594ba5270b88798c66fefc17a1b25b27894e4fb7862Jean-Michel Trivi } catch (NoSuchElementException e) { 1595ba5270b88798c66fefc17a1b25b27894e4fb7862Jean-Michel Trivi Log.e(TAG, "error unlinking to death", e); 1596ba5270b88798c66fefc17a1b25b27894e4fb7862Jean-Michel Trivi } 1597ba5270b88798c66fefc17a1b25b27894e4fb7862Jean-Michel Trivi } 1598ba5270b88798c66fefc17a1b25b27894e4fb7862Jean-Michel Trivi 1599ba5270b88798c66fefc17a1b25b27894e4fb7862Jean-Michel Trivi public void binderDied() { 1600ba5270b88798c66fefc17a1b25b27894e4fb7862Jean-Michel Trivi Log.w(TAG, "Recorder with remote submix at full volume died " + mICallback); 1601ba5270b88798c66fefc17a1b25b27894e4fb7862Jean-Michel Trivi forceRemoteSubmixFullVolume(false, mICallback); 1602ba5270b88798c66fefc17a1b25b27894e4fb7862Jean-Michel Trivi } 1603ba5270b88798c66fefc17a1b25b27894e4fb7862Jean-Michel Trivi } 1604ba5270b88798c66fefc17a1b25b27894e4fb7862Jean-Michel Trivi 1605ba5270b88798c66fefc17a1b25b27894e4fb7862Jean-Michel Trivi /** 1606ba5270b88798c66fefc17a1b25b27894e4fb7862Jean-Michel Trivi * call must be synchronized on mRmtSbmxFullVolDeathHandlers 1607ba5270b88798c66fefc17a1b25b27894e4fb7862Jean-Michel Trivi * @return true if there is a registered death handler, false otherwise */ 1608ba5270b88798c66fefc17a1b25b27894e4fb7862Jean-Michel Trivi private boolean discardRmtSbmxFullVolDeathHandlerFor(IBinder cb) { 1609ba5270b88798c66fefc17a1b25b27894e4fb7862Jean-Michel Trivi Iterator<RmtSbmxFullVolDeathHandler> it = mRmtSbmxFullVolDeathHandlers.iterator(); 1610ba5270b88798c66fefc17a1b25b27894e4fb7862Jean-Michel Trivi while (it.hasNext()) { 1611ba5270b88798c66fefc17a1b25b27894e4fb7862Jean-Michel Trivi final RmtSbmxFullVolDeathHandler handler = it.next(); 1612ba5270b88798c66fefc17a1b25b27894e4fb7862Jean-Michel Trivi if (handler.isHandlerFor(cb)) { 1613ba5270b88798c66fefc17a1b25b27894e4fb7862Jean-Michel Trivi handler.forget(); 1614ba5270b88798c66fefc17a1b25b27894e4fb7862Jean-Michel Trivi mRmtSbmxFullVolDeathHandlers.remove(handler); 1615ba5270b88798c66fefc17a1b25b27894e4fb7862Jean-Michel Trivi return true; 1616ba5270b88798c66fefc17a1b25b27894e4fb7862Jean-Michel Trivi } 1617ba5270b88798c66fefc17a1b25b27894e4fb7862Jean-Michel Trivi } 1618ba5270b88798c66fefc17a1b25b27894e4fb7862Jean-Michel Trivi return false; 1619ba5270b88798c66fefc17a1b25b27894e4fb7862Jean-Michel Trivi } 1620ba5270b88798c66fefc17a1b25b27894e4fb7862Jean-Michel Trivi 1621ba5270b88798c66fefc17a1b25b27894e4fb7862Jean-Michel Trivi /** call synchronized on mRmtSbmxFullVolDeathHandlers */ 1622ba5270b88798c66fefc17a1b25b27894e4fb7862Jean-Michel Trivi private boolean hasRmtSbmxFullVolDeathHandlerFor(IBinder cb) { 1623ba5270b88798c66fefc17a1b25b27894e4fb7862Jean-Michel Trivi Iterator<RmtSbmxFullVolDeathHandler> it = mRmtSbmxFullVolDeathHandlers.iterator(); 1624ba5270b88798c66fefc17a1b25b27894e4fb7862Jean-Michel Trivi while (it.hasNext()) { 1625ba5270b88798c66fefc17a1b25b27894e4fb7862Jean-Michel Trivi if (it.next().isHandlerFor(cb)) { 1626ba5270b88798c66fefc17a1b25b27894e4fb7862Jean-Michel Trivi return true; 1627ba5270b88798c66fefc17a1b25b27894e4fb7862Jean-Michel Trivi } 1628ba5270b88798c66fefc17a1b25b27894e4fb7862Jean-Michel Trivi } 1629ba5270b88798c66fefc17a1b25b27894e4fb7862Jean-Michel Trivi return false; 1630ba5270b88798c66fefc17a1b25b27894e4fb7862Jean-Michel Trivi } 1631ba5270b88798c66fefc17a1b25b27894e4fb7862Jean-Michel Trivi 1632ba5270b88798c66fefc17a1b25b27894e4fb7862Jean-Michel Trivi private int mRmtSbmxFullVolRefCount = 0; 1633ba5270b88798c66fefc17a1b25b27894e4fb7862Jean-Michel Trivi private ArrayList<RmtSbmxFullVolDeathHandler> mRmtSbmxFullVolDeathHandlers = 1634ba5270b88798c66fefc17a1b25b27894e4fb7862Jean-Michel Trivi new ArrayList<RmtSbmxFullVolDeathHandler>(); 1635ba5270b88798c66fefc17a1b25b27894e4fb7862Jean-Michel Trivi 1636ba5270b88798c66fefc17a1b25b27894e4fb7862Jean-Michel Trivi public void forceRemoteSubmixFullVolume(boolean startForcing, IBinder cb) { 1637ba5270b88798c66fefc17a1b25b27894e4fb7862Jean-Michel Trivi if (cb == null) { 1638ba5270b88798c66fefc17a1b25b27894e4fb7862Jean-Michel Trivi return; 1639ba5270b88798c66fefc17a1b25b27894e4fb7862Jean-Michel Trivi } 1640ba5270b88798c66fefc17a1b25b27894e4fb7862Jean-Michel Trivi if ((PackageManager.PERMISSION_GRANTED != mContext.checkCallingOrSelfPermission( 1641ba5270b88798c66fefc17a1b25b27894e4fb7862Jean-Michel Trivi android.Manifest.permission.CAPTURE_AUDIO_OUTPUT))) { 1642ba5270b88798c66fefc17a1b25b27894e4fb7862Jean-Michel Trivi Log.w(TAG, "Trying to call forceRemoteSubmixFullVolume() without CAPTURE_AUDIO_OUTPUT"); 1643ba5270b88798c66fefc17a1b25b27894e4fb7862Jean-Michel Trivi return; 1644ba5270b88798c66fefc17a1b25b27894e4fb7862Jean-Michel Trivi } 1645ba5270b88798c66fefc17a1b25b27894e4fb7862Jean-Michel Trivi synchronized(mRmtSbmxFullVolDeathHandlers) { 1646ba5270b88798c66fefc17a1b25b27894e4fb7862Jean-Michel Trivi boolean applyRequired = false; 1647ba5270b88798c66fefc17a1b25b27894e4fb7862Jean-Michel Trivi if (startForcing) { 1648ba5270b88798c66fefc17a1b25b27894e4fb7862Jean-Michel Trivi if (!hasRmtSbmxFullVolDeathHandlerFor(cb)) { 1649ba5270b88798c66fefc17a1b25b27894e4fb7862Jean-Michel Trivi mRmtSbmxFullVolDeathHandlers.add(new RmtSbmxFullVolDeathHandler(cb)); 1650ba5270b88798c66fefc17a1b25b27894e4fb7862Jean-Michel Trivi if (mRmtSbmxFullVolRefCount == 0) { 1651ba5270b88798c66fefc17a1b25b27894e4fb7862Jean-Michel Trivi mFullVolumeDevices |= AudioSystem.DEVICE_OUT_REMOTE_SUBMIX; 1652ba5270b88798c66fefc17a1b25b27894e4fb7862Jean-Michel Trivi mFixedVolumeDevices |= AudioSystem.DEVICE_OUT_REMOTE_SUBMIX; 1653ba5270b88798c66fefc17a1b25b27894e4fb7862Jean-Michel Trivi applyRequired = true; 1654ba5270b88798c66fefc17a1b25b27894e4fb7862Jean-Michel Trivi } 1655ba5270b88798c66fefc17a1b25b27894e4fb7862Jean-Michel Trivi mRmtSbmxFullVolRefCount++; 1656ba5270b88798c66fefc17a1b25b27894e4fb7862Jean-Michel Trivi } 1657ba5270b88798c66fefc17a1b25b27894e4fb7862Jean-Michel Trivi } else { 1658ba5270b88798c66fefc17a1b25b27894e4fb7862Jean-Michel Trivi if (discardRmtSbmxFullVolDeathHandlerFor(cb) && (mRmtSbmxFullVolRefCount > 0)) { 1659ba5270b88798c66fefc17a1b25b27894e4fb7862Jean-Michel Trivi mRmtSbmxFullVolRefCount--; 1660ba5270b88798c66fefc17a1b25b27894e4fb7862Jean-Michel Trivi if (mRmtSbmxFullVolRefCount == 0) { 1661ba5270b88798c66fefc17a1b25b27894e4fb7862Jean-Michel Trivi mFullVolumeDevices &= ~AudioSystem.DEVICE_OUT_REMOTE_SUBMIX; 1662ba5270b88798c66fefc17a1b25b27894e4fb7862Jean-Michel Trivi mFixedVolumeDevices &= ~AudioSystem.DEVICE_OUT_REMOTE_SUBMIX; 1663ba5270b88798c66fefc17a1b25b27894e4fb7862Jean-Michel Trivi applyRequired = true; 1664ba5270b88798c66fefc17a1b25b27894e4fb7862Jean-Michel Trivi } 1665ba5270b88798c66fefc17a1b25b27894e4fb7862Jean-Michel Trivi } 1666ba5270b88798c66fefc17a1b25b27894e4fb7862Jean-Michel Trivi } 1667ba5270b88798c66fefc17a1b25b27894e4fb7862Jean-Michel Trivi if (applyRequired) { 1668ba5270b88798c66fefc17a1b25b27894e4fb7862Jean-Michel Trivi // Assumes only STREAM_MUSIC going through DEVICE_OUT_REMOTE_SUBMIX 1669ba5270b88798c66fefc17a1b25b27894e4fb7862Jean-Michel Trivi checkAllFixedVolumeDevices(AudioSystem.STREAM_MUSIC); 1670ba5270b88798c66fefc17a1b25b27894e4fb7862Jean-Michel Trivi mStreamStates[AudioSystem.STREAM_MUSIC].applyAllVolumes(); 1671ba5270b88798c66fefc17a1b25b27894e4fb7862Jean-Michel Trivi } 1672ba5270b88798c66fefc17a1b25b27894e4fb7862Jean-Michel Trivi } 1673ba5270b88798c66fefc17a1b25b27894e4fb7862Jean-Michel Trivi } 1674ba5270b88798c66fefc17a1b25b27894e4fb7862Jean-Michel Trivi 1675961cae92540763226648813d111c5b5c3b0f1597Dianne Hackborn /** @see AudioManager#setMasterMute(boolean, int) */ 16764a21b25fad62e4f19d13ba814263841c931f56efJulia Reynolds public void setMasterMute(boolean state, int flags, String callingPackage, IBinder cb) { 16777c82ced4fc5b66c09a19eed9a5499039530142fbRoboErik setMasterMuteInternal(state, flags, callingPackage, cb, Binder.getCallingUid()); 16787c82ced4fc5b66c09a19eed9a5499039530142fbRoboErik } 16797c82ced4fc5b66c09a19eed9a5499039530142fbRoboErik 16807c82ced4fc5b66c09a19eed9a5499039530142fbRoboErik private void setMasterMuteInternal(boolean state, int flags, String callingPackage, IBinder cb, 16817c82ced4fc5b66c09a19eed9a5499039530142fbRoboErik int uid) { 168283a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent if (mUseFixedVolume) { 168383a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent return; 168483a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent } 16857c82ced4fc5b66c09a19eed9a5499039530142fbRoboErik if (mAppOps.noteOp(AppOpsManager.OP_AUDIO_MASTER_VOLUME, uid, callingPackage) 16867c82ced4fc5b66c09a19eed9a5499039530142fbRoboErik != AppOpsManager.MODE_ALLOWED) { 16874a21b25fad62e4f19d13ba814263841c931f56efJulia Reynolds return; 16884a21b25fad62e4f19d13ba814263841c931f56efJulia Reynolds } 16891ce5b26d707e0086e09af3cd0428f1b441145261Jason Simmons if (state != AudioSystem.getMasterMute()) { 1690336cdb488ff0e5ec6709c66f55072d3ad22b82edJinsuk Kim setSystemAudioMute(state); 16911ce5b26d707e0086e09af3cd0428f1b441145261Jason Simmons AudioSystem.setMasterMute(state); 169257978ed86286a33d5b1a0fd000ca3406ba9d87b3Justin Koh // Post a persist master volume msg 169375cf9e19a575c28c200c02c0ab6f83bb79f5c50dJustin Koh sendMsg(mAudioHandler, MSG_PERSIST_MASTER_VOLUME_MUTE, SENDMSG_REPLACE, state ? 1 1694b53453fae037d67e421011936c8fdffe7ba43922Julia Reynolds : 0, UserHandle.getCallingUserId(), null, PERSIST_DELAY); 16950273af55cf68d54d26d154b44d105d40fed79701Justin Koh sendMasterMuteUpdate(state, flags); 16967c82ced4fc5b66c09a19eed9a5499039530142fbRoboErik 16977c82ced4fc5b66c09a19eed9a5499039530142fbRoboErik Intent intent = new Intent(AudioManager.MASTER_MUTE_CHANGED_ACTION); 16987c82ced4fc5b66c09a19eed9a5499039530142fbRoboErik intent.putExtra(AudioManager.EXTRA_MASTER_VOLUME_MUTED, state); 16997c82ced4fc5b66c09a19eed9a5499039530142fbRoboErik sendBroadcastToAll(intent); 17001ce5b26d707e0086e09af3cd0428f1b441145261Jason Simmons } 1701ce952c8e13c535bedde77bcdb94dfcc7508475aaMike Lockwood } 1702ce952c8e13c535bedde77bcdb94dfcc7508475aaMike Lockwood 1703ce952c8e13c535bedde77bcdb94dfcc7508475aaMike Lockwood /** get master mute state. */ 1704ce952c8e13c535bedde77bcdb94dfcc7508475aaMike Lockwood public boolean isMasterMute() { 17053194ea94348bce8e7ee9f803698d877f46f8279aMike Lockwood return AudioSystem.getMasterMute(); 1706ce952c8e13c535bedde77bcdb94dfcc7508475aaMike Lockwood } 1707ce952c8e13c535bedde77bcdb94dfcc7508475aaMike Lockwood 1708fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi protected static int getMaxStreamVolume(int streamType) { 1709fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi return MAX_STREAM_VOLUME[streamType]; 1710fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi } 1711fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi 171291377de6f23af2b0b08adae22810cae6fc35cb1aEric Laurent public static int getDefaultStreamVolume(int streamType) { 171391377de6f23af2b0b08adae22810cae6fc35cb1aEric Laurent return DEFAULT_STREAM_VOLUME[streamType]; 171491377de6f23af2b0b08adae22810cae6fc35cb1aEric Laurent } 171591377de6f23af2b0b08adae22810cae6fc35cb1aEric Laurent 17169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** @see AudioManager#getStreamVolume(int) */ 17179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int getStreamVolume(int streamType) { 17189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ensureValidStreamType(streamType); 17199bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent int device = getDeviceForStream(streamType); 17208fa4d6f585f40ff5cf5f9bed316d92c64a306f21Eric Laurent synchronized (VolumeStreamState.class) { 17218fa4d6f585f40ff5cf5f9bed316d92c64a306f21Eric Laurent int index = mStreamStates[streamType].getIndex(device); 17224bbcc6549738f3d69831b2bd9eb4accec3e9920eEric Laurent 17238fa4d6f585f40ff5cf5f9bed316d92c64a306f21Eric Laurent // by convention getStreamVolume() returns 0 when a stream is muted. 17248fa4d6f585f40ff5cf5f9bed316d92c64a306f21Eric Laurent if (mStreamStates[streamType].isMuted_syncVSS()) { 17258fa4d6f585f40ff5cf5f9bed316d92c64a306f21Eric Laurent index = 0; 17268fa4d6f585f40ff5cf5f9bed316d92c64a306f21Eric Laurent } 17278fa4d6f585f40ff5cf5f9bed316d92c64a306f21Eric Laurent if (index != 0 && (mStreamVolumeAlias[streamType] == AudioSystem.STREAM_MUSIC) && 17288fa4d6f585f40ff5cf5f9bed316d92c64a306f21Eric Laurent (device & mFixedVolumeDevices) != 0) { 17298fa4d6f585f40ff5cf5f9bed316d92c64a306f21Eric Laurent index = mStreamStates[streamType].getMaxIndex(); 17308fa4d6f585f40ff5cf5f9bed316d92c64a306f21Eric Laurent } 17318fa4d6f585f40ff5cf5f9bed316d92c64a306f21Eric Laurent return (index + 5) / 10; 17324bbcc6549738f3d69831b2bd9eb4accec3e9920eEric Laurent } 17339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 17349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1735519c7744b522aa07e12bc3244ac3de14aa2a4ad0RoboErik @Override 17364767690f09ea3447b8c5c32fb28d27650aa18e00Mike Lockwood public int getMasterVolume() { 1737ce952c8e13c535bedde77bcdb94dfcc7508475aaMike Lockwood if (isMasterMute()) return 0; 1738ce952c8e13c535bedde77bcdb94dfcc7508475aaMike Lockwood return getLastAudibleMasterVolume(); 17398dc1dabd254249b7ddb8743e88fdb96580ffc585Mike Lockwood } 17408dc1dabd254249b7ddb8743e88fdb96580ffc585Mike Lockwood 1741519c7744b522aa07e12bc3244ac3de14aa2a4ad0RoboErik @Override 1742ba50b97cff80e73620a0e3d13cae169e095974a7Dianne Hackborn public void setMasterVolume(int volume, int flags, String callingPackage) { 1743519c7744b522aa07e12bc3244ac3de14aa2a4ad0RoboErik setMasterVolume(volume, flags, callingPackage, Binder.getCallingUid()); 1744519c7744b522aa07e12bc3244ac3de14aa2a4ad0RoboErik } 1745519c7744b522aa07e12bc3244ac3de14aa2a4ad0RoboErik 1746519c7744b522aa07e12bc3244ac3de14aa2a4ad0RoboErik public void setMasterVolume(int volume, int flags, String callingPackage, int uid) { 174783a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent if (mUseFixedVolume) { 174883a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent return; 174983a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent } 175083a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent 1751519c7744b522aa07e12bc3244ac3de14aa2a4ad0RoboErik if (mAppOps.noteOp(AppOpsManager.OP_AUDIO_MASTER_VOLUME, uid, callingPackage) 1752519c7744b522aa07e12bc3244ac3de14aa2a4ad0RoboErik != AppOpsManager.MODE_ALLOWED) { 1753ba50b97cff80e73620a0e3d13cae169e095974a7Dianne Hackborn return; 1754ba50b97cff80e73620a0e3d13cae169e095974a7Dianne Hackborn } 1755ba50b97cff80e73620a0e3d13cae169e095974a7Dianne Hackborn 17569760647dd0ee67e7c20f3e9d661d2006b1df0b54Mike Lockwood if (volume < 0) { 17579760647dd0ee67e7c20f3e9d661d2006b1df0b54Mike Lockwood volume = 0; 17589760647dd0ee67e7c20f3e9d661d2006b1df0b54Mike Lockwood } else if (volume > MAX_MASTER_VOLUME) { 17599760647dd0ee67e7c20f3e9d661d2006b1df0b54Mike Lockwood volume = MAX_MASTER_VOLUME; 17609760647dd0ee67e7c20f3e9d661d2006b1df0b54Mike Lockwood } 17615c55a051ad7d86a464fb91426f1ea3c0250e38b3Mike Lockwood doSetMasterVolume((float)volume / MAX_MASTER_VOLUME, flags); 17625c55a051ad7d86a464fb91426f1ea3c0250e38b3Mike Lockwood } 17635c55a051ad7d86a464fb91426f1ea3c0250e38b3Mike Lockwood 17645c55a051ad7d86a464fb91426f1ea3c0250e38b3Mike Lockwood private void doSetMasterVolume(float volume, int flags) { 17655c55a051ad7d86a464fb91426f1ea3c0250e38b3Mike Lockwood // don't allow changing master volume when muted 17665c55a051ad7d86a464fb91426f1ea3c0250e38b3Mike Lockwood if (!AudioSystem.getMasterMute()) { 17675c55a051ad7d86a464fb91426f1ea3c0250e38b3Mike Lockwood int oldVolume = getMasterVolume(); 17685c55a051ad7d86a464fb91426f1ea3c0250e38b3Mike Lockwood AudioSystem.setMasterVolume(volume); 17695c55a051ad7d86a464fb91426f1ea3c0250e38b3Mike Lockwood 17705c55a051ad7d86a464fb91426f1ea3c0250e38b3Mike Lockwood int newVolume = getMasterVolume(); 17715c55a051ad7d86a464fb91426f1ea3c0250e38b3Mike Lockwood if (newVolume != oldVolume) { 17725c55a051ad7d86a464fb91426f1ea3c0250e38b3Mike Lockwood // Post a persist master volume msg 17735c55a051ad7d86a464fb91426f1ea3c0250e38b3Mike Lockwood sendMsg(mAudioHandler, MSG_PERSIST_MASTER_VOLUME, SENDMSG_REPLACE, 17745c55a051ad7d86a464fb91426f1ea3c0250e38b3Mike Lockwood Math.round(volume * (float)1000.0), 0, null, PERSIST_DELAY); 1775336cdb488ff0e5ec6709c66f55072d3ad22b82edJinsuk Kim setSystemAudioVolume(oldVolume, newVolume, getMasterMaxVolume(), flags); 17765c55a051ad7d86a464fb91426f1ea3c0250e38b3Mike Lockwood } 17773caba517253d1703fc29b50740c4567b932279fbJustin Koh // Send the volume update regardless whether there was a change. 17783caba517253d1703fc29b50740c4567b932279fbJustin Koh sendMasterVolumeUpdate(flags, oldVolume, newVolume); 17795c55a051ad7d86a464fb91426f1ea3c0250e38b3Mike Lockwood } 17808dc1dabd254249b7ddb8743e88fdb96580ffc585Mike Lockwood } 17818dc1dabd254249b7ddb8743e88fdb96580ffc585Mike Lockwood 17829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** @see AudioManager#getStreamMaxVolume(int) */ 17839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int getStreamMaxVolume(int streamType) { 17849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ensureValidStreamType(streamType); 1785a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent return (mStreamStates[streamType].getMaxIndex() + 5) / 10; 17869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 17879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 17884767690f09ea3447b8c5c32fb28d27650aa18e00Mike Lockwood public int getMasterMaxVolume() { 17894767690f09ea3447b8c5c32fb28d27650aa18e00Mike Lockwood return MAX_MASTER_VOLUME; 17904767690f09ea3447b8c5c32fb28d27650aa18e00Mike Lockwood } 179125101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent 179225101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent /** Get last audible volume before stream was muted. */ 179325101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent public int getLastAudibleStreamVolume(int streamType) { 179425101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent ensureValidStreamType(streamType); 17959bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent int device = getDeviceForStream(streamType); 179642b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent return (mStreamStates[streamType].getIndex(device) + 5) / 10; 179725101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent } 179825101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent 1799ce952c8e13c535bedde77bcdb94dfcc7508475aaMike Lockwood /** Get last audible master volume before it was muted. */ 1800ce952c8e13c535bedde77bcdb94dfcc7508475aaMike Lockwood public int getLastAudibleMasterVolume() { 1801ce952c8e13c535bedde77bcdb94dfcc7508475aaMike Lockwood return Math.round(AudioSystem.getMasterVolume() * MAX_MASTER_VOLUME); 1802ce952c8e13c535bedde77bcdb94dfcc7508475aaMike Lockwood } 1803ce952c8e13c535bedde77bcdb94dfcc7508475aaMike Lockwood 1804961cae92540763226648813d111c5b5c3b0f1597Dianne Hackborn /** @see AudioManager#getMasterStreamType() */ 18056d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent public int getMasterStreamType() { 18064f0f120316cfcee5880191264885772677fff921John Spurlock return mStreamVolumeAlias[AudioSystem.STREAM_SYSTEM]; 18076d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent } 18086d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent 180922c921a910d236abf3a1705a02541a49fdaf3a14Emily Bernier /** @see AudioManager#setMicrophoneMute(boolean) */ 181022c921a910d236abf3a1705a02541a49fdaf3a14Emily Bernier public void setMicrophoneMute(boolean on, String callingPackage) { 181122c921a910d236abf3a1705a02541a49fdaf3a14Emily Bernier if (mAppOps.noteOp(AppOpsManager.OP_MUTE_MICROPHONE, Binder.getCallingUid(), 181222c921a910d236abf3a1705a02541a49fdaf3a14Emily Bernier callingPackage) != AppOpsManager.MODE_ALLOWED) { 181322c921a910d236abf3a1705a02541a49fdaf3a14Emily Bernier return; 181422c921a910d236abf3a1705a02541a49fdaf3a14Emily Bernier } 18154a4fea0752c8edd33d680765e97ee3b538d777a5Jean-Michel Trivi if (!checkAudioSettingsPermission("setMicrophoneMute()")) { 18164a4fea0752c8edd33d680765e97ee3b538d777a5Jean-Michel Trivi return; 18174a4fea0752c8edd33d680765e97ee3b538d777a5Jean-Michel Trivi } 181822c921a910d236abf3a1705a02541a49fdaf3a14Emily Bernier 181922c921a910d236abf3a1705a02541a49fdaf3a14Emily Bernier AudioSystem.muteMicrophone(on); 1820b53453fae037d67e421011936c8fdffe7ba43922Julia Reynolds // Post a persist microphone msg. 1821b53453fae037d67e421011936c8fdffe7ba43922Julia Reynolds sendMsg(mAudioHandler, MSG_PERSIST_MICROPHONE_MUTE, SENDMSG_REPLACE, on ? 1 1822b53453fae037d67e421011936c8fdffe7ba43922Julia Reynolds : 0, UserHandle.getCallingUserId(), null, PERSIST_DELAY); 182322c921a910d236abf3a1705a02541a49fdaf3a14Emily Bernier } 182422c921a910d236abf3a1705a02541a49fdaf3a14Emily Bernier 1825661f2cf45860d2e10924e6b69966a9afe255f28bJohn Spurlock @Override 1826661f2cf45860d2e10924e6b69966a9afe255f28bJohn Spurlock public int getRingerModeExternal() { 1827661f2cf45860d2e10924e6b69966a9afe255f28bJohn Spurlock synchronized(mSettingsLock) { 1828661f2cf45860d2e10924e6b69966a9afe255f28bJohn Spurlock return mRingerModeExternal; 1829661f2cf45860d2e10924e6b69966a9afe255f28bJohn Spurlock } 1830661f2cf45860d2e10924e6b69966a9afe255f28bJohn Spurlock } 1831661f2cf45860d2e10924e6b69966a9afe255f28bJohn Spurlock 1832661f2cf45860d2e10924e6b69966a9afe255f28bJohn Spurlock @Override 1833661f2cf45860d2e10924e6b69966a9afe255f28bJohn Spurlock public int getRingerModeInternal() { 1834ba195ebc76f23b6679443724ab58c9dc9f2df884Glenn Kasten synchronized(mSettingsLock) { 1835ba195ebc76f23b6679443724ab58c9dc9f2df884Glenn Kasten return mRingerMode; 1836ba195ebc76f23b6679443724ab58c9dc9f2df884Glenn Kasten } 1837ba195ebc76f23b6679443724ab58c9dc9f2df884Glenn Kasten } 1838ba195ebc76f23b6679443724ab58c9dc9f2df884Glenn Kasten 1839ba195ebc76f23b6679443724ab58c9dc9f2df884Glenn Kasten private void ensureValidRingerMode(int ringerMode) { 18409755937ed90f06db45ff5fe4510950ae1516f8f9John Spurlock if (!isValidRingerMode(ringerMode)) { 1841ba195ebc76f23b6679443724ab58c9dc9f2df884Glenn Kasten throw new IllegalArgumentException("Bad ringer mode " + ringerMode); 1842ba195ebc76f23b6679443724ab58c9dc9f2df884Glenn Kasten } 18439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 18449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 18459755937ed90f06db45ff5fe4510950ae1516f8f9John Spurlock /** @see AudioManager#isValidRingerMode(int) */ 18469755937ed90f06db45ff5fe4510950ae1516f8f9John Spurlock public boolean isValidRingerMode(int ringerMode) { 18479755937ed90f06db45ff5fe4510950ae1516f8f9John Spurlock return ringerMode >= 0 && ringerMode <= AudioManager.RINGER_MODE_MAX; 18489755937ed90f06db45ff5fe4510950ae1516f8f9John Spurlock } 18499755937ed90f06db45ff5fe4510950ae1516f8f9John Spurlock 1850661f2cf45860d2e10924e6b69966a9afe255f28bJohn Spurlock public void setRingerModeExternal(int ringerMode, String caller) { 1851af88a19165a1de77948d58b2692c9a7e13712a59John Spurlock setRingerMode(ringerMode, caller, true /*external*/); 1852661f2cf45860d2e10924e6b69966a9afe255f28bJohn Spurlock } 1853661f2cf45860d2e10924e6b69966a9afe255f28bJohn Spurlock 1854661f2cf45860d2e10924e6b69966a9afe255f28bJohn Spurlock public void setRingerModeInternal(int ringerMode, String caller) { 1855661f2cf45860d2e10924e6b69966a9afe255f28bJohn Spurlock enforceSelfOrSystemUI("setRingerModeInternal"); 1856af88a19165a1de77948d58b2692c9a7e13712a59John Spurlock setRingerMode(ringerMode, caller, false /*external*/); 1857661f2cf45860d2e10924e6b69966a9afe255f28bJohn Spurlock } 1858661f2cf45860d2e10924e6b69966a9afe255f28bJohn Spurlock 1859661f2cf45860d2e10924e6b69966a9afe255f28bJohn Spurlock private void setRingerMode(int ringerMode, String caller, boolean external) { 1860212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent if (mUseFixedVolume || isPlatformTelevision()) { 186183a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent return; 186283a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent } 1863661f2cf45860d2e10924e6b69966a9afe255f28bJohn Spurlock if (caller == null || caller.length() == 0) { 1864661f2cf45860d2e10924e6b69966a9afe255f28bJohn Spurlock throw new IllegalArgumentException("Bad caller: " + caller); 1865661f2cf45860d2e10924e6b69966a9afe255f28bJohn Spurlock } 18669755937ed90f06db45ff5fe4510950ae1516f8f9John Spurlock ensureValidRingerMode(ringerMode); 1867244820185269991186d07068b92985624cede4a5Eric Laurent if ((ringerMode == AudioManager.RINGER_MODE_VIBRATE) && !mHasVibrator) { 1868244820185269991186d07068b92985624cede4a5Eric Laurent ringerMode = AudioManager.RINGER_MODE_SILENT; 1869244820185269991186d07068b92985624cede4a5Eric Laurent } 1870af88a19165a1de77948d58b2692c9a7e13712a59John Spurlock final long identity = Binder.clearCallingIdentity(); 1871af88a19165a1de77948d58b2692c9a7e13712a59John Spurlock try { 1872af88a19165a1de77948d58b2692c9a7e13712a59John Spurlock synchronized (mSettingsLock) { 1873af88a19165a1de77948d58b2692c9a7e13712a59John Spurlock final int ringerModeInternal = getRingerModeInternal(); 1874af88a19165a1de77948d58b2692c9a7e13712a59John Spurlock final int ringerModeExternal = getRingerModeExternal(); 1875af88a19165a1de77948d58b2692c9a7e13712a59John Spurlock if (external) { 1876af88a19165a1de77948d58b2692c9a7e13712a59John Spurlock setRingerModeExt(ringerMode); 1877af88a19165a1de77948d58b2692c9a7e13712a59John Spurlock if (mRingerModeDelegate != null) { 1878af88a19165a1de77948d58b2692c9a7e13712a59John Spurlock ringerMode = mRingerModeDelegate.onSetRingerModeExternal(ringerModeExternal, 1879af88a19165a1de77948d58b2692c9a7e13712a59John Spurlock ringerMode, caller, ringerModeInternal); 1880af88a19165a1de77948d58b2692c9a7e13712a59John Spurlock } 1881af88a19165a1de77948d58b2692c9a7e13712a59John Spurlock if (ringerMode != ringerModeInternal) { 1882af88a19165a1de77948d58b2692c9a7e13712a59John Spurlock setRingerModeInt(ringerMode, true /*persist*/); 1883af88a19165a1de77948d58b2692c9a7e13712a59John Spurlock } 1884af88a19165a1de77948d58b2692c9a7e13712a59John Spurlock } else /*internal*/ { 1885af88a19165a1de77948d58b2692c9a7e13712a59John Spurlock if (ringerMode != ringerModeInternal) { 1886af88a19165a1de77948d58b2692c9a7e13712a59John Spurlock setRingerModeInt(ringerMode, true /*persist*/); 1887af88a19165a1de77948d58b2692c9a7e13712a59John Spurlock } 1888af88a19165a1de77948d58b2692c9a7e13712a59John Spurlock if (mRingerModeDelegate != null) { 1889af88a19165a1de77948d58b2692c9a7e13712a59John Spurlock ringerMode = mRingerModeDelegate.onSetRingerModeInternal(ringerModeInternal, 1890af88a19165a1de77948d58b2692c9a7e13712a59John Spurlock ringerMode, caller, ringerModeExternal); 1891af88a19165a1de77948d58b2692c9a7e13712a59John Spurlock } 1892af88a19165a1de77948d58b2692c9a7e13712a59John Spurlock setRingerModeExt(ringerMode); 189357627794b682235afd60adfb235fee46d32f54e2John Spurlock } 1894661f2cf45860d2e10924e6b69966a9afe255f28bJohn Spurlock } 1895af88a19165a1de77948d58b2692c9a7e13712a59John Spurlock } finally { 1896af88a19165a1de77948d58b2692c9a7e13712a59John Spurlock Binder.restoreCallingIdentity(identity); 1897b109615ebebd6f3b9ae789412279f576c3ace46bJason Parekh } 1898b109615ebebd6f3b9ae789412279f576c3ace46bJason Parekh } 18999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1900661f2cf45860d2e10924e6b69966a9afe255f28bJohn Spurlock private void setRingerModeExt(int ringerMode) { 1901661f2cf45860d2e10924e6b69966a9afe255f28bJohn Spurlock synchronized(mSettingsLock) { 1902661f2cf45860d2e10924e6b69966a9afe255f28bJohn Spurlock if (ringerMode == mRingerModeExternal) return; 1903661f2cf45860d2e10924e6b69966a9afe255f28bJohn Spurlock mRingerModeExternal = ringerMode; 1904e5b42d97f6fd3eb0220ea84f21e60d530d93fc46John Spurlock } 1905661f2cf45860d2e10924e6b69966a9afe255f28bJohn Spurlock // Send sticky broadcast 1906bcc1087af40a0e1bb35dbe8a39c830ecdea8280bJohn Spurlock broadcastRingerMode(AudioManager.RINGER_MODE_CHANGED_ACTION, ringerMode); 1907e5b42d97f6fd3eb0220ea84f21e60d530d93fc46John Spurlock } 1908e5b42d97f6fd3eb0220ea84f21e60d530d93fc46John Spurlock 19094050c93601b3c3609b21cc1e18a29b64747e7fa9Eric Laurent private void setRingerModeInt(int ringerMode, boolean persist) { 1910bcc1087af40a0e1bb35dbe8a39c830ecdea8280bJohn Spurlock final boolean change; 1911ba195ebc76f23b6679443724ab58c9dc9f2df884Glenn Kasten synchronized(mSettingsLock) { 1912bcc1087af40a0e1bb35dbe8a39c830ecdea8280bJohn Spurlock change = mRingerMode != ringerMode; 1913ba195ebc76f23b6679443724ab58c9dc9f2df884Glenn Kasten mRingerMode = ringerMode; 1914ba195ebc76f23b6679443724ab58c9dc9f2df884Glenn Kasten } 1915b109615ebebd6f3b9ae789412279f576c3ace46bJason Parekh 19165b4e654d0c7de8e4d58d73e73b0d5220f19b68f7Eric Laurent // Mute stream if not previously muted by ringer mode and ringer mode 19175b4e654d0c7de8e4d58d73e73b0d5220f19b68f7Eric Laurent // is not RINGER_MODE_NORMAL and stream is affected by ringer mode. 19185b4e654d0c7de8e4d58d73e73b0d5220f19b68f7Eric Laurent // Unmute stream if previously muted by ringer mode and ringer mode 19195b4e654d0c7de8e4d58d73e73b0d5220f19b68f7Eric Laurent // is RINGER_MODE_NORMAL or stream is not affected by ringer mode. 1920b109615ebebd6f3b9ae789412279f576c3ace46bJason Parekh int numStreamTypes = AudioSystem.getNumStreamTypes(); 1921661f2cf45860d2e10924e6b69966a9afe255f28bJohn Spurlock final boolean ringerModeMute = ringerMode == AudioManager.RINGER_MODE_VIBRATE 1922661f2cf45860d2e10924e6b69966a9afe255f28bJohn Spurlock || ringerMode == AudioManager.RINGER_MODE_SILENT; 19235b4e654d0c7de8e4d58d73e73b0d5220f19b68f7Eric Laurent for (int streamType = numStreamTypes - 1; streamType >= 0; streamType--) { 1924661f2cf45860d2e10924e6b69966a9afe255f28bJohn Spurlock final boolean isMuted = isStreamMutedByRingerMode(streamType); 1925661f2cf45860d2e10924e6b69966a9afe255f28bJohn Spurlock final boolean shouldMute = ringerModeMute && isStreamAffectedByRingerMode(streamType); 1926661f2cf45860d2e10924e6b69966a9afe255f28bJohn Spurlock if (isMuted == shouldMute) continue; 1927661f2cf45860d2e10924e6b69966a9afe255f28bJohn Spurlock if (!shouldMute) { 1928661f2cf45860d2e10924e6b69966a9afe255f28bJohn Spurlock // unmute 1929661f2cf45860d2e10924e6b69966a9afe255f28bJohn Spurlock // ring and notifications volume should never be 0 when not silenced 1930661f2cf45860d2e10924e6b69966a9afe255f28bJohn Spurlock // on voice capable devices or devices that support vibration 1931661f2cf45860d2e10924e6b69966a9afe255f28bJohn Spurlock if ((isPlatformVoice() || mHasVibrator) && 1932661f2cf45860d2e10924e6b69966a9afe255f28bJohn Spurlock mStreamVolumeAlias[streamType] == AudioSystem.STREAM_RING) { 1933661f2cf45860d2e10924e6b69966a9afe255f28bJohn Spurlock synchronized (VolumeStreamState.class) { 1934661f2cf45860d2e10924e6b69966a9afe255f28bJohn Spurlock Set set = mStreamStates[streamType].mIndex.entrySet(); 1935661f2cf45860d2e10924e6b69966a9afe255f28bJohn Spurlock Iterator i = set.iterator(); 1936661f2cf45860d2e10924e6b69966a9afe255f28bJohn Spurlock while (i.hasNext()) { 1937661f2cf45860d2e10924e6b69966a9afe255f28bJohn Spurlock Map.Entry entry = (Map.Entry)i.next(); 1938661f2cf45860d2e10924e6b69966a9afe255f28bJohn Spurlock if ((Integer)entry.getValue() == 0) { 1939661f2cf45860d2e10924e6b69966a9afe255f28bJohn Spurlock entry.setValue(10); 19409bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent } 19419bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent } 1942b024c30a80684ac08daef3137b7ba0d347fe3ce5Eric Laurent } 19439bcf401d13d47416043a704430388abd59aef7cdEric Laurent } 1944661f2cf45860d2e10924e6b69966a9afe255f28bJohn Spurlock mStreamStates[streamType].mute(null, false); 1945661f2cf45860d2e10924e6b69966a9afe255f28bJohn Spurlock mRingerModeMutedStreams &= ~(1 << streamType); 19465b4e654d0c7de8e4d58d73e73b0d5220f19b68f7Eric Laurent } else { 1947661f2cf45860d2e10924e6b69966a9afe255f28bJohn Spurlock // mute 1948661f2cf45860d2e10924e6b69966a9afe255f28bJohn Spurlock mStreamStates[streamType].mute(null, true); 1949661f2cf45860d2e10924e6b69966a9afe255f28bJohn Spurlock mRingerModeMutedStreams |= (1 << streamType); 1950b109615ebebd6f3b9ae789412279f576c3ace46bJason Parekh } 19519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1952a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent 1953b109615ebebd6f3b9ae789412279f576c3ace46bJason Parekh // Post a persist ringer mode msg 19544050c93601b3c3609b21cc1e18a29b64747e7fa9Eric Laurent if (persist) { 1955afbb047c3945e9c2b7e9bc6b25098d5fb80bba4eEric Laurent sendMsg(mAudioHandler, MSG_PERSIST_RINGER_MODE, 19564050c93601b3c3609b21cc1e18a29b64747e7fa9Eric Laurent SENDMSG_REPLACE, 0, 0, null, PERSIST_DELAY); 19574050c93601b3c3609b21cc1e18a29b64747e7fa9Eric Laurent } 1958bcc1087af40a0e1bb35dbe8a39c830ecdea8280bJohn Spurlock if (change) { 1959bcc1087af40a0e1bb35dbe8a39c830ecdea8280bJohn Spurlock // Send sticky broadcast 1960bcc1087af40a0e1bb35dbe8a39c830ecdea8280bJohn Spurlock broadcastRingerMode(AudioManager.INTERNAL_RINGER_MODE_CHANGED_ACTION, ringerMode); 1961bcc1087af40a0e1bb35dbe8a39c830ecdea8280bJohn Spurlock } 19629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 19639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 19649063154a793b0ab38b3c5992cbaed046427b4a82Mike Lockwood private void restoreMasterVolume() { 196583a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent if (mUseFixedVolume) { 196683a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent AudioSystem.setMasterVolume(1.0f); 196783a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent return; 196883a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent } 19699063154a793b0ab38b3c5992cbaed046427b4a82Mike Lockwood if (mUseMasterVolume) { 1970bc0fab1fc2db832ef86d8a33466ec4d68b103ca0Eric Laurent float volume = Settings.System.getFloatForUser(mContentResolver, 1971bc0fab1fc2db832ef86d8a33466ec4d68b103ca0Eric Laurent Settings.System.VOLUME_MASTER, -1.0f, UserHandle.USER_CURRENT); 19729063154a793b0ab38b3c5992cbaed046427b4a82Mike Lockwood if (volume >= 0.0f) { 19739063154a793b0ab38b3c5992cbaed046427b4a82Mike Lockwood AudioSystem.setMasterVolume(volume); 19749063154a793b0ab38b3c5992cbaed046427b4a82Mike Lockwood } 19759063154a793b0ab38b3c5992cbaed046427b4a82Mike Lockwood } 19769063154a793b0ab38b3c5992cbaed046427b4a82Mike Lockwood } 19779063154a793b0ab38b3c5992cbaed046427b4a82Mike Lockwood 19789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** @see AudioManager#shouldVibrate(int) */ 19799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public boolean shouldVibrate(int vibrateType) { 1980bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent if (!mHasVibrator) return false; 19819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 19829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project switch (getVibrateSetting(vibrateType)) { 19839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 19849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case AudioManager.VIBRATE_SETTING_ON: 198557627794b682235afd60adfb235fee46d32f54e2John Spurlock return getRingerModeExternal() != AudioManager.RINGER_MODE_SILENT; 19869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 19879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case AudioManager.VIBRATE_SETTING_ONLY_SILENT: 198857627794b682235afd60adfb235fee46d32f54e2John Spurlock return getRingerModeExternal() == AudioManager.RINGER_MODE_VIBRATE; 19899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 19909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case AudioManager.VIBRATE_SETTING_OFF: 1991bcac496076ef6f439147e7a2be71e8a2b76ddedeDaniel Sandler // return false, even for incoming calls 1992bcac496076ef6f439147e7a2be71e8a2b76ddedeDaniel Sandler return false; 19939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 19949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project default: 19959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 19969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 19979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 19989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 19999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** @see AudioManager#getVibrateSetting(int) */ 20009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int getVibrateSetting(int vibrateType) { 2001bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent if (!mHasVibrator) return AudioManager.VIBRATE_SETTING_OFF; 20029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return (mVibrateSetting >> (vibrateType * 2)) & 3; 20039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 20049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 20059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** @see AudioManager#setVibrateSetting(int, int) */ 20069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void setVibrateSetting(int vibrateType, int vibrateSetting) { 20079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2008bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent if (!mHasVibrator) return; 2009bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent 20109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mVibrateSetting = getValueForVibrateSetting(mVibrateSetting, vibrateType, vibrateSetting); 20119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 20129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Broadcast change 20139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project broadcastVibrateSetting(vibrateType); 20149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 20159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 20169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 20179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 20189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @see #setVibrateSetting(int, int) 20199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 20209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static int getValueForVibrateSetting(int existingValue, int vibrateType, 20219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int vibrateSetting) { 20229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 20239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // First clear the existing setting. Each vibrate type has two bits in 20249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // the value. Note '3' is '11' in binary. 20259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project existingValue &= ~(3 << (vibrateType * 2)); 20269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 20279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Set into the old value 20289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project existingValue |= (vibrateSetting & 3) << (vibrateType * 2); 20299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 20309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return existingValue; 20319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 20329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 20339272b4b4a44fe1f33e3030810618194f817caaecEric Laurent private class SetModeDeathHandler implements IBinder.DeathRecipient { 20349272b4b4a44fe1f33e3030810618194f817caaecEric Laurent private IBinder mCb; // To be notified of client's death 2035f1ddd51f9cd2f92b922bc636c307210a8d587c25Marco Nelissen private int mPid; 20369272b4b4a44fe1f33e3030810618194f817caaecEric Laurent private int mMode = AudioSystem.MODE_NORMAL; // Current mode set by this client 20379272b4b4a44fe1f33e3030810618194f817caaecEric Laurent 20389f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent SetModeDeathHandler(IBinder cb, int pid) { 20399272b4b4a44fe1f33e3030810618194f817caaecEric Laurent mCb = cb; 20409f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent mPid = pid; 20419272b4b4a44fe1f33e3030810618194f817caaecEric Laurent } 20429272b4b4a44fe1f33e3030810618194f817caaecEric Laurent 20439272b4b4a44fe1f33e3030810618194f817caaecEric Laurent public void binderDied() { 2044d7454be47f4111c0478a502353e11dea401378bdEric Laurent int newModeOwnerPid = 0; 20459272b4b4a44fe1f33e3030810618194f817caaecEric Laurent synchronized(mSetModeDeathHandlers) { 20469272b4b4a44fe1f33e3030810618194f817caaecEric Laurent Log.w(TAG, "setMode() client died"); 20479272b4b4a44fe1f33e3030810618194f817caaecEric Laurent int index = mSetModeDeathHandlers.indexOf(this); 20489272b4b4a44fe1f33e3030810618194f817caaecEric Laurent if (index < 0) { 20499272b4b4a44fe1f33e3030810618194f817caaecEric Laurent Log.w(TAG, "unregistered setMode() client died"); 20509272b4b4a44fe1f33e3030810618194f817caaecEric Laurent } else { 2051d7454be47f4111c0478a502353e11dea401378bdEric Laurent newModeOwnerPid = setModeInt(AudioSystem.MODE_NORMAL, mCb, mPid); 20529272b4b4a44fe1f33e3030810618194f817caaecEric Laurent } 20539272b4b4a44fe1f33e3030810618194f817caaecEric Laurent } 20549f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent // when entering RINGTONE, IN_CALL or IN_COMMUNICATION mode, clear all 20559f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent // SCO connections not started by the application changing the mode 2056d7454be47f4111c0478a502353e11dea401378bdEric Laurent if (newModeOwnerPid != 0) { 20576b5e22d52c69cb6d80ff09bd32395b0034ada343Eric Laurent final long ident = Binder.clearCallingIdentity(); 20586b5e22d52c69cb6d80ff09bd32395b0034ada343Eric Laurent disconnectBluetoothSco(newModeOwnerPid); 20596b5e22d52c69cb6d80ff09bd32395b0034ada343Eric Laurent Binder.restoreCallingIdentity(ident); 20609f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent } 20619272b4b4a44fe1f33e3030810618194f817caaecEric Laurent } 20629272b4b4a44fe1f33e3030810618194f817caaecEric Laurent 2063f1ddd51f9cd2f92b922bc636c307210a8d587c25Marco Nelissen public int getPid() { 2064f1ddd51f9cd2f92b922bc636c307210a8d587c25Marco Nelissen return mPid; 2065f1ddd51f9cd2f92b922bc636c307210a8d587c25Marco Nelissen } 2066f1ddd51f9cd2f92b922bc636c307210a8d587c25Marco Nelissen 20679272b4b4a44fe1f33e3030810618194f817caaecEric Laurent public void setMode(int mode) { 20689272b4b4a44fe1f33e3030810618194f817caaecEric Laurent mMode = mode; 20699272b4b4a44fe1f33e3030810618194f817caaecEric Laurent } 20709272b4b4a44fe1f33e3030810618194f817caaecEric Laurent 20719272b4b4a44fe1f33e3030810618194f817caaecEric Laurent public int getMode() { 20729272b4b4a44fe1f33e3030810618194f817caaecEric Laurent return mMode; 20739272b4b4a44fe1f33e3030810618194f817caaecEric Laurent } 20749272b4b4a44fe1f33e3030810618194f817caaecEric Laurent 20759272b4b4a44fe1f33e3030810618194f817caaecEric Laurent public IBinder getBinder() { 20769272b4b4a44fe1f33e3030810618194f817caaecEric Laurent return mCb; 20779272b4b4a44fe1f33e3030810618194f817caaecEric Laurent } 20789272b4b4a44fe1f33e3030810618194f817caaecEric Laurent } 20799272b4b4a44fe1f33e3030810618194f817caaecEric Laurent 20809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** @see AudioManager#setMode(int) */ 20819272b4b4a44fe1f33e3030810618194f817caaecEric Laurent public void setMode(int mode, IBinder cb) { 2082339567d5c91a8dc9228913ed1e5deb0ebb8a4a64Jean-Michel Trivi if (DEBUG_MODE) { Log.v(TAG, "setMode(mode=" + mode + ")"); } 20839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!checkAudioSettingsPermission("setMode()")) { 20849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 20859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2086a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent 2087ccd654e9d4c38da0d652c442e7a2ca3f447e9abeJean-Michel Trivi if ( (mode == AudioSystem.MODE_IN_CALL) && 2088ccd654e9d4c38da0d652c442e7a2ca3f447e9abeJean-Michel Trivi (mContext.checkCallingOrSelfPermission( 2089ccd654e9d4c38da0d652c442e7a2ca3f447e9abeJean-Michel Trivi android.Manifest.permission.MODIFY_PHONE_STATE) 2090ccd654e9d4c38da0d652c442e7a2ca3f447e9abeJean-Michel Trivi != PackageManager.PERMISSION_GRANTED)) { 2091ccd654e9d4c38da0d652c442e7a2ca3f447e9abeJean-Michel Trivi Log.w(TAG, "MODIFY_PHONE_STATE Permission Denial: setMode(MODE_IN_CALL) from pid=" 2092ccd654e9d4c38da0d652c442e7a2ca3f447e9abeJean-Michel Trivi + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid()); 2093ccd654e9d4c38da0d652c442e7a2ca3f447e9abeJean-Michel Trivi return; 2094ccd654e9d4c38da0d652c442e7a2ca3f447e9abeJean-Michel Trivi } 2095ccd654e9d4c38da0d652c442e7a2ca3f447e9abeJean-Michel Trivi 20968f677d66d9c3ba34c97e69b2bb9e161f129af0eeJean-Michel Trivi if (mode < AudioSystem.MODE_CURRENT || mode >= AudioSystem.NUM_MODES) { 2097a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent return; 2098a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent } 2099a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent 2100d7454be47f4111c0478a502353e11dea401378bdEric Laurent int newModeOwnerPid = 0; 21019f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent synchronized(mSetModeDeathHandlers) { 2102a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent if (mode == AudioSystem.MODE_CURRENT) { 2103a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent mode = mMode; 2104a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent } 2105d7454be47f4111c0478a502353e11dea401378bdEric Laurent newModeOwnerPid = setModeInt(mode, cb, Binder.getCallingPid()); 21069f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent } 21079f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent // when entering RINGTONE, IN_CALL or IN_COMMUNICATION mode, clear all 21089f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent // SCO connections not started by the application changing the mode 2109d7454be47f4111c0478a502353e11dea401378bdEric Laurent if (newModeOwnerPid != 0) { 2110d7454be47f4111c0478a502353e11dea401378bdEric Laurent disconnectBluetoothSco(newModeOwnerPid); 21119f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent } 21129f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent } 21132ade576148fe33c5ff6098d30ccfbcf28df70e8eJean-Michel Trivi 21149f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent // must be called synchronized on mSetModeDeathHandlers 2115d7454be47f4111c0478a502353e11dea401378bdEric Laurent // setModeInt() returns a valid PID if the audio mode was successfully set to 21169f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent // any mode other than NORMAL. 2117ccd654e9d4c38da0d652c442e7a2ca3f447e9abeJean-Michel Trivi private int setModeInt(int mode, IBinder cb, int pid) { 2118339567d5c91a8dc9228913ed1e5deb0ebb8a4a64Jean-Michel Trivi if (DEBUG_MODE) { Log.v(TAG, "setModeInt(mode=" + mode + ", pid=" + pid + ")"); } 2119d7454be47f4111c0478a502353e11dea401378bdEric Laurent int newModeOwnerPid = 0; 21209f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent if (cb == null) { 21219f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent Log.e(TAG, "setModeInt() called with null binder"); 2122d7454be47f4111c0478a502353e11dea401378bdEric Laurent return newModeOwnerPid; 21239f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent } 21242ade576148fe33c5ff6098d30ccfbcf28df70e8eJean-Michel Trivi 21259f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent SetModeDeathHandler hdlr = null; 21269f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent Iterator iter = mSetModeDeathHandlers.iterator(); 21279f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent while (iter.hasNext()) { 21289f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent SetModeDeathHandler h = (SetModeDeathHandler)iter.next(); 21299f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent if (h.getPid() == pid) { 21309f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent hdlr = h; 21319f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent // Remove from client list so that it is re-inserted at top of list 21329f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent iter.remove(); 21339f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent hdlr.getBinder().unlinkToDeath(hdlr, 0); 21349f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent break; 21359f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent } 21369f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent } 21379f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent int status = AudioSystem.AUDIO_STATUS_OK; 21389f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent do { 21399f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent if (mode == AudioSystem.MODE_NORMAL) { 21409f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent // get new mode from client at top the list if any 21419f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent if (!mSetModeDeathHandlers.isEmpty()) { 21429f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent hdlr = mSetModeDeathHandlers.get(0); 21439f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent cb = hdlr.getBinder(); 21449f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent mode = hdlr.getMode(); 2145339567d5c91a8dc9228913ed1e5deb0ebb8a4a64Jean-Michel Trivi if (DEBUG_MODE) { 2146339567d5c91a8dc9228913ed1e5deb0ebb8a4a64Jean-Michel Trivi Log.w(TAG, " using mode=" + mode + " instead due to death hdlr at pid=" 2147339567d5c91a8dc9228913ed1e5deb0ebb8a4a64Jean-Michel Trivi + hdlr.mPid); 2148339567d5c91a8dc9228913ed1e5deb0ebb8a4a64Jean-Michel Trivi } 21499f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent } 21509f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent } else { 21519f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent if (hdlr == null) { 21529f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent hdlr = new SetModeDeathHandler(cb, pid); 21539f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent } 21549f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent // Register for client death notification 21559f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent try { 21569f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent cb.linkToDeath(hdlr, 0); 21579f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent } catch (RemoteException e) { 21589f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent // Client has died! 21599f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent Log.w(TAG, "setMode() could not link to "+cb+" binder death"); 21609f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent } 21619272b4b4a44fe1f33e3030810618194f817caaecEric Laurent 21629f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent // Last client to call setMode() is always at top of client list 21639f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent // as required by SetModeDeathHandler.binderDied() 21649f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent mSetModeDeathHandlers.add(0, hdlr); 21659f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent hdlr.setMode(mode); 21669f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent } 21673def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent 21689f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent if (mode != mMode) { 21699f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent status = AudioSystem.setPhoneState(mode); 21709f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent if (status == AudioSystem.AUDIO_STATUS_OK) { 2171339567d5c91a8dc9228913ed1e5deb0ebb8a4a64Jean-Michel Trivi if (DEBUG_MODE) { Log.v(TAG, " mode successfully set to " + mode); } 21729f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent mMode = mode; 21739f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent } else { 21749f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent if (hdlr != null) { 21759f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent mSetModeDeathHandlers.remove(hdlr); 21769f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent cb.unlinkToDeath(hdlr, 0); 21773def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent } 21789f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent // force reading new top of mSetModeDeathHandlers stack 2179339567d5c91a8dc9228913ed1e5deb0ebb8a4a64Jean-Michel Trivi if (DEBUG_MODE) { Log.w(TAG, " mode set to MODE_NORMAL after phoneState pb"); } 21809f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent mode = AudioSystem.MODE_NORMAL; 2181b9c9d260f21b321527c4622a123af9767630d94dEric Laurent } 21829f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent } else { 21839f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent status = AudioSystem.AUDIO_STATUS_OK; 21849f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent } 21859f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent } while (status != AudioSystem.AUDIO_STATUS_OK && !mSetModeDeathHandlers.isEmpty()); 21869f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent 21879f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent if (status == AudioSystem.AUDIO_STATUS_OK) { 21889f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent if (mode != AudioSystem.MODE_NORMAL) { 2189d7454be47f4111c0478a502353e11dea401378bdEric Laurent if (mSetModeDeathHandlers.isEmpty()) { 2190d7454be47f4111c0478a502353e11dea401378bdEric Laurent Log.e(TAG, "setMode() different from MODE_NORMAL with empty mode client stack"); 2191d7454be47f4111c0478a502353e11dea401378bdEric Laurent } else { 2192d7454be47f4111c0478a502353e11dea401378bdEric Laurent newModeOwnerPid = mSetModeDeathHandlers.get(0).getPid(); 2193d7454be47f4111c0478a502353e11dea401378bdEric Laurent } 21949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 21959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int streamType = getActiveStreamType(AudioManager.USE_DEFAULT_STREAM_TYPE); 21969bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent int device = getDeviceForStream(streamType); 219742b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent int index = mStreamStates[mStreamVolumeAlias[streamType]].getIndex(device); 219842b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent setStreamVolumeInt(mStreamVolumeAlias[streamType], index, device, true); 21996d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent 22006d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent updateStreamVolumeAlias(true /*updateVolumes*/); 22019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2202d7454be47f4111c0478a502353e11dea401378bdEric Laurent return newModeOwnerPid; 22039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 22049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 22059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** @see AudioManager#getMode() */ 22069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int getMode() { 22079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mMode; 22089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 22099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2210e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent //========================================================================================== 2211e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent // Sound Effects 2212e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent //========================================================================================== 2213e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent 2214e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent private static final String TAG_AUDIO_ASSETS = "audio_assets"; 2215e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent private static final String ATTR_VERSION = "version"; 2216e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent private static final String TAG_GROUP = "group"; 2217e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent private static final String ATTR_GROUP_NAME = "name"; 2218e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent private static final String TAG_ASSET = "asset"; 2219e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent private static final String ATTR_ASSET_ID = "id"; 2220e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent private static final String ATTR_ASSET_FILE = "file"; 2221e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent 2222e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent private static final String ASSET_FILE_VERSION = "1.0"; 2223e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent private static final String GROUP_TOUCH_SOUNDS = "touch_sounds"; 2224e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent 2225167d1a27713ab64cd3c0aa70de96434083ef0400Glenn Kasten private static final int SOUND_EFFECTS_LOAD_TIMEOUT_MS = 5000; 22265d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent 22275d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent class LoadSoundEffectReply { 22285d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent public int mStatus = 1; 22295d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent }; 22305d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent 2231e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent private void loadTouchSoundAssetDefaults() { 2232e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent SOUND_EFFECT_FILES.add("Effect_Tick.ogg"); 2233e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent for (int i = 0; i < AudioManager.NUM_SOUND_EFFECTS; i++) { 2234e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent SOUND_EFFECT_FILES_MAP[i][0] = 0; 2235e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent SOUND_EFFECT_FILES_MAP[i][1] = -1; 2236e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent } 2237e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent } 2238e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent 2239e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent private void loadTouchSoundAssets() { 2240e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent XmlResourceParser parser = null; 2241e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent 22425d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent // only load assets once. 22435d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent if (!SOUND_EFFECT_FILES.isEmpty()) { 22445d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent return; 22455d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent } 22465d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent 2247e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent loadTouchSoundAssetDefaults(); 2248e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent 2249e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent try { 2250e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent parser = mContext.getResources().getXml(com.android.internal.R.xml.audio_assets); 2251e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent 2252e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent XmlUtils.beginDocument(parser, TAG_AUDIO_ASSETS); 2253e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent String version = parser.getAttributeValue(null, ATTR_VERSION); 2254e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent boolean inTouchSoundsGroup = false; 2255e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent 2256e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent if (ASSET_FILE_VERSION.equals(version)) { 2257e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent while (true) { 2258e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent XmlUtils.nextElement(parser); 2259e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent String element = parser.getName(); 2260e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent if (element == null) { 2261e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent break; 2262e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent } 2263e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent if (element.equals(TAG_GROUP)) { 2264e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent String name = parser.getAttributeValue(null, ATTR_GROUP_NAME); 2265e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent if (GROUP_TOUCH_SOUNDS.equals(name)) { 2266e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent inTouchSoundsGroup = true; 2267e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent break; 2268e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent } 2269e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent } 2270e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent } 2271e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent while (inTouchSoundsGroup) { 2272e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent XmlUtils.nextElement(parser); 2273e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent String element = parser.getName(); 2274e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent if (element == null) { 2275e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent break; 2276e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent } 2277e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent if (element.equals(TAG_ASSET)) { 2278e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent String id = parser.getAttributeValue(null, ATTR_ASSET_ID); 2279e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent String file = parser.getAttributeValue(null, ATTR_ASSET_FILE); 2280e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent int fx; 2281e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent 2282e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent try { 2283e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent Field field = AudioManager.class.getField(id); 2284e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent fx = field.getInt(null); 2285e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent } catch (Exception e) { 2286e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent Log.w(TAG, "Invalid touch sound ID: "+id); 2287e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent continue; 2288e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent } 2289e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent 2290e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent int i = SOUND_EFFECT_FILES.indexOf(file); 2291e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent if (i == -1) { 2292e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent i = SOUND_EFFECT_FILES.size(); 2293e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent SOUND_EFFECT_FILES.add(file); 2294e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent } 2295e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent SOUND_EFFECT_FILES_MAP[fx][0] = i; 2296e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent } else { 2297e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent break; 2298e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent } 2299e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent } 2300e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent } 2301e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent } catch (Resources.NotFoundException e) { 2302e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent Log.w(TAG, "audio assets file not found", e); 2303e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent } catch (XmlPullParserException e) { 2304e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent Log.w(TAG, "XML parser exception reading touch sound assets", e); 2305e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent } catch (IOException e) { 2306e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent Log.w(TAG, "I/O exception reading touch sound assets", e); 2307e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent } finally { 2308e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent if (parser != null) { 2309e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent parser.close(); 2310e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent } 2311e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent } 2312e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent } 2313e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent 23149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** @see AudioManager#playSoundEffect(int) */ 23159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void playSoundEffect(int effectType) { 23165d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent playSoundEffectVolume(effectType, -1.0f); 23179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 23189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 23199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** @see AudioManager#playSoundEffect(int, float) */ 23209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void playSoundEffectVolume(int effectType, float volume) { 2321559c76dbc37ff25b204ed1f060d3ec2fa43d718cNatalie Silvanovich if (effectType >= AudioManager.NUM_SOUND_EFFECTS || effectType < 0) { 2322559c76dbc37ff25b204ed1f060d3ec2fa43d718cNatalie Silvanovich Log.w(TAG, "AudioService effectType value " + effectType + " out of range"); 2323559c76dbc37ff25b204ed1f060d3ec2fa43d718cNatalie Silvanovich return; 2324559c76dbc37ff25b204ed1f060d3ec2fa43d718cNatalie Silvanovich } 2325559c76dbc37ff25b204ed1f060d3ec2fa43d718cNatalie Silvanovich 23265d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent sendMsg(mAudioHandler, MSG_PLAY_SOUND_EFFECT, SENDMSG_QUEUE, 23279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project effectType, (int) (volume * 1000), null, 0); 23289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 23299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 23309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 23319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Loads samples into the soundpool. 23325c17a820f9e46e0756c11795b3e6f89105f2f539Glenn Kasten * This method must be called at first when sound effects are enabled 23339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 23349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public boolean loadSoundEffects() { 23355d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent int attempts = 3; 23365d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent LoadSoundEffectReply reply = new LoadSoundEffectReply(); 2337117b7bb5b5a4457711f59bde3dcc83d8f111c524Eric Laurent 23385d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent synchronized (reply) { 23395d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent sendMsg(mAudioHandler, MSG_LOAD_SOUND_EFFECTS, SENDMSG_QUEUE, 0, 0, reply, 0); 23405d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent while ((reply.mStatus == 1) && (attempts-- > 0)) { 2341117b7bb5b5a4457711f59bde3dcc83d8f111c524Eric Laurent try { 2342167d1a27713ab64cd3c0aa70de96434083ef0400Glenn Kasten reply.wait(SOUND_EFFECTS_LOAD_TIMEOUT_MS); 23435d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent } catch (InterruptedException e) { 23445d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent Log.w(TAG, "loadSoundEffects Interrupted while waiting sound pool loaded."); 2345117b7bb5b5a4457711f59bde3dcc83d8f111c524Eric Laurent } 2346a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent } 23479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 23485d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent return (reply.mStatus == 0); 23499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 23509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 23519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 23529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Unloads samples from the sound pool. 23539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * This method can be called to free some memory when 23549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * sound effects are disabled. 23559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 23569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void unloadSoundEffects() { 23575d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent sendMsg(mAudioHandler, MSG_UNLOAD_SOUND_EFFECTS, SENDMSG_QUEUE, 0, 0, null, 0); 23589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 23599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2360a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent class SoundPoolListenerThread extends Thread { 2361a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent public SoundPoolListenerThread() { 2362a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent super("SoundPoolListenerThread"); 2363a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent } 2364a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent 2365a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent @Override 2366a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent public void run() { 2367a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent 2368a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent Looper.prepare(); 2369a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent mSoundPoolLooper = Looper.myLooper(); 2370a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent 2371a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent synchronized (mSoundEffectsLock) { 2372a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent if (mSoundPool != null) { 2373a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent mSoundPoolCallBack = new SoundPoolCallback(); 2374a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent mSoundPool.setOnLoadCompleteListener(mSoundPoolCallBack); 2375a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent } 2376a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent mSoundEffectsLock.notify(); 2377a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent } 2378a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent Looper.loop(); 2379a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent } 2380a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent } 2381a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent 2382a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent private final class SoundPoolCallback implements 2383a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent android.media.SoundPool.OnLoadCompleteListener { 2384a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent 23855d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent int mStatus = 1; // 1 means neither error nor last sample loaded yet 23865d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent List<Integer> mSamples = new ArrayList<Integer>(); 2387a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent 2388a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent public int status() { 2389a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent return mStatus; 2390a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent } 2391a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent 23925d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent public void setSamples(int[] samples) { 23935d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent for (int i = 0; i < samples.length; i++) { 23945d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent // do not wait ack for samples rejected upfront by SoundPool 23955d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent if (samples[i] > 0) { 23965d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent mSamples.add(samples[i]); 23975d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent } 23985d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent } 2399a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent } 2400a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent 2401a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent public void onLoadComplete(SoundPool soundPool, int sampleId, int status) { 2402a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent synchronized (mSoundEffectsLock) { 24035d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent int i = mSamples.indexOf(sampleId); 24045d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent if (i >= 0) { 24055d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent mSamples.remove(i); 2406a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent } 24075d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent if ((status != 0) || mSamples. isEmpty()) { 24085d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent mStatus = status; 2409a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent mSoundEffectsLock.notify(); 2410a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent } 2411a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent } 2412a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent } 2413a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent } 2414a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent 24154050c93601b3c3609b21cc1e18a29b64747e7fa9Eric Laurent /** @see AudioManager#reloadAudioSettings() */ 24164050c93601b3c3609b21cc1e18a29b64747e7fa9Eric Laurent public void reloadAudioSettings() { 2417bc0fab1fc2db832ef86d8a33466ec4d68b103ca0Eric Laurent readAudioSettings(false /*userSwitch*/); 2418bc0fab1fc2db832ef86d8a33466ec4d68b103ca0Eric Laurent } 2419bc0fab1fc2db832ef86d8a33466ec4d68b103ca0Eric Laurent 2420bc0fab1fc2db832ef86d8a33466ec4d68b103ca0Eric Laurent private void readAudioSettings(boolean userSwitch) { 24214050c93601b3c3609b21cc1e18a29b64747e7fa9Eric Laurent // restore ringer mode, ringer mode affected streams, mute affected streams and vibrate settings 24224050c93601b3c3609b21cc1e18a29b64747e7fa9Eric Laurent readPersistedSettings(); 24234050c93601b3c3609b21cc1e18a29b64747e7fa9Eric Laurent 24244050c93601b3c3609b21cc1e18a29b64747e7fa9Eric Laurent // restore volume settings 24254050c93601b3c3609b21cc1e18a29b64747e7fa9Eric Laurent int numStreamTypes = AudioSystem.getNumStreamTypes(); 24264050c93601b3c3609b21cc1e18a29b64747e7fa9Eric Laurent for (int streamType = 0; streamType < numStreamTypes; streamType++) { 24274050c93601b3c3609b21cc1e18a29b64747e7fa9Eric Laurent VolumeStreamState streamState = mStreamStates[streamType]; 24284050c93601b3c3609b21cc1e18a29b64747e7fa9Eric Laurent 2429bc0fab1fc2db832ef86d8a33466ec4d68b103ca0Eric Laurent if (userSwitch && mStreamVolumeAlias[streamType] == AudioSystem.STREAM_MUSIC) { 2430bc0fab1fc2db832ef86d8a33466ec4d68b103ca0Eric Laurent continue; 2431bc0fab1fc2db832ef86d8a33466ec4d68b103ca0Eric Laurent } 2432bc0fab1fc2db832ef86d8a33466ec4d68b103ca0Eric Laurent 24338fa4d6f585f40ff5cf5f9bed316d92c64a306f21Eric Laurent streamState.readSettings(); 24348fa4d6f585f40ff5cf5f9bed316d92c64a306f21Eric Laurent synchronized (VolumeStreamState.class) { 24353172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent // unmute stream that was muted but is not affect by mute anymore 24368fa4d6f585f40ff5cf5f9bed316d92c64a306f21Eric Laurent if (streamState.isMuted_syncVSS() && ((!isStreamAffectedByMute(streamType) && 243783a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent !isStreamMutedByRingerMode(streamType)) || mUseFixedVolume)) { 24383172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent int size = streamState.mDeathHandlers.size(); 24393172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent for (int i = 0; i < size; i++) { 24403172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent streamState.mDeathHandlers.get(i).mMuteCount = 1; 24418fa4d6f585f40ff5cf5f9bed316d92c64a306f21Eric Laurent streamState.mDeathHandlers.get(i).mute_syncVSS(false); 24423172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent } 24433172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent } 24444050c93601b3c3609b21cc1e18a29b64747e7fa9Eric Laurent } 24454050c93601b3c3609b21cc1e18a29b64747e7fa9Eric Laurent } 24464050c93601b3c3609b21cc1e18a29b64747e7fa9Eric Laurent 244733902db75011d863009585682bd08560c5b89a75Eric Laurent // apply new ringer mode before checking volume for alias streams so that streams 244833902db75011d863009585682bd08560c5b89a75Eric Laurent // muted by ringer mode have the correct volume 2449661f2cf45860d2e10924e6b69966a9afe255f28bJohn Spurlock setRingerModeInt(getRingerModeInternal(), false); 245033902db75011d863009585682bd08560c5b89a75Eric Laurent 2451212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent checkAllFixedVolumeDevices(); 2452244820185269991186d07068b92985624cede4a5Eric Laurent checkAllAliasStreamVolumes(); 2453244820185269991186d07068b92985624cede4a5Eric Laurent 2454d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent synchronized (mSafeMediaVolumeState) { 2455aa5ee4d65f8788e2a0afcd198367450853fd72acJohn Spurlock mMusicActiveMs = MathUtils.constrain(Settings.Secure.getIntForUser(mContentResolver, 2456aa5ee4d65f8788e2a0afcd198367450853fd72acJohn Spurlock Settings.Secure.UNSAFE_VOLUME_MUSIC_ACTIVE_MS, 0, UserHandle.USER_CURRENT), 2457aa5ee4d65f8788e2a0afcd198367450853fd72acJohn Spurlock 0, UNSAFE_VOLUME_MUSIC_ACTIVE_MS_MAX); 2458d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent if (mSafeMediaVolumeState == SAFE_MEDIA_VOLUME_ACTIVE) { 2459f1a457d06c53a901ea08d2d3fb6e766bc06c4d4fEric Laurent enforceSafeMediaVolume(); 2460f1a457d06c53a901ea08d2d3fb6e766bc06c4d4fEric Laurent } 2461c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent } 24624050c93601b3c3609b21cc1e18a29b64747e7fa9Eric Laurent } 24634050c93601b3c3609b21cc1e18a29b64747e7fa9Eric Laurent 2464961cae92540763226648813d111c5b5c3b0f1597Dianne Hackborn /** @see AudioManager#setSpeakerphoneOn(boolean) */ 2465c42ac9d4d03f62c3a1ba197a28a81fda44bd8b7fEric Laurent public void setSpeakerphoneOn(boolean on){ 2466dc1d17a1dbfc2ae01c20012133a836b62f5b6930Eric Laurent if (!checkAudioSettingsPermission("setSpeakerphoneOn()")) { 2467dc1d17a1dbfc2ae01c20012133a836b62f5b6930Eric Laurent return; 2468dc1d17a1dbfc2ae01c20012133a836b62f5b6930Eric Laurent } 24697337bee7839238f244fad31112a45389f6ef907cJohan Gustavsson 24707337bee7839238f244fad31112a45389f6ef907cJohan Gustavsson if (on) { 24717337bee7839238f244fad31112a45389f6ef907cJohan Gustavsson if (mForcedUseForComm == AudioSystem.FORCE_BT_SCO) { 24727337bee7839238f244fad31112a45389f6ef907cJohan Gustavsson sendMsg(mAudioHandler, MSG_SET_FORCE_USE, SENDMSG_QUEUE, 24737337bee7839238f244fad31112a45389f6ef907cJohan Gustavsson AudioSystem.FOR_RECORD, AudioSystem.FORCE_NONE, null, 0); 24747337bee7839238f244fad31112a45389f6ef907cJohan Gustavsson } 24757337bee7839238f244fad31112a45389f6ef907cJohan Gustavsson mForcedUseForComm = AudioSystem.FORCE_SPEAKER; 24767337bee7839238f244fad31112a45389f6ef907cJohan Gustavsson } else if (mForcedUseForComm == AudioSystem.FORCE_SPEAKER){ 24777337bee7839238f244fad31112a45389f6ef907cJohan Gustavsson mForcedUseForComm = AudioSystem.FORCE_NONE; 24787337bee7839238f244fad31112a45389f6ef907cJohan Gustavsson } 2479fa640154f1f42121d81242b2f1a10f03e52f0014Eric Laurent 2480afbb047c3945e9c2b7e9bc6b25098d5fb80bba4eEric Laurent sendMsg(mAudioHandler, MSG_SET_FORCE_USE, SENDMSG_QUEUE, 2481fa640154f1f42121d81242b2f1a10f03e52f0014Eric Laurent AudioSystem.FOR_COMMUNICATION, mForcedUseForComm, null, 0); 2482c42ac9d4d03f62c3a1ba197a28a81fda44bd8b7fEric Laurent } 2483c42ac9d4d03f62c3a1ba197a28a81fda44bd8b7fEric Laurent 2484c42ac9d4d03f62c3a1ba197a28a81fda44bd8b7fEric Laurent /** @see AudioManager#isSpeakerphoneOn() */ 2485c42ac9d4d03f62c3a1ba197a28a81fda44bd8b7fEric Laurent public boolean isSpeakerphoneOn() { 2486fa640154f1f42121d81242b2f1a10f03e52f0014Eric Laurent return (mForcedUseForComm == AudioSystem.FORCE_SPEAKER); 2487c42ac9d4d03f62c3a1ba197a28a81fda44bd8b7fEric Laurent } 2488c42ac9d4d03f62c3a1ba197a28a81fda44bd8b7fEric Laurent 2489961cae92540763226648813d111c5b5c3b0f1597Dianne Hackborn /** @see AudioManager#setBluetoothScoOn(boolean) */ 2490c42ac9d4d03f62c3a1ba197a28a81fda44bd8b7fEric Laurent public void setBluetoothScoOn(boolean on){ 2491dc1d17a1dbfc2ae01c20012133a836b62f5b6930Eric Laurent if (!checkAudioSettingsPermission("setBluetoothScoOn()")) { 2492dc1d17a1dbfc2ae01c20012133a836b62f5b6930Eric Laurent return; 2493dc1d17a1dbfc2ae01c20012133a836b62f5b6930Eric Laurent } 24947337bee7839238f244fad31112a45389f6ef907cJohan Gustavsson 24957337bee7839238f244fad31112a45389f6ef907cJohan Gustavsson if (on) { 24967337bee7839238f244fad31112a45389f6ef907cJohan Gustavsson mForcedUseForComm = AudioSystem.FORCE_BT_SCO; 24977337bee7839238f244fad31112a45389f6ef907cJohan Gustavsson } else if (mForcedUseForComm == AudioSystem.FORCE_BT_SCO) { 24987337bee7839238f244fad31112a45389f6ef907cJohan Gustavsson mForcedUseForComm = AudioSystem.FORCE_NONE; 24997337bee7839238f244fad31112a45389f6ef907cJohan Gustavsson } 2500fa640154f1f42121d81242b2f1a10f03e52f0014Eric Laurent 2501afbb047c3945e9c2b7e9bc6b25098d5fb80bba4eEric Laurent sendMsg(mAudioHandler, MSG_SET_FORCE_USE, SENDMSG_QUEUE, 2502fa640154f1f42121d81242b2f1a10f03e52f0014Eric Laurent AudioSystem.FOR_COMMUNICATION, mForcedUseForComm, null, 0); 2503afbb047c3945e9c2b7e9bc6b25098d5fb80bba4eEric Laurent sendMsg(mAudioHandler, MSG_SET_FORCE_USE, SENDMSG_QUEUE, 2504fa640154f1f42121d81242b2f1a10f03e52f0014Eric Laurent AudioSystem.FOR_RECORD, mForcedUseForComm, null, 0); 2505c42ac9d4d03f62c3a1ba197a28a81fda44bd8b7fEric Laurent } 2506c42ac9d4d03f62c3a1ba197a28a81fda44bd8b7fEric Laurent 2507c42ac9d4d03f62c3a1ba197a28a81fda44bd8b7fEric Laurent /** @see AudioManager#isBluetoothScoOn() */ 2508c42ac9d4d03f62c3a1ba197a28a81fda44bd8b7fEric Laurent public boolean isBluetoothScoOn() { 2509fa640154f1f42121d81242b2f1a10f03e52f0014Eric Laurent return (mForcedUseForComm == AudioSystem.FORCE_BT_SCO); 2510c42ac9d4d03f62c3a1ba197a28a81fda44bd8b7fEric Laurent } 2511c42ac9d4d03f62c3a1ba197a28a81fda44bd8b7fEric Laurent 2512961cae92540763226648813d111c5b5c3b0f1597Dianne Hackborn /** @see AudioManager#setBluetoothA2dpOn(boolean) */ 25137847211fb4699bf6018e29d214a918ed6657319bEric Laurent public void setBluetoothA2dpOn(boolean on) { 2514c390bed06b4a572e273ead1254da9a932e04dce3Eric Laurent synchronized (mBluetoothA2dpEnabledLock) { 2515c390bed06b4a572e273ead1254da9a932e04dce3Eric Laurent mBluetoothA2dpEnabled = on; 2516c390bed06b4a572e273ead1254da9a932e04dce3Eric Laurent sendMsg(mAudioHandler, MSG_SET_FORCE_BT_A2DP_USE, SENDMSG_QUEUE, 2517c390bed06b4a572e273ead1254da9a932e04dce3Eric Laurent AudioSystem.FOR_MEDIA, 2518c390bed06b4a572e273ead1254da9a932e04dce3Eric Laurent mBluetoothA2dpEnabled ? AudioSystem.FORCE_NONE : AudioSystem.FORCE_NO_BT_A2DP, 2519c390bed06b4a572e273ead1254da9a932e04dce3Eric Laurent null, 0); 2520c390bed06b4a572e273ead1254da9a932e04dce3Eric Laurent } 25217847211fb4699bf6018e29d214a918ed6657319bEric Laurent } 25227847211fb4699bf6018e29d214a918ed6657319bEric Laurent 25237847211fb4699bf6018e29d214a918ed6657319bEric Laurent /** @see AudioManager#isBluetoothA2dpOn() */ 25247847211fb4699bf6018e29d214a918ed6657319bEric Laurent public boolean isBluetoothA2dpOn() { 25257847211fb4699bf6018e29d214a918ed6657319bEric Laurent synchronized (mBluetoothA2dpEnabledLock) { 25267847211fb4699bf6018e29d214a918ed6657319bEric Laurent return mBluetoothA2dpEnabled; 25277847211fb4699bf6018e29d214a918ed6657319bEric Laurent } 25287847211fb4699bf6018e29d214a918ed6657319bEric Laurent } 25297847211fb4699bf6018e29d214a918ed6657319bEric Laurent 25303def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent /** @see AudioManager#startBluetoothSco() */ 253183900754f357616b9e56eaf7fc85f49b8906e987Eric Laurent public void startBluetoothSco(IBinder cb, int targetSdkVersion) { 253283900754f357616b9e56eaf7fc85f49b8906e987Eric Laurent int scoAudioMode = 253383900754f357616b9e56eaf7fc85f49b8906e987Eric Laurent (targetSdkVersion < Build.VERSION_CODES.JELLY_BEAN_MR2) ? 2534f4e51d82d2e34e6832903f01eaecc15ded6c3241Liejun Tao SCO_MODE_VIRTUAL_CALL : SCO_MODE_UNDEFINED; 253583900754f357616b9e56eaf7fc85f49b8906e987Eric Laurent startBluetoothScoInt(cb, scoAudioMode); 253683900754f357616b9e56eaf7fc85f49b8906e987Eric Laurent } 253783900754f357616b9e56eaf7fc85f49b8906e987Eric Laurent 253883900754f357616b9e56eaf7fc85f49b8906e987Eric Laurent /** @see AudioManager#startBluetoothScoVirtualCall() */ 253983900754f357616b9e56eaf7fc85f49b8906e987Eric Laurent public void startBluetoothScoVirtualCall(IBinder cb) { 254083900754f357616b9e56eaf7fc85f49b8906e987Eric Laurent startBluetoothScoInt(cb, SCO_MODE_VIRTUAL_CALL); 254183900754f357616b9e56eaf7fc85f49b8906e987Eric Laurent } 254283900754f357616b9e56eaf7fc85f49b8906e987Eric Laurent 254383900754f357616b9e56eaf7fc85f49b8906e987Eric Laurent void startBluetoothScoInt(IBinder cb, int scoAudioMode){ 2544dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent if (!checkAudioSettingsPermission("startBluetoothSco()") || 25454a5eeb9c727d77bb57fef87a70c8c9cc23dbfee3Eric Laurent !mSystemReady) { 25463def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent return; 25473def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent } 2548854938a72d968c1bc0de4e2b0ea87777cfebc045Eric Laurent ScoClient client = getScoClient(cb, true); 2549f5a1fc3c0fd733acd21e1437f153ba27220be8ceEric Laurent // The calling identity must be cleared before calling ScoClient.incCount(). 2550f5a1fc3c0fd733acd21e1437f153ba27220be8ceEric Laurent // inCount() calls requestScoState() which in turn can call BluetoothHeadset APIs 2551f5a1fc3c0fd733acd21e1437f153ba27220be8ceEric Laurent // and this must be done on behalf of system server to make sure permissions are granted. 2552f5a1fc3c0fd733acd21e1437f153ba27220be8ceEric Laurent // The caller identity must be cleared after getScoClient() because it is needed if a new 2553f5a1fc3c0fd733acd21e1437f153ba27220be8ceEric Laurent // client is created. 2554f5a1fc3c0fd733acd21e1437f153ba27220be8ceEric Laurent final long ident = Binder.clearCallingIdentity(); 255583900754f357616b9e56eaf7fc85f49b8906e987Eric Laurent client.incCount(scoAudioMode); 25562a57ca931fefe817b6110101289721acaacfc808Eric Laurent Binder.restoreCallingIdentity(ident); 25573def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent } 25583def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent 25593def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent /** @see AudioManager#stopBluetoothSco() */ 25603def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent public void stopBluetoothSco(IBinder cb){ 2561dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent if (!checkAudioSettingsPermission("stopBluetoothSco()") || 25624a5eeb9c727d77bb57fef87a70c8c9cc23dbfee3Eric Laurent !mSystemReady) { 25633def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent return; 25643def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent } 2565854938a72d968c1bc0de4e2b0ea87777cfebc045Eric Laurent ScoClient client = getScoClient(cb, false); 2566f5a1fc3c0fd733acd21e1437f153ba27220be8ceEric Laurent // The calling identity must be cleared before calling ScoClient.decCount(). 2567f5a1fc3c0fd733acd21e1437f153ba27220be8ceEric Laurent // decCount() calls requestScoState() which in turn can call BluetoothHeadset APIs 2568f5a1fc3c0fd733acd21e1437f153ba27220be8ceEric Laurent // and this must be done on behalf of system server to make sure permissions are granted. 2569f5a1fc3c0fd733acd21e1437f153ba27220be8ceEric Laurent final long ident = Binder.clearCallingIdentity(); 2570854938a72d968c1bc0de4e2b0ea87777cfebc045Eric Laurent if (client != null) { 2571854938a72d968c1bc0de4e2b0ea87777cfebc045Eric Laurent client.decCount(); 2572854938a72d968c1bc0de4e2b0ea87777cfebc045Eric Laurent } 25732a57ca931fefe817b6110101289721acaacfc808Eric Laurent Binder.restoreCallingIdentity(ident); 25743def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent } 25753def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent 25767847211fb4699bf6018e29d214a918ed6657319bEric Laurent 25773def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent private class ScoClient implements IBinder.DeathRecipient { 25783def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent private IBinder mCb; // To be notified of client's death 2579f1ddd51f9cd2f92b922bc636c307210a8d587c25Marco Nelissen private int mCreatorPid; 25803def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent private int mStartcount; // number of SCO connections started by this client 25813def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent 25823def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent ScoClient(IBinder cb) { 25833def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent mCb = cb; 2584f1ddd51f9cd2f92b922bc636c307210a8d587c25Marco Nelissen mCreatorPid = Binder.getCallingPid(); 25853def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent mStartcount = 0; 25863def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent } 25873def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent 25883def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent public void binderDied() { 25893def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent synchronized(mScoClients) { 25903def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent Log.w(TAG, "SCO client died"); 25913def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent int index = mScoClients.indexOf(this); 25923def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent if (index < 0) { 25933def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent Log.w(TAG, "unregistered SCO client died"); 25943def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent } else { 25953def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent clearCount(true); 25963def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent mScoClients.remove(this); 25973def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent } 25983def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent } 25993def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent } 26003def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent 260183900754f357616b9e56eaf7fc85f49b8906e987Eric Laurent public void incCount(int scoAudioMode) { 26023def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent synchronized(mScoClients) { 260383900754f357616b9e56eaf7fc85f49b8906e987Eric Laurent requestScoState(BluetoothHeadset.STATE_AUDIO_CONNECTED, scoAudioMode); 26043def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent if (mStartcount == 0) { 26053def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent try { 26063def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent mCb.linkToDeath(this, 0); 26073def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent } catch (RemoteException e) { 26083def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent // client has already died! 26093def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent Log.w(TAG, "ScoClient incCount() could not link to "+mCb+" binder death"); 26103def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent } 26113def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent } 26123def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent mStartcount++; 26133def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent } 26143def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent } 26153def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent 26163def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent public void decCount() { 26173def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent synchronized(mScoClients) { 26183def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent if (mStartcount == 0) { 26193def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent Log.w(TAG, "ScoClient.decCount() already 0"); 26203def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent } else { 26213def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent mStartcount--; 26223def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent if (mStartcount == 0) { 2623e2dd8c4592762414c2c27e4589be7edc91a5ecaeEric Laurent try { 2624e2dd8c4592762414c2c27e4589be7edc91a5ecaeEric Laurent mCb.unlinkToDeath(this, 0); 2625e2dd8c4592762414c2c27e4589be7edc91a5ecaeEric Laurent } catch (NoSuchElementException e) { 2626e2dd8c4592762414c2c27e4589be7edc91a5ecaeEric Laurent Log.w(TAG, "decCount() going to 0 but not registered to binder"); 2627e2dd8c4592762414c2c27e4589be7edc91a5ecaeEric Laurent } 26283def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent } 2629c18c9138cee0f0859bcab636a004ce92ca4a9ab5Eric Laurent requestScoState(BluetoothHeadset.STATE_AUDIO_DISCONNECTED, 0); 26303def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent } 26313def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent } 26323def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent } 26333def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent 26343def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent public void clearCount(boolean stopSco) { 26353def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent synchronized(mScoClients) { 2636e2dd8c4592762414c2c27e4589be7edc91a5ecaeEric Laurent if (mStartcount != 0) { 2637e2dd8c4592762414c2c27e4589be7edc91a5ecaeEric Laurent try { 2638e2dd8c4592762414c2c27e4589be7edc91a5ecaeEric Laurent mCb.unlinkToDeath(this, 0); 2639e2dd8c4592762414c2c27e4589be7edc91a5ecaeEric Laurent } catch (NoSuchElementException e) { 2640e2dd8c4592762414c2c27e4589be7edc91a5ecaeEric Laurent Log.w(TAG, "clearCount() mStartcount: "+mStartcount+" != 0 but not registered to binder"); 2641e2dd8c4592762414c2c27e4589be7edc91a5ecaeEric Laurent } 2642e2dd8c4592762414c2c27e4589be7edc91a5ecaeEric Laurent } 26433def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent mStartcount = 0; 26443def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent if (stopSco) { 2645c18c9138cee0f0859bcab636a004ce92ca4a9ab5Eric Laurent requestScoState(BluetoothHeadset.STATE_AUDIO_DISCONNECTED, 0); 26463def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent } 26473def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent } 26483def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent } 26493def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent 26503def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent public int getCount() { 26513def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent return mStartcount; 26523def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent } 26533def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent 26543def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent public IBinder getBinder() { 26553def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent return mCb; 26563def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent } 26573def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent 2658d7454be47f4111c0478a502353e11dea401378bdEric Laurent public int getPid() { 2659d7454be47f4111c0478a502353e11dea401378bdEric Laurent return mCreatorPid; 2660d7454be47f4111c0478a502353e11dea401378bdEric Laurent } 2661d7454be47f4111c0478a502353e11dea401378bdEric Laurent 26623def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent public int totalCount() { 26633def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent synchronized(mScoClients) { 26643def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent int count = 0; 26653def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent int size = mScoClients.size(); 26663def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent for (int i = 0; i < size; i++) { 26673def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent count += mScoClients.get(i).getCount(); 26683def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent } 26693def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent return count; 26703def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent } 26713def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent } 26723def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent 267383900754f357616b9e56eaf7fc85f49b8906e987Eric Laurent private void requestScoState(int state, int scoAudioMode) { 267462ef767b15a712bab31cc0d5508a330906f535c2Eric Laurent checkScoAudioState(); 2675dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent if (totalCount() == 0) { 2676dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent if (state == BluetoothHeadset.STATE_AUDIO_CONNECTED) { 2677dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent // Make sure that the state transitions to CONNECTING even if we cannot initiate 2678dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent // the connection. 2679dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent broadcastScoConnectionState(AudioManager.SCO_AUDIO_STATE_CONNECTING); 2680dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent // Accept SCO audio activation only in NORMAL audio mode or if the mode is 2681f1ddd51f9cd2f92b922bc636c307210a8d587c25Marco Nelissen // currently controlled by the same client process. 26829f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent synchronized(mSetModeDeathHandlers) { 26839f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent if ((mSetModeDeathHandlers.isEmpty() || 26849f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent mSetModeDeathHandlers.get(0).getPid() == mCreatorPid) && 26859f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent (mScoAudioState == SCO_STATE_INACTIVE || 26869f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent mScoAudioState == SCO_STATE_DEACTIVATE_REQ)) { 26879f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent if (mScoAudioState == SCO_STATE_INACTIVE) { 268883900754f357616b9e56eaf7fc85f49b8906e987Eric Laurent mScoAudioMode = scoAudioMode; 2689f4e51d82d2e34e6832903f01eaecc15ded6c3241Liejun Tao if (scoAudioMode == SCO_MODE_UNDEFINED) { 2690570cc5302a2e076f2b6ce810f9ac6f3c53bcd125Andre Eisenbach if (mBluetoothHeadsetDevice != null) { 2691570cc5302a2e076f2b6ce810f9ac6f3c53bcd125Andre Eisenbach mScoAudioMode = new Integer(Settings.Global.getInt( 2692570cc5302a2e076f2b6ce810f9ac6f3c53bcd125Andre Eisenbach mContentResolver, 2693570cc5302a2e076f2b6ce810f9ac6f3c53bcd125Andre Eisenbach "bluetooth_sco_channel_"+ 2694570cc5302a2e076f2b6ce810f9ac6f3c53bcd125Andre Eisenbach mBluetoothHeadsetDevice.getAddress(), 2695570cc5302a2e076f2b6ce810f9ac6f3c53bcd125Andre Eisenbach SCO_MODE_VIRTUAL_CALL)); 2696570cc5302a2e076f2b6ce810f9ac6f3c53bcd125Andre Eisenbach if (mScoAudioMode > SCO_MODE_MAX || mScoAudioMode < 0) { 2697570cc5302a2e076f2b6ce810f9ac6f3c53bcd125Andre Eisenbach mScoAudioMode = SCO_MODE_VIRTUAL_CALL; 2698570cc5302a2e076f2b6ce810f9ac6f3c53bcd125Andre Eisenbach } 2699570cc5302a2e076f2b6ce810f9ac6f3c53bcd125Andre Eisenbach } else { 2700570cc5302a2e076f2b6ce810f9ac6f3c53bcd125Andre Eisenbach mScoAudioMode = SCO_MODE_RAW; 2701f4e51d82d2e34e6832903f01eaecc15ded6c3241Liejun Tao } 2702f4e51d82d2e34e6832903f01eaecc15ded6c3241Liejun Tao } 27039f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent if (mBluetoothHeadset != null && mBluetoothHeadsetDevice != null) { 2704f4e51d82d2e34e6832903f01eaecc15ded6c3241Liejun Tao boolean status = false; 2705c18c9138cee0f0859bcab636a004ce92ca4a9ab5Eric Laurent if (mScoAudioMode == SCO_MODE_RAW) { 2706c18c9138cee0f0859bcab636a004ce92ca4a9ab5Eric Laurent status = mBluetoothHeadset.connectAudio(); 2707f4e51d82d2e34e6832903f01eaecc15ded6c3241Liejun Tao } else if (mScoAudioMode == SCO_MODE_VIRTUAL_CALL) { 2708c18c9138cee0f0859bcab636a004ce92ca4a9ab5Eric Laurent status = mBluetoothHeadset.startScoUsingVirtualVoiceCall( 2709c18c9138cee0f0859bcab636a004ce92ca4a9ab5Eric Laurent mBluetoothHeadsetDevice); 2710f4e51d82d2e34e6832903f01eaecc15ded6c3241Liejun Tao } else if (mScoAudioMode == SCO_MODE_VR) { 2711f4e51d82d2e34e6832903f01eaecc15ded6c3241Liejun Tao status = mBluetoothHeadset.startVoiceRecognition( 2712f4e51d82d2e34e6832903f01eaecc15ded6c3241Liejun Tao mBluetoothHeadsetDevice); 2713c18c9138cee0f0859bcab636a004ce92ca4a9ab5Eric Laurent } 2714f4e51d82d2e34e6832903f01eaecc15ded6c3241Liejun Tao 2715c18c9138cee0f0859bcab636a004ce92ca4a9ab5Eric Laurent if (status) { 27169f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent mScoAudioState = SCO_STATE_ACTIVE_INTERNAL; 27179f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent } else { 27189f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent broadcastScoConnectionState( 27199f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent AudioManager.SCO_AUDIO_STATE_DISCONNECTED); 27209f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent } 27219f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent } else if (getBluetoothHeadset()) { 27229f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent mScoAudioState = SCO_STATE_ACTIVATE_REQ; 2723dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent } 27249f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent } else { 27259f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent mScoAudioState = SCO_STATE_ACTIVE_INTERNAL; 27269f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent broadcastScoConnectionState(AudioManager.SCO_AUDIO_STATE_CONNECTED); 2727dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent } 2728dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent } else { 27299f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent broadcastScoConnectionState(AudioManager.SCO_AUDIO_STATE_DISCONNECTED); 2730dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent } 2731dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent } 273262ef767b15a712bab31cc0d5508a330906f535c2Eric Laurent } else if (state == BluetoothHeadset.STATE_AUDIO_DISCONNECTED && 2733dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent (mScoAudioState == SCO_STATE_ACTIVE_INTERNAL || 2734dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent mScoAudioState == SCO_STATE_ACTIVATE_REQ)) { 2735dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent if (mScoAudioState == SCO_STATE_ACTIVE_INTERNAL) { 2736671db6f3ba1fdb3c907e0735fe6d0d284f5c34deMarco Nelissen if (mBluetoothHeadset != null && mBluetoothHeadsetDevice != null) { 2737f4e51d82d2e34e6832903f01eaecc15ded6c3241Liejun Tao boolean status = false; 2738c18c9138cee0f0859bcab636a004ce92ca4a9ab5Eric Laurent if (mScoAudioMode == SCO_MODE_RAW) { 2739c18c9138cee0f0859bcab636a004ce92ca4a9ab5Eric Laurent status = mBluetoothHeadset.disconnectAudio(); 2740f4e51d82d2e34e6832903f01eaecc15ded6c3241Liejun Tao } else if (mScoAudioMode == SCO_MODE_VIRTUAL_CALL) { 2741c18c9138cee0f0859bcab636a004ce92ca4a9ab5Eric Laurent status = mBluetoothHeadset.stopScoUsingVirtualVoiceCall( 2742c18c9138cee0f0859bcab636a004ce92ca4a9ab5Eric Laurent mBluetoothHeadsetDevice); 2743f4e51d82d2e34e6832903f01eaecc15ded6c3241Liejun Tao } else if (mScoAudioMode == SCO_MODE_VR) { 2744f4e51d82d2e34e6832903f01eaecc15ded6c3241Liejun Tao status = mBluetoothHeadset.stopVoiceRecognition( 2745f4e51d82d2e34e6832903f01eaecc15ded6c3241Liejun Tao mBluetoothHeadsetDevice); 2746c18c9138cee0f0859bcab636a004ce92ca4a9ab5Eric Laurent } 2747f4e51d82d2e34e6832903f01eaecc15ded6c3241Liejun Tao 2748c18c9138cee0f0859bcab636a004ce92ca4a9ab5Eric Laurent if (!status) { 2749dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent mScoAudioState = SCO_STATE_INACTIVE; 2750dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent broadcastScoConnectionState( 2751dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent AudioManager.SCO_AUDIO_STATE_DISCONNECTED); 2752dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent } 2753dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent } else if (getBluetoothHeadset()) { 2754dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent mScoAudioState = SCO_STATE_DEACTIVATE_REQ; 2755dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent } 2756dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent } else { 2757dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent mScoAudioState = SCO_STATE_INACTIVE; 2758dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent broadcastScoConnectionState(AudioManager.SCO_AUDIO_STATE_DISCONNECTED); 2759dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent } 27603def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent } 27613def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent } 27623def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent } 27633def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent } 27643def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent 276562ef767b15a712bab31cc0d5508a330906f535c2Eric Laurent private void checkScoAudioState() { 276662ef767b15a712bab31cc0d5508a330906f535c2Eric Laurent if (mBluetoothHeadset != null && mBluetoothHeadsetDevice != null && 2767dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent mScoAudioState == SCO_STATE_INACTIVE && 276862ef767b15a712bab31cc0d5508a330906f535c2Eric Laurent mBluetoothHeadset.getAudioState(mBluetoothHeadsetDevice) 276962ef767b15a712bab31cc0d5508a330906f535c2Eric Laurent != BluetoothHeadset.STATE_AUDIO_DISCONNECTED) { 277062ef767b15a712bab31cc0d5508a330906f535c2Eric Laurent mScoAudioState = SCO_STATE_ACTIVE_EXTERNAL; 277162ef767b15a712bab31cc0d5508a330906f535c2Eric Laurent } 277262ef767b15a712bab31cc0d5508a330906f535c2Eric Laurent } 277362ef767b15a712bab31cc0d5508a330906f535c2Eric Laurent 2774854938a72d968c1bc0de4e2b0ea87777cfebc045Eric Laurent private ScoClient getScoClient(IBinder cb, boolean create) { 27753def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent synchronized(mScoClients) { 2776854938a72d968c1bc0de4e2b0ea87777cfebc045Eric Laurent ScoClient client = null; 27773def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent int size = mScoClients.size(); 27783def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent for (int i = 0; i < size; i++) { 27793def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent client = mScoClients.get(i); 27803def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent if (client.getBinder() == cb) 27813def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent return client; 27823def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent } 2783854938a72d968c1bc0de4e2b0ea87777cfebc045Eric Laurent if (create) { 2784854938a72d968c1bc0de4e2b0ea87777cfebc045Eric Laurent client = new ScoClient(cb); 2785854938a72d968c1bc0de4e2b0ea87777cfebc045Eric Laurent mScoClients.add(client); 2786854938a72d968c1bc0de4e2b0ea87777cfebc045Eric Laurent } 27873def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent return client; 27883def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent } 27893def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent } 27903def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent 2791d7454be47f4111c0478a502353e11dea401378bdEric Laurent public void clearAllScoClients(int exceptPid, boolean stopSco) { 27923def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent synchronized(mScoClients) { 2793854938a72d968c1bc0de4e2b0ea87777cfebc045Eric Laurent ScoClient savedClient = null; 27943def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent int size = mScoClients.size(); 27953def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent for (int i = 0; i < size; i++) { 2796854938a72d968c1bc0de4e2b0ea87777cfebc045Eric Laurent ScoClient cl = mScoClients.get(i); 2797d7454be47f4111c0478a502353e11dea401378bdEric Laurent if (cl.getPid() != exceptPid) { 2798854938a72d968c1bc0de4e2b0ea87777cfebc045Eric Laurent cl.clearCount(stopSco); 2799854938a72d968c1bc0de4e2b0ea87777cfebc045Eric Laurent } else { 2800854938a72d968c1bc0de4e2b0ea87777cfebc045Eric Laurent savedClient = cl; 2801854938a72d968c1bc0de4e2b0ea87777cfebc045Eric Laurent } 2802854938a72d968c1bc0de4e2b0ea87777cfebc045Eric Laurent } 2803854938a72d968c1bc0de4e2b0ea87777cfebc045Eric Laurent mScoClients.clear(); 2804854938a72d968c1bc0de4e2b0ea87777cfebc045Eric Laurent if (savedClient != null) { 2805854938a72d968c1bc0de4e2b0ea87777cfebc045Eric Laurent mScoClients.add(savedClient); 28063def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent } 28073def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent } 28083def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent } 28093def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent 2810dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent private boolean getBluetoothHeadset() { 2811dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent boolean result = false; 2812dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter(); 2813dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent if (adapter != null) { 2814dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent result = adapter.getProfileProxy(mContext, mBluetoothProfileServiceListener, 2815dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent BluetoothProfile.HEADSET); 2816dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent } 2817dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent // If we could not get a bluetooth headset proxy, send a failure message 2818dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent // without delay to reset the SCO audio state and clear SCO clients. 2819dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent // If we could get a proxy, send a delayed failure message that will reset our state 2820dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent // in case we don't receive onServiceConnected(). 2821afbb047c3945e9c2b7e9bc6b25098d5fb80bba4eEric Laurent sendMsg(mAudioHandler, MSG_BT_HEADSET_CNCT_FAILED, 2822dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent SENDMSG_REPLACE, 0, 0, null, result ? BT_HEADSET_CNCT_TIMEOUT_MS : 0); 2823dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent return result; 2824dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent } 2825dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent 2826d7454be47f4111c0478a502353e11dea401378bdEric Laurent private void disconnectBluetoothSco(int exceptPid) { 2827dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent synchronized(mScoClients) { 2828dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent checkScoAudioState(); 2829dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent if (mScoAudioState == SCO_STATE_ACTIVE_EXTERNAL || 2830dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent mScoAudioState == SCO_STATE_DEACTIVATE_EXT_REQ) { 2831dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent if (mBluetoothHeadsetDevice != null) { 2832dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent if (mBluetoothHeadset != null) { 2833dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent if (!mBluetoothHeadset.stopVoiceRecognition( 2834b06ac839dd2d0437fc8314f6deb7233af5af521eEric Laurent mBluetoothHeadsetDevice)) { 2835afbb047c3945e9c2b7e9bc6b25098d5fb80bba4eEric Laurent sendMsg(mAudioHandler, MSG_BT_HEADSET_CNCT_FAILED, 2836dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent SENDMSG_REPLACE, 0, 0, null, 0); 2837dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent } 2838dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent } else if (mScoAudioState == SCO_STATE_ACTIVE_EXTERNAL && 2839dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent getBluetoothHeadset()) { 2840dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent mScoAudioState = SCO_STATE_DEACTIVATE_EXT_REQ; 2841dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent } 2842dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent } 2843dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent } else { 2844d7454be47f4111c0478a502353e11dea401378bdEric Laurent clearAllScoClients(exceptPid, true); 2845dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent } 2846dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent } 2847dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent } 2848dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent 2849dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent private void resetBluetoothSco() { 2850dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent synchronized(mScoClients) { 2851d7454be47f4111c0478a502353e11dea401378bdEric Laurent clearAllScoClients(0, false); 2852dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent mScoAudioState = SCO_STATE_INACTIVE; 2853dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent broadcastScoConnectionState(AudioManager.SCO_AUDIO_STATE_DISCONNECTED); 2854dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent } 2855dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent } 2856dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent 2857dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent private void broadcastScoConnectionState(int state) { 28582a57ca931fefe817b6110101289721acaacfc808Eric Laurent sendMsg(mAudioHandler, MSG_BROADCAST_BT_CONNECTION_STATE, 28592a57ca931fefe817b6110101289721acaacfc808Eric Laurent SENDMSG_QUEUE, state, 0, null, 0); 28602a57ca931fefe817b6110101289721acaacfc808Eric Laurent } 28612a57ca931fefe817b6110101289721acaacfc808Eric Laurent 28622a57ca931fefe817b6110101289721acaacfc808Eric Laurent private void onBroadcastScoConnectionState(int state) { 2863dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent if (state != mScoConnectionState) { 2864dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent Intent newIntent = new Intent(AudioManager.ACTION_SCO_AUDIO_STATE_UPDATED); 2865dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent newIntent.putExtra(AudioManager.EXTRA_SCO_AUDIO_STATE, state); 2866dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent newIntent.putExtra(AudioManager.EXTRA_SCO_AUDIO_PREVIOUS_STATE, 2867dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent mScoConnectionState); 28685ac72a29593ab9a20337a2225df52bdf4754be02Dianne Hackborn sendStickyBroadcastToAll(newIntent); 2869dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent mScoConnectionState = state; 2870dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent } 2871dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent } 2872dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent 287382aa7f017daaaeb96c13e6e3491d5037ab471085Jaikumar Ganesh private BluetoothProfile.ServiceListener mBluetoothProfileServiceListener = 287482aa7f017daaaeb96c13e6e3491d5037ab471085Jaikumar Ganesh new BluetoothProfile.ServiceListener() { 287582aa7f017daaaeb96c13e6e3491d5037ab471085Jaikumar Ganesh public void onServiceConnected(int profile, BluetoothProfile proxy) { 28766bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent BluetoothDevice btDevice; 28776bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent List<BluetoothDevice> deviceList; 28786bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent switch(profile) { 28796bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent case BluetoothProfile.A2DP: 28805a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du synchronized (mA2dpAvrcpLock) { 28815a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du mA2dp = (BluetoothA2dp) proxy; 28825a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du deviceList = mA2dp.getConnectedDevices(); 28835a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du if (deviceList.size() > 0) { 28845a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du btDevice = deviceList.get(0); 28855a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du synchronized (mConnectedDevices) { 28865a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du int state = mA2dp.getConnectionState(btDevice); 28875a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du int delay = checkSendBecomingNoisyIntent( 28880a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, 28890a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood (state == BluetoothA2dp.STATE_CONNECTED) ? 1 : 0); 28905a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du queueMsgUnderWakeLock(mAudioHandler, 28910a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood MSG_SET_A2DP_SINK_CONNECTION_STATE, 28925a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du state, 28935a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du 0, 28945a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du btDevice, 28955a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du delay); 28965a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du } 2897b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent } 28986bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent } 28996bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent break; 29006bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent 29010a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood case BluetoothProfile.A2DP_SINK: 29020a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood deviceList = proxy.getConnectedDevices(); 29030a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood if (deviceList.size() > 0) { 29040a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood btDevice = deviceList.get(0); 29050a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood synchronized (mConnectedDevices) { 29060a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood int state = proxy.getConnectionState(btDevice); 29070a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood queueMsgUnderWakeLock(mAudioHandler, 29080a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood MSG_SET_A2DP_SRC_CONNECTION_STATE, 29090a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood state, 29100a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood 0, 29110a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood btDevice, 29120a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood 0 /* delay */); 29130a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood } 29140a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood } 29150a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood break; 29160a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood 29176bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent case BluetoothProfile.HEADSET: 29186bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent synchronized (mScoClients) { 29196bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent // Discard timeout message 29206bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent mAudioHandler.removeMessages(MSG_BT_HEADSET_CNCT_FAILED); 29216bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent mBluetoothHeadset = (BluetoothHeadset) proxy; 29226bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent deviceList = mBluetoothHeadset.getConnectedDevices(); 29236bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent if (deviceList.size() > 0) { 29246bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent mBluetoothHeadsetDevice = deviceList.get(0); 29256bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent } else { 29266bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent mBluetoothHeadsetDevice = null; 2927dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent } 29286bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent // Refresh SCO audio state 29296bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent checkScoAudioState(); 29306bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent // Continue pending action if any 29316bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent if (mScoAudioState == SCO_STATE_ACTIVATE_REQ || 29326bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent mScoAudioState == SCO_STATE_DEACTIVATE_REQ || 29336bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent mScoAudioState == SCO_STATE_DEACTIVATE_EXT_REQ) { 29346bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent boolean status = false; 29356bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent if (mBluetoothHeadsetDevice != null) { 29366bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent switch (mScoAudioState) { 29376bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent case SCO_STATE_ACTIVATE_REQ: 29386bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent mScoAudioState = SCO_STATE_ACTIVE_INTERNAL; 2939c18c9138cee0f0859bcab636a004ce92ca4a9ab5Eric Laurent if (mScoAudioMode == SCO_MODE_RAW) { 2940c18c9138cee0f0859bcab636a004ce92ca4a9ab5Eric Laurent status = mBluetoothHeadset.connectAudio(); 2941f4e51d82d2e34e6832903f01eaecc15ded6c3241Liejun Tao } else if (mScoAudioMode == SCO_MODE_VIRTUAL_CALL) { 2942c18c9138cee0f0859bcab636a004ce92ca4a9ab5Eric Laurent status = mBluetoothHeadset.startScoUsingVirtualVoiceCall( 2943c18c9138cee0f0859bcab636a004ce92ca4a9ab5Eric Laurent mBluetoothHeadsetDevice); 2944f4e51d82d2e34e6832903f01eaecc15ded6c3241Liejun Tao } else if (mScoAudioMode == SCO_MODE_VR) { 2945f4e51d82d2e34e6832903f01eaecc15ded6c3241Liejun Tao status = mBluetoothHeadset.startVoiceRecognition( 2946f4e51d82d2e34e6832903f01eaecc15ded6c3241Liejun Tao mBluetoothHeadsetDevice); 2947c18c9138cee0f0859bcab636a004ce92ca4a9ab5Eric Laurent } 29486bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent break; 29496bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent case SCO_STATE_DEACTIVATE_REQ: 2950c18c9138cee0f0859bcab636a004ce92ca4a9ab5Eric Laurent if (mScoAudioMode == SCO_MODE_RAW) { 2951c18c9138cee0f0859bcab636a004ce92ca4a9ab5Eric Laurent status = mBluetoothHeadset.disconnectAudio(); 2952f4e51d82d2e34e6832903f01eaecc15ded6c3241Liejun Tao } else if (mScoAudioMode == SCO_MODE_VIRTUAL_CALL) { 2953c18c9138cee0f0859bcab636a004ce92ca4a9ab5Eric Laurent status = mBluetoothHeadset.stopScoUsingVirtualVoiceCall( 2954c18c9138cee0f0859bcab636a004ce92ca4a9ab5Eric Laurent mBluetoothHeadsetDevice); 2955f4e51d82d2e34e6832903f01eaecc15ded6c3241Liejun Tao } else if (mScoAudioMode == SCO_MODE_VR) { 2956f4e51d82d2e34e6832903f01eaecc15ded6c3241Liejun Tao status = mBluetoothHeadset.stopVoiceRecognition( 2957f4e51d82d2e34e6832903f01eaecc15ded6c3241Liejun Tao mBluetoothHeadsetDevice); 2958c18c9138cee0f0859bcab636a004ce92ca4a9ab5Eric Laurent } 29596bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent break; 29606bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent case SCO_STATE_DEACTIVATE_EXT_REQ: 29616bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent status = mBluetoothHeadset.stopVoiceRecognition( 29626bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent mBluetoothHeadsetDevice); 29636bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent } 29646bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent } 29656bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent if (!status) { 2966afbb047c3945e9c2b7e9bc6b25098d5fb80bba4eEric Laurent sendMsg(mAudioHandler, MSG_BT_HEADSET_CNCT_FAILED, 29676bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent SENDMSG_REPLACE, 0, 0, null, 0); 29686bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent } 2969dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent } 2970dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent } 29716bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent break; 29726bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent 29736bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent default: 29746bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent break; 29753def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent } 29763def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent } 297782aa7f017daaaeb96c13e6e3491d5037ab471085Jaikumar Ganesh public void onServiceDisconnected(int profile) { 29786bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent switch(profile) { 29796bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent case BluetoothProfile.A2DP: 29805a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du synchronized (mA2dpAvrcpLock) { 29815a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du mA2dp = null; 29825a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du synchronized (mConnectedDevices) { 29835a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du if (mConnectedDevices.containsKey(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP)) { 29845a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du makeA2dpDeviceUnavailableNow( 29855a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du mConnectedDevices.get(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP)); 29865a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du } 29876bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent } 29886bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent } 29896bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent break; 29906bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent 29910a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood case BluetoothProfile.A2DP_SINK: 29920a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood synchronized (mConnectedDevices) { 29930a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood if (mConnectedDevices.containsKey(AudioSystem.DEVICE_IN_BLUETOOTH_A2DP)) { 29940a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood makeA2dpSrcUnavailable( 29950a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood mConnectedDevices.get(AudioSystem.DEVICE_IN_BLUETOOTH_A2DP)); 29960a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood } 29970a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood } 29980a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood break; 29990a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood 30006bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent case BluetoothProfile.HEADSET: 30016bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent synchronized (mScoClients) { 30026bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent mBluetoothHeadset = null; 30036bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent } 30046bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent break; 30056bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent 30066bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent default: 30076bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent break; 30083def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent } 30093def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent } 30103def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent }; 3011d5176cfe6eae954e9cef1e2ec17859a5089e1330Jean-Michel Trivi 3012c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent private void onCheckMusicActive() { 3013d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent synchronized (mSafeMediaVolumeState) { 3014d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent if (mSafeMediaVolumeState == SAFE_MEDIA_VOLUME_INACTIVE) { 3015c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent int device = getDeviceForStream(AudioSystem.STREAM_MUSIC); 3016c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent 3017c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent if ((device & mSafeMediaVolumeDevices) != 0) { 3018c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent sendMsg(mAudioHandler, 3019c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent MSG_CHECK_MUSIC_ACTIVE, 3020c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent SENDMSG_REPLACE, 3021f1a457d06c53a901ea08d2d3fb6e766bc06c4d4fEric Laurent 0, 3022c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent 0, 3023c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent null, 3024c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent MUSIC_ACTIVE_POLL_PERIOD_MS); 302542b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent int index = mStreamStates[AudioSystem.STREAM_MUSIC].getIndex(device); 3026f1a457d06c53a901ea08d2d3fb6e766bc06c4d4fEric Laurent if (AudioSystem.isStreamActive(AudioSystem.STREAM_MUSIC, 0) && 3027f1a457d06c53a901ea08d2d3fb6e766bc06c4d4fEric Laurent (index > mSafeMediaVolumeIndex)) { 3028c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent // Approximate cumulative active music time 3029c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent mMusicActiveMs += MUSIC_ACTIVE_POLL_PERIOD_MS; 3030c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent if (mMusicActiveMs > UNSAFE_VOLUME_MUSIC_ACTIVE_MS_MAX) { 3031c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent setSafeMediaVolumeEnabled(true); 3032c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent mMusicActiveMs = 0; 3033c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent } 3034aa5ee4d65f8788e2a0afcd198367450853fd72acJohn Spurlock saveMusicActiveMs(); 3035c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent } 3036c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent } 3037c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent } 3038c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent } 3039c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent } 3040c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent 3041aa5ee4d65f8788e2a0afcd198367450853fd72acJohn Spurlock private void saveMusicActiveMs() { 3042aa5ee4d65f8788e2a0afcd198367450853fd72acJohn Spurlock mAudioHandler.obtainMessage(MSG_PERSIST_MUSIC_ACTIVE_MS, mMusicActiveMs, 0).sendToTarget(); 3043aa5ee4d65f8788e2a0afcd198367450853fd72acJohn Spurlock } 3044aa5ee4d65f8788e2a0afcd198367450853fd72acJohn Spurlock 3045d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent private void onConfigureSafeVolume(boolean force) { 3046d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent synchronized (mSafeMediaVolumeState) { 3047d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent int mcc = mContext.getResources().getConfiguration().mcc; 3048d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent if ((mMcc != mcc) || ((mMcc == 0) && force)) { 3049d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent mSafeMediaVolumeIndex = mContext.getResources().getInteger( 3050d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent com.android.internal.R.integer.config_safe_media_volume_index) * 10; 3051351346092acdfbfcc1d9ebf98d539d2a1196c5e8John Spurlock boolean safeMediaVolumeEnabled = 3052351346092acdfbfcc1d9ebf98d539d2a1196c5e8John Spurlock SystemProperties.getBoolean("audio.safemedia.force", false) 3053351346092acdfbfcc1d9ebf98d539d2a1196c5e8John Spurlock || mContext.getResources().getBoolean( 3054351346092acdfbfcc1d9ebf98d539d2a1196c5e8John Spurlock com.android.internal.R.bool.config_safe_media_volume_enabled); 305505274f348e12983eb8613cc6eb9ae561e8197e28Eric Laurent 305605274f348e12983eb8613cc6eb9ae561e8197e28Eric Laurent // The persisted state is either "disabled" or "active": this is the state applied 305705274f348e12983eb8613cc6eb9ae561e8197e28Eric Laurent // next time we boot and cannot be "inactive" 305805274f348e12983eb8613cc6eb9ae561e8197e28Eric Laurent int persistedState; 3059d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent if (safeMediaVolumeEnabled) { 306005274f348e12983eb8613cc6eb9ae561e8197e28Eric Laurent persistedState = SAFE_MEDIA_VOLUME_ACTIVE; 306105274f348e12983eb8613cc6eb9ae561e8197e28Eric Laurent // The state can already be "inactive" here if the user has forced it before 306205274f348e12983eb8613cc6eb9ae561e8197e28Eric Laurent // the 30 seconds timeout for forced configuration. In this case we don't reset 306305274f348e12983eb8613cc6eb9ae561e8197e28Eric Laurent // it to "active". 306405274f348e12983eb8613cc6eb9ae561e8197e28Eric Laurent if (mSafeMediaVolumeState != SAFE_MEDIA_VOLUME_INACTIVE) { 3065aa5ee4d65f8788e2a0afcd198367450853fd72acJohn Spurlock if (mMusicActiveMs == 0) { 3066aa5ee4d65f8788e2a0afcd198367450853fd72acJohn Spurlock mSafeMediaVolumeState = SAFE_MEDIA_VOLUME_ACTIVE; 3067aa5ee4d65f8788e2a0afcd198367450853fd72acJohn Spurlock enforceSafeMediaVolume(); 3068aa5ee4d65f8788e2a0afcd198367450853fd72acJohn Spurlock } else { 3069aa5ee4d65f8788e2a0afcd198367450853fd72acJohn Spurlock // We have existing playback time recorded, already confirmed. 3070aa5ee4d65f8788e2a0afcd198367450853fd72acJohn Spurlock mSafeMediaVolumeState = SAFE_MEDIA_VOLUME_INACTIVE; 3071aa5ee4d65f8788e2a0afcd198367450853fd72acJohn Spurlock } 307205274f348e12983eb8613cc6eb9ae561e8197e28Eric Laurent } 3073d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent } else { 307405274f348e12983eb8613cc6eb9ae561e8197e28Eric Laurent persistedState = SAFE_MEDIA_VOLUME_DISABLED; 3075d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent mSafeMediaVolumeState = SAFE_MEDIA_VOLUME_DISABLED; 3076d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent } 3077d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent mMcc = mcc; 307805274f348e12983eb8613cc6eb9ae561e8197e28Eric Laurent sendMsg(mAudioHandler, 307905274f348e12983eb8613cc6eb9ae561e8197e28Eric Laurent MSG_PERSIST_SAFE_VOLUME_STATE, 308005274f348e12983eb8613cc6eb9ae561e8197e28Eric Laurent SENDMSG_QUEUE, 308105274f348e12983eb8613cc6eb9ae561e8197e28Eric Laurent persistedState, 308205274f348e12983eb8613cc6eb9ae561e8197e28Eric Laurent 0, 308305274f348e12983eb8613cc6eb9ae561e8197e28Eric Laurent null, 308405274f348e12983eb8613cc6eb9ae561e8197e28Eric Laurent 0); 3085d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent } 3086d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent } 3087d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent } 3088d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent 30899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /////////////////////////////////////////////////////////////////////////// 30909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Internal methods 30919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /////////////////////////////////////////////////////////////////////////// 30929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 30939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 30949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Checks if the adjustment should change ringer mode instead of just 30959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * adjusting volume. If so, this will set the proper ringer mode and volume 30969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * indices on the stream states. 30979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 3098a11b4affcad3d255aa723a89b768ea222506f2e8John Spurlock private int checkForRingerModeChange(int oldIndex, int direction, int step) { 3099a11b4affcad3d255aa723a89b768ea222506f2e8John Spurlock int result = FLAG_ADJUST_VOLUME; 3100661f2cf45860d2e10924e6b69966a9afe255f28bJohn Spurlock int ringerMode = getRingerModeInternal(); 3101bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent 3102bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent switch (ringerMode) { 3103bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent case RINGER_MODE_NORMAL: 3104bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent if (direction == AudioManager.ADJUST_LOWER) { 3105bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent if (mHasVibrator) { 3106244820185269991186d07068b92985624cede4a5Eric Laurent // "step" is the delta in internal index units corresponding to a 3107244820185269991186d07068b92985624cede4a5Eric Laurent // change of 1 in UI index units. 3108244820185269991186d07068b92985624cede4a5Eric Laurent // Because of rounding when rescaling from one stream index range to its alias 3109244820185269991186d07068b92985624cede4a5Eric Laurent // index range, we cannot simply test oldIndex == step: 3110244820185269991186d07068b92985624cede4a5Eric Laurent // (step <= oldIndex < 2 * step) is equivalent to: (old UI index == 1) 3111244820185269991186d07068b92985624cede4a5Eric Laurent if (step <= oldIndex && oldIndex < 2 * step) { 3112bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent ringerMode = RINGER_MODE_VIBRATE; 3113bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent } 3114bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent } else { 3115244820185269991186d07068b92985624cede4a5Eric Laurent // (oldIndex < step) is equivalent to (old UI index == 0) 31168600534df66c2ff5846ed230b50c56229322d48aJohn Spurlock if ((oldIndex < step) 31178600534df66c2ff5846ed230b50c56229322d48aJohn Spurlock && VOLUME_SETS_RINGER_MODE_SILENT 31188600534df66c2ff5846ed230b50c56229322d48aJohn Spurlock && mPrevVolDirection != AudioManager.ADJUST_LOWER) { 3119bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent ringerMode = RINGER_MODE_SILENT; 3120bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent } 31213d4c06f90726a85e89dab13c41ddc15b9c912a3fEric Laurent } 31226329bf7b1e2217c6c9477bd57349a1edade18417Daniel Sandler } 3123bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent break; 3124bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent case RINGER_MODE_VIBRATE: 3125bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent if (!mHasVibrator) { 3126bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent Log.e(TAG, "checkForRingerModeChange() current ringer mode is vibrate" + 3127bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent "but no vibrator is present"); 3128bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent break; 3129bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent } 3130c696a53d1fe4d61373c5dc64dd057d322da90c8fAmith Yamasani if ((direction == AudioManager.ADJUST_LOWER)) { 3131795a51469701b4339eed4d97b6b06560f2d16d3fJohn Spurlock if (mPrevVolDirection != AudioManager.ADJUST_LOWER) { 3132795a51469701b4339eed4d97b6b06560f2d16d3fJohn Spurlock if (VOLUME_SETS_RINGER_MODE_SILENT) { 3133795a51469701b4339eed4d97b6b06560f2d16d3fJohn Spurlock ringerMode = RINGER_MODE_SILENT; 3134795a51469701b4339eed4d97b6b06560f2d16d3fJohn Spurlock } else { 3135795a51469701b4339eed4d97b6b06560f2d16d3fJohn Spurlock result |= AudioManager.FLAG_SHOW_VIBRATE_HINT; 3136795a51469701b4339eed4d97b6b06560f2d16d3fJohn Spurlock } 3137c696a53d1fe4d61373c5dc64dd057d322da90c8fAmith Yamasani } 3138c696a53d1fe4d61373c5dc64dd057d322da90c8fAmith Yamasani } else if (direction == AudioManager.ADJUST_RAISE) { 3139bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent ringerMode = RINGER_MODE_NORMAL; 3140c696a53d1fe4d61373c5dc64dd057d322da90c8fAmith Yamasani } 3141a11b4affcad3d255aa723a89b768ea222506f2e8John Spurlock result &= ~FLAG_ADJUST_VOLUME; 3142bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent break; 3143bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent case RINGER_MODE_SILENT: 31449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (direction == AudioManager.ADJUST_RAISE) { 3145a11b4affcad3d255aa723a89b768ea222506f2e8John Spurlock if (PREVENT_VOLUME_ADJUSTMENT_IF_SILENT) { 3146a11b4affcad3d255aa723a89b768ea222506f2e8John Spurlock result |= AudioManager.FLAG_SHOW_SILENT_HINT; 3147bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent } else { 3148a11b4affcad3d255aa723a89b768ea222506f2e8John Spurlock if (mHasVibrator) { 3149a11b4affcad3d255aa723a89b768ea222506f2e8John Spurlock ringerMode = RINGER_MODE_VIBRATE; 3150a11b4affcad3d255aa723a89b768ea222506f2e8John Spurlock } else { 3151a11b4affcad3d255aa723a89b768ea222506f2e8John Spurlock ringerMode = RINGER_MODE_NORMAL; 3152a11b4affcad3d255aa723a89b768ea222506f2e8John Spurlock } 3153bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent } 31549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3155a11b4affcad3d255aa723a89b768ea222506f2e8John Spurlock result &= ~FLAG_ADJUST_VOLUME; 3156bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent break; 3157bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent default: 3158bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent Log.e(TAG, "checkForRingerModeChange() wrong ringer mode: "+ringerMode); 3159bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent break; 31609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 31619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3162661f2cf45860d2e10924e6b69966a9afe255f28bJohn Spurlock setRingerMode(ringerMode, TAG + ".checkForRingerModeChange", false /*external*/); 31639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 316425101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent mPrevVolDirection = direction; 316525101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent 3166a11b4affcad3d255aa723a89b768ea222506f2e8John Spurlock return result; 31679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 31689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 31693346a802087f621c6441bc512dfcc17b07143fc6John Spurlock @Override 31709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public boolean isStreamAffectedByRingerMode(int streamType) { 31719bcf401d13d47416043a704430388abd59aef7cdEric Laurent return (mRingerModeAffectedStreams & (1 << streamType)) != 0; 31729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 31739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 31745b4e654d0c7de8e4d58d73e73b0d5220f19b68f7Eric Laurent private boolean isStreamMutedByRingerMode(int streamType) { 31755b4e654d0c7de8e4d58d73e73b0d5220f19b68f7Eric Laurent return (mRingerModeMutedStreams & (1 << streamType)) != 0; 31765b4e654d0c7de8e4d58d73e73b0d5220f19b68f7Eric Laurent } 31775b4e654d0c7de8e4d58d73e73b0d5220f19b68f7Eric Laurent 317824e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent boolean updateRingerModeAffectedStreams() { 317924e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent int ringerModeAffectedStreams; 318024e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent // make sure settings for ringer mode are consistent with device type: non voice capable 318124e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent // devices (tablets) include media stream in silent mode whereas phones don't. 318224e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent ringerModeAffectedStreams = Settings.System.getIntForUser(mContentResolver, 318324e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent Settings.System.MODE_RINGER_STREAMS_AFFECTED, 318424e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent ((1 << AudioSystem.STREAM_RING)|(1 << AudioSystem.STREAM_NOTIFICATION)| 318524e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent (1 << AudioSystem.STREAM_SYSTEM)|(1 << AudioSystem.STREAM_SYSTEM_ENFORCED)), 318624e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent UserHandle.USER_CURRENT); 318724e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent 318824e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent // ringtone, notification and system streams are always affected by ringer mode 318924e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent ringerModeAffectedStreams |= (1 << AudioSystem.STREAM_RING)| 319024e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent (1 << AudioSystem.STREAM_NOTIFICATION)| 319124e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent (1 << AudioSystem.STREAM_SYSTEM); 319224e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent 3193212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent switch (mPlatformType) { 3194212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent case PLATFORM_TELEVISION: 3195212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent ringerModeAffectedStreams = 0; 3196212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent break; 3197212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent default: 319877e54d905f8c0c9925f21a8339a893391179d9d7John Spurlock ringerModeAffectedStreams &= ~(1 << AudioSystem.STREAM_MUSIC); 3199212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent break; 320024e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent } 3201212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent 320224e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent synchronized (mCameraSoundForced) { 320324e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent if (mCameraSoundForced) { 320424e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent ringerModeAffectedStreams &= ~(1 << AudioSystem.STREAM_SYSTEM_ENFORCED); 320524e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent } else { 320624e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent ringerModeAffectedStreams |= (1 << AudioSystem.STREAM_SYSTEM_ENFORCED); 320724e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent } 320824e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent } 320924e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent if (mStreamVolumeAlias[AudioSystem.STREAM_DTMF] == AudioSystem.STREAM_RING) { 321024e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent ringerModeAffectedStreams |= (1 << AudioSystem.STREAM_DTMF); 321124e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent } else { 321224e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent ringerModeAffectedStreams &= ~(1 << AudioSystem.STREAM_DTMF); 321324e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent } 321424e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent 321524e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent if (ringerModeAffectedStreams != mRingerModeAffectedStreams) { 321624e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent Settings.System.putIntForUser(mContentResolver, 321724e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent Settings.System.MODE_RINGER_STREAMS_AFFECTED, 321824e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent ringerModeAffectedStreams, 321924e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent UserHandle.USER_CURRENT); 322024e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent mRingerModeAffectedStreams = ringerModeAffectedStreams; 322124e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent return true; 322224e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent } 322324e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent return false; 322424e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent } 322524e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent 32269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public boolean isStreamAffectedByMute(int streamType) { 32279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return (mMuteAffectedStreams & (1 << streamType)) != 0; 32289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 32299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 32309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private void ensureValidDirection(int direction) { 32319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (direction < AudioManager.ADJUST_LOWER || direction > AudioManager.ADJUST_RAISE) { 32329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw new IllegalArgumentException("Bad direction " + direction); 32339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 32349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 32359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 32366c798970ccb8759d1e613b57111daa8da0ab44c7Lei Zhang private void ensureValidSteps(int steps) { 32376c798970ccb8759d1e613b57111daa8da0ab44c7Lei Zhang if (Math.abs(steps) > MAX_BATCH_VOLUME_ADJUST_STEPS) { 32386c798970ccb8759d1e613b57111daa8da0ab44c7Lei Zhang throw new IllegalArgumentException("Bad volume adjust steps " + steps); 32396c798970ccb8759d1e613b57111daa8da0ab44c7Lei Zhang } 32406c798970ccb8759d1e613b57111daa8da0ab44c7Lei Zhang } 32416c798970ccb8759d1e613b57111daa8da0ab44c7Lei Zhang 32429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private void ensureValidStreamType(int streamType) { 32439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (streamType < 0 || streamType >= mStreamStates.length) { 32449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw new IllegalArgumentException("Bad stream type " + streamType); 32459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 32469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 32479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 32486d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent private boolean isInCommunication() { 32490eb1e402c7e612887e38dc5516f11506b11fd835Nancy Chen boolean IsInCall = false; 325025101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent 3251ef9f6f957d897ea0ed82114185b8fa3fefd4917bTyler Gunn TelecomManager telecomManager = 3252ef9f6f957d897ea0ed82114185b8fa3fefd4917bTyler Gunn (TelecomManager) mContext.getSystemService(Context.TELECOM_SERVICE); 325338edfda9bdd282228db08e3cc449b554b8744625Eric Laurent 325438edfda9bdd282228db08e3cc449b554b8744625Eric Laurent final long ident = Binder.clearCallingIdentity(); 3255ef9f6f957d897ea0ed82114185b8fa3fefd4917bTyler Gunn IsInCall = telecomManager.isInCall(); 325638edfda9bdd282228db08e3cc449b554b8744625Eric Laurent Binder.restoreCallingIdentity(ident); 32579eb45934c582a0bf5060125690de8bce4f10ca76Santos Cordon 32580eb1e402c7e612887e38dc5516f11506b11fd835Nancy Chen return (IsInCall || getMode() == AudioManager.MODE_IN_COMMUNICATION); 32596d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent } 326025101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent 3261fca1e603236b8d1681f784e77e3719d1d59c1428Jean-Michel Trivi /** 3262fca1e603236b8d1681f784e77e3719d1d59c1428Jean-Michel Trivi * For code clarity for getActiveStreamType(int) 3263fca1e603236b8d1681f784e77e3719d1d59c1428Jean-Michel Trivi * @param delay_ms max time since last STREAM_MUSIC activity to consider 3264fca1e603236b8d1681f784e77e3719d1d59c1428Jean-Michel Trivi * @return true if STREAM_MUSIC is active in streams handled by AudioFlinger now or 3265fca1e603236b8d1681f784e77e3719d1d59c1428Jean-Michel Trivi * in the last "delay_ms" ms. 3266fca1e603236b8d1681f784e77e3719d1d59c1428Jean-Michel Trivi */ 3267fca1e603236b8d1681f784e77e3719d1d59c1428Jean-Michel Trivi private boolean isAfMusicActiveRecently(int delay_ms) { 3268fca1e603236b8d1681f784e77e3719d1d59c1428Jean-Michel Trivi return AudioSystem.isStreamActive(AudioSystem.STREAM_MUSIC, delay_ms) 3269fca1e603236b8d1681f784e77e3719d1d59c1428Jean-Michel Trivi || AudioSystem.isStreamActiveRemotely(AudioSystem.STREAM_MUSIC, delay_ms); 3270fca1e603236b8d1681f784e77e3719d1d59c1428Jean-Michel Trivi } 3271fca1e603236b8d1681f784e77e3719d1d59c1428Jean-Michel Trivi 32726d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent private int getActiveStreamType(int suggestedStreamType) { 3273212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent switch (mPlatformType) { 3274212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent case PLATFORM_VOICE: 32756d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent if (isInCommunication()) { 327625101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent if (AudioSystem.getForceUse(AudioSystem.FOR_COMMUNICATION) 327725101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent == AudioSystem.FORCE_BT_SCO) { 327825101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent // Log.v(TAG, "getActiveStreamType: Forcing STREAM_BLUETOOTH_SCO..."); 327925101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent return AudioSystem.STREAM_BLUETOOTH_SCO; 328025101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent } else { 328125101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent // Log.v(TAG, "getActiveStreamType: Forcing STREAM_VOICE_CALL..."); 328225101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent return AudioSystem.STREAM_VOICE_CALL; 328325101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent } 32843114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi } else if (suggestedStreamType == AudioManager.USE_DEFAULT_STREAM_TYPE) { 3285873cc45da2463a11182fe94a2565364d7e1709bbJean-Michel Trivi if (isAfMusicActiveRecently(StreamOverride.sDelayMs)) { 32863114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi if (DEBUG_VOL) 32873114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi Log.v(TAG, "getActiveStreamType: Forcing STREAM_MUSIC stream active"); 32883114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi return AudioSystem.STREAM_MUSIC; 3289fca1e603236b8d1681f784e77e3719d1d59c1428Jean-Michel Trivi } else { 3290fca1e603236b8d1681f784e77e3719d1d59c1428Jean-Michel Trivi if (DEBUG_VOL) 3291fca1e603236b8d1681f784e77e3719d1d59c1428Jean-Michel Trivi Log.v(TAG, "getActiveStreamType: Forcing STREAM_RING b/c default"); 3292fca1e603236b8d1681f784e77e3719d1d59c1428Jean-Michel Trivi return AudioSystem.STREAM_RING; 32933114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi } 3294fca1e603236b8d1681f784e77e3719d1d59c1428Jean-Michel Trivi } else if (isAfMusicActiveRecently(0)) { 32953114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi if (DEBUG_VOL) 32963114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi Log.v(TAG, "getActiveStreamType: Forcing STREAM_MUSIC stream active"); 329725101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent return AudioSystem.STREAM_MUSIC; 329825101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent } 3299212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent break; 3300212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent case PLATFORM_TELEVISION: 3301212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent if (suggestedStreamType == AudioManager.USE_DEFAULT_STREAM_TYPE) { 33022811dd337262934ea82477f9598f3e49092edb5eRoboErik // TV always defaults to STREAM_MUSIC 3303212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent return AudioSystem.STREAM_MUSIC; 3304212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent } 3305212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent break; 3306212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent default: 33076d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent if (isInCommunication()) { 330825101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent if (AudioSystem.getForceUse(AudioSystem.FOR_COMMUNICATION) 330925101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent == AudioSystem.FORCE_BT_SCO) { 33103114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi if (DEBUG_VOL) Log.v(TAG, "getActiveStreamType: Forcing STREAM_BLUETOOTH_SCO"); 331125101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent return AudioSystem.STREAM_BLUETOOTH_SCO; 331225101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent } else { 33133114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi if (DEBUG_VOL) Log.v(TAG, "getActiveStreamType: Forcing STREAM_VOICE_CALL"); 331425101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent return AudioSystem.STREAM_VOICE_CALL; 331525101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent } 331625101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent } else if (AudioSystem.isStreamActive(AudioSystem.STREAM_NOTIFICATION, 3317873cc45da2463a11182fe94a2565364d7e1709bbJean-Michel Trivi StreamOverride.sDelayMs) || 33183114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi AudioSystem.isStreamActive(AudioSystem.STREAM_RING, 3319873cc45da2463a11182fe94a2565364d7e1709bbJean-Michel Trivi StreamOverride.sDelayMs)) { 33203114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi if (DEBUG_VOL) Log.v(TAG, "getActiveStreamType: Forcing STREAM_NOTIFICATION"); 332125101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent return AudioSystem.STREAM_NOTIFICATION; 33223114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi } else if (suggestedStreamType == AudioManager.USE_DEFAULT_STREAM_TYPE) { 3323873cc45da2463a11182fe94a2565364d7e1709bbJean-Michel Trivi if (isAfMusicActiveRecently(StreamOverride.sDelayMs)) { 3324fca1e603236b8d1681f784e77e3719d1d59c1428Jean-Michel Trivi if (DEBUG_VOL) Log.v(TAG, "getActiveStreamType: forcing STREAM_MUSIC"); 3325fca1e603236b8d1681f784e77e3719d1d59c1428Jean-Michel Trivi return AudioSystem.STREAM_MUSIC; 33263114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi } else { 3327eb1d88ddf9a0888455c82b83f19da124e5ca6f16John Spurlock if (DEBUG_VOL) Log.v(TAG, 3328eb1d88ddf9a0888455c82b83f19da124e5ca6f16John Spurlock "getActiveStreamType: using STREAM_NOTIFICATION as default"); 3329eb1d88ddf9a0888455c82b83f19da124e5ca6f16John Spurlock return AudioSystem.STREAM_NOTIFICATION; 33303114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi } 3331c7fcba4b7bd3d78e7cfe975a3f8e4dde2f6738b7Joe Onorato } 3332212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent break; 33339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3334212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent if (DEBUG_VOL) Log.v(TAG, "getActiveStreamType: Returning suggested type " 3335212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent + suggestedStreamType); 3336212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent return suggestedStreamType; 33379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 33389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3339bcc1087af40a0e1bb35dbe8a39c830ecdea8280bJohn Spurlock private void broadcastRingerMode(String action, int ringerMode) { 33409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Send sticky broadcast 3341bcc1087af40a0e1bb35dbe8a39c830ecdea8280bJohn Spurlock Intent broadcast = new Intent(action); 3342ba195ebc76f23b6679443724ab58c9dc9f2df884Glenn Kasten broadcast.putExtra(AudioManager.EXTRA_RINGER_MODE, ringerMode); 33431c633fc89bae9bf0af6fe643ac7ad2e744f27bedDianne Hackborn broadcast.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT 33441c633fc89bae9bf0af6fe643ac7ad2e744f27bedDianne Hackborn | Intent.FLAG_RECEIVER_REPLACE_PENDING); 33455ac72a29593ab9a20337a2225df52bdf4754be02Dianne Hackborn sendStickyBroadcastToAll(broadcast); 33469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 33479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 33489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private void broadcastVibrateSetting(int vibrateType) { 33499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Send broadcast 33509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (ActivityManagerNative.isSystemReady()) { 33519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Intent broadcast = new Intent(AudioManager.VIBRATE_SETTING_CHANGED_ACTION); 33529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project broadcast.putExtra(AudioManager.EXTRA_VIBRATE_TYPE, vibrateType); 33539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project broadcast.putExtra(AudioManager.EXTRA_VIBRATE_SETTING, getVibrateSetting(vibrateType)); 33545ac72a29593ab9a20337a2225df52bdf4754be02Dianne Hackborn sendBroadcastToAll(broadcast); 33559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 33569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 33579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 33589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Message helper methods 33592d8dab5a549b25b6f36df4614d7c0166d4d099e2Jean-Michel Trivi /** 33602d8dab5a549b25b6f36df4614d7c0166d4d099e2Jean-Michel Trivi * Queue a message on the given handler's message queue, after acquiring the service wake lock. 33612d8dab5a549b25b6f36df4614d7c0166d4d099e2Jean-Michel Trivi * Note that the wake lock needs to be released after the message has been handled. 33622d8dab5a549b25b6f36df4614d7c0166d4d099e2Jean-Michel Trivi */ 33632d8dab5a549b25b6f36df4614d7c0166d4d099e2Jean-Michel Trivi private void queueMsgUnderWakeLock(Handler handler, int msg, 33642d8dab5a549b25b6f36df4614d7c0166d4d099e2Jean-Michel Trivi int arg1, int arg2, Object obj, int delay) { 3365a4dfbdc54d8898491d3a7d1d9d818c7db3fd773dEric Laurent final long ident = Binder.clearCallingIdentity(); 3366a4dfbdc54d8898491d3a7d1d9d818c7db3fd773dEric Laurent // Always acquire the wake lock as AudioService because it is released by the 3367a4dfbdc54d8898491d3a7d1d9d818c7db3fd773dEric Laurent // message handler. 3368fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi mAudioEventWakeLock.acquire(); 3369a4dfbdc54d8898491d3a7d1d9d818c7db3fd773dEric Laurent Binder.restoreCallingIdentity(ident); 33702d8dab5a549b25b6f36df4614d7c0166d4d099e2Jean-Michel Trivi sendMsg(handler, msg, SENDMSG_QUEUE, arg1, arg2, obj, delay); 33712d8dab5a549b25b6f36df4614d7c0166d4d099e2Jean-Michel Trivi } 33729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3373afbb047c3945e9c2b7e9bc6b25098d5fb80bba4eEric Laurent private static void sendMsg(Handler handler, int msg, 33749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int existingMsgPolicy, int arg1, int arg2, Object obj, int delay) { 33759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 33769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (existingMsgPolicy == SENDMSG_REPLACE) { 33779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project handler.removeMessages(msg); 33789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (existingMsgPolicy == SENDMSG_NOOP && handler.hasMessages(msg)) { 33799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 33809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3381adbe8bf85f3c8230d16ae5cb3f5d9736e09ed84aEric Laurent synchronized (mLastDeviceConnectMsgTime) { 3382adbe8bf85f3c8230d16ae5cb3f5d9736e09ed84aEric Laurent long time = SystemClock.uptimeMillis() + delay; 3383adbe8bf85f3c8230d16ae5cb3f5d9736e09ed84aEric Laurent handler.sendMessageAtTime(handler.obtainMessage(msg, arg1, arg2, obj), time); 3384adbe8bf85f3c8230d16ae5cb3f5d9736e09ed84aEric Laurent if (msg == MSG_SET_WIRED_DEVICE_CONNECTION_STATE || 3385adbe8bf85f3c8230d16ae5cb3f5d9736e09ed84aEric Laurent msg == MSG_SET_A2DP_SRC_CONNECTION_STATE || 3386adbe8bf85f3c8230d16ae5cb3f5d9736e09ed84aEric Laurent msg == MSG_SET_A2DP_SINK_CONNECTION_STATE) { 3387adbe8bf85f3c8230d16ae5cb3f5d9736e09ed84aEric Laurent mLastDeviceConnectMsgTime = time; 3388adbe8bf85f3c8230d16ae5cb3f5d9736e09ed84aEric Laurent } 3389adbe8bf85f3c8230d16ae5cb3f5d9736e09ed84aEric Laurent } 33909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 33919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 33929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project boolean checkAudioSettingsPermission(String method) { 3393ccd654e9d4c38da0d652c442e7a2ca3f447e9abeJean-Michel Trivi if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.MODIFY_AUDIO_SETTINGS) 33949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project == PackageManager.PERMISSION_GRANTED) { 33959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 33969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 33979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String msg = "Audio Settings Permission Denial: " + method + " from pid=" 33989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project + Binder.getCallingPid() 33999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project + ", uid=" + Binder.getCallingUid(); 34009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Log.w(TAG, msg); 34019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 34029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 34039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 34049bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent private int getDeviceForStream(int stream) { 34059bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent int device = AudioSystem.getDevicesForStream(stream); 34069bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent if ((device & (device - 1)) != 0) { 34079bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent // Multiple device selection is either: 34089bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent // - speaker + one other device: give priority to speaker in this case. 34099bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent // - one A2DP device + another device: happens with duplicated output. In this case 34109bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent // retain the device on the A2DP output as the other must not correspond to an active 34119bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent // selection if not the speaker. 3412c9ff968787d4744194f9985ebaf8ce7efdd12256Jungshik Jang // - HDMI-CEC system audio mode only output: give priority to available item in order. 34139bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent if ((device & AudioSystem.DEVICE_OUT_SPEAKER) != 0) { 34149bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent device = AudioSystem.DEVICE_OUT_SPEAKER; 3415c9ff968787d4744194f9985ebaf8ce7efdd12256Jungshik Jang } else if ((device & AudioSystem.DEVICE_OUT_HDMI_ARC) != 0) { 3416c9ff968787d4744194f9985ebaf8ce7efdd12256Jungshik Jang device = AudioSystem.DEVICE_OUT_HDMI_ARC; 3417c9ff968787d4744194f9985ebaf8ce7efdd12256Jungshik Jang } else if ((device & AudioSystem.DEVICE_OUT_SPDIF) != 0) { 3418c9ff968787d4744194f9985ebaf8ce7efdd12256Jungshik Jang device = AudioSystem.DEVICE_OUT_SPDIF; 3419c9ff968787d4744194f9985ebaf8ce7efdd12256Jungshik Jang } else if ((device & AudioSystem.DEVICE_OUT_AUX_LINE) != 0) { 3420c9ff968787d4744194f9985ebaf8ce7efdd12256Jungshik Jang device = AudioSystem.DEVICE_OUT_AUX_LINE; 34219bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent } else { 34229bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent device &= AudioSystem.DEVICE_OUT_ALL_A2DP; 34239bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent } 34249bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent } 34259bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent return device; 34269bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent } 34279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3428b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent public void setWiredDeviceConnectionState(int device, int state, String name) { 3429b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent synchronized (mConnectedDevices) { 3430b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent int delay = checkSendBecomingNoisyIntent(device, state); 34312d8dab5a549b25b6f36df4614d7c0166d4d099e2Jean-Michel Trivi queueMsgUnderWakeLock(mAudioHandler, 3432b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent MSG_SET_WIRED_DEVICE_CONNECTION_STATE, 3433b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent device, 3434b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent state, 3435b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent name, 3436b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent delay); 3437b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent } 3438b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent } 3439b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent 34400a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood public int setBluetoothA2dpDeviceConnectionState(BluetoothDevice device, int state, int profile) 3441b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent { 3442b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent int delay; 34430a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood if (profile != BluetoothProfile.A2DP && profile != BluetoothProfile.A2DP_SINK) { 34440a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood throw new IllegalArgumentException("invalid profile " + profile); 34450a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood } 3446b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent synchronized (mConnectedDevices) { 34470a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood if (profile == BluetoothProfile.A2DP) { 34480a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood delay = checkSendBecomingNoisyIntent(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, 34490a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood (state == BluetoothA2dp.STATE_CONNECTED) ? 1 : 0); 34500a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood } else { 34510a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood delay = 0; 34520a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood } 34532d8dab5a549b25b6f36df4614d7c0166d4d099e2Jean-Michel Trivi queueMsgUnderWakeLock(mAudioHandler, 34540a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood (profile == BluetoothProfile.A2DP ? 34550a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood MSG_SET_A2DP_SINK_CONNECTION_STATE : MSG_SET_A2DP_SRC_CONNECTION_STATE), 3456b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent state, 3457b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent 0, 3458b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent device, 3459b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent delay); 3460b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent } 3461b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent return delay; 3462b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent } 3463b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent 34649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /////////////////////////////////////////////////////////////////////////// 34659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Inner classes 34669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /////////////////////////////////////////////////////////////////////////// 34679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 34688fa4d6f585f40ff5cf5f9bed316d92c64a306f21Eric Laurent // NOTE: Locking order for synchronized objects related to volume or ringer mode management: 34698fa4d6f585f40ff5cf5f9bed316d92c64a306f21Eric Laurent // 1 mScoclient OR mSafeMediaVolumeState 34708fa4d6f585f40ff5cf5f9bed316d92c64a306f21Eric Laurent // 2 mSetModeDeathHandlers 34718fa4d6f585f40ff5cf5f9bed316d92c64a306f21Eric Laurent // 3 mSettingsLock 34728fa4d6f585f40ff5cf5f9bed316d92c64a306f21Eric Laurent // 4 VolumeStreamState.class 34738fa4d6f585f40ff5cf5f9bed316d92c64a306f21Eric Laurent // 5 mCameraSoundForced 34749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public class VolumeStreamState { 34759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private final int mStreamType; 34769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 347711a74a75653197a3d31fe91590cd8312f5270c44Jean-Michel Trivi private String mVolumeIndexSettingName; 3478a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent private int mIndexMax; 34793172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent private final ConcurrentHashMap<Integer, Integer> mIndex = 34803172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent new ConcurrentHashMap<Integer, Integer>(8, 0.75f, 4); 34819bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent private ArrayList<VolumeDeathHandler> mDeathHandlers; //handles mute/solo clients death 34829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3483a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent private VolumeStreamState(String settingName, int streamType) { 34849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 34859bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent mVolumeIndexSettingName = settingName; 34869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 34879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mStreamType = streamType; 34885982013cfc8274ff0bafaba83c676b3a8890cba9Jared Suttles mIndexMax = MAX_STREAM_VOLUME[streamType]; 3489a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent AudioSystem.initStreamVolume(streamType, 0, mIndexMax); 3490a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent mIndexMax *= 10; 34919bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent 349233902db75011d863009585682bd08560c5b89a75Eric Laurent // mDeathHandlers must be created before calling readSettings() 34939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mDeathHandlers = new ArrayList<VolumeDeathHandler>(); 349433902db75011d863009585682bd08560c5b89a75Eric Laurent 349533902db75011d863009585682bd08560c5b89a75Eric Laurent readSettings(); 34969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 34979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 349842b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent public String getSettingNameForDevice(int device) { 349942b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent String name = mVolumeIndexSettingName; 3500948d32748caaac5be06c991ebf00f74265a7849fEric Laurent String suffix = AudioSystem.getOutputDeviceName(device); 35019bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent if (suffix.isEmpty()) { 35029bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent return name; 35039bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent } 35049bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent return name + "_" + suffix; 35059bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent } 35069bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent 3507fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent public void readSettings() { 3508fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent synchronized (VolumeStreamState.class) { 3509da39290460b30e5080769f039d6dff352b3c7808Wally Yau // force maximum volume on all streams if fixed volume property 3510da39290460b30e5080769f039d6dff352b3c7808Wally Yau // or master volume property is set 3511da39290460b30e5080769f039d6dff352b3c7808Wally Yau if (mUseFixedVolume || mUseMasterVolume) { 3512fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent mIndex.put(AudioSystem.DEVICE_OUT_DEFAULT, mIndexMax); 3513fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent return; 3514fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent } 3515fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent // do not read system stream volume from settings: this stream is always aliased 3516fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent // to another stream type and its volume is never persisted. Values in settings can 3517fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent // only be stale values 3518fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent if ((mStreamType == AudioSystem.STREAM_SYSTEM) || 3519fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent (mStreamType == AudioSystem.STREAM_SYSTEM_ENFORCED)) { 352091377de6f23af2b0b08adae22810cae6fc35cb1aEric Laurent int index = 10 * DEFAULT_STREAM_VOLUME[mStreamType]; 3521fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent synchronized (mCameraSoundForced) { 3522fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent if (mCameraSoundForced) { 3523fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent index = mIndexMax; 3524fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent } 3525dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent } 3526fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent mIndex.put(AudioSystem.DEVICE_OUT_DEFAULT, index); 3527fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent return; 3528dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent } 3529002e9d382d2daa7ed41636463ecdbddbd4897abaEric Laurent 3530fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent int remainingDevices = AudioSystem.DEVICE_OUT_ALL; 353183a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent 3532fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent for (int i = 0; remainingDevices != 0; i++) { 3533fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent int device = (1 << i); 3534fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent if ((device & remainingDevices) == 0) { 3535fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent continue; 3536fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent } 3537fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent remainingDevices &= ~device; 3538fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent 3539fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent // retrieve current volume for device 3540fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent String name = getSettingNameForDevice(device); 3541fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent // if no volume stored for current stream and device, use default volume if default 3542fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent // device, continue otherwise 3543fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent int defaultIndex = (device == AudioSystem.DEVICE_OUT_DEFAULT) ? 354491377de6f23af2b0b08adae22810cae6fc35cb1aEric Laurent DEFAULT_STREAM_VOLUME[mStreamType] : -1; 3545fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent int index = Settings.System.getIntForUser( 3546fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent mContentResolver, name, defaultIndex, UserHandle.USER_CURRENT); 3547fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent if (index == -1) { 3548fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent continue; 3549fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent } 35509bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent 3551212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent mIndex.put(device, getValidIndex(10 * index)); 3552dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent } 35539bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent } 35549bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent } 35559bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent 35568fa4d6f585f40ff5cf5f9bed316d92c64a306f21Eric Laurent // must be called while synchronized VolumeStreamState.class 35578fa4d6f585f40ff5cf5f9bed316d92c64a306f21Eric Laurent public void applyDeviceVolume_syncVSS(int device) { 355842b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent int index; 35598fa4d6f585f40ff5cf5f9bed316d92c64a306f21Eric Laurent if (isMuted_syncVSS()) { 356042b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent index = 0; 3561ba5270b88798c66fefc17a1b25b27894e4fb7862Jean-Michel Trivi } else if (((device & AudioSystem.DEVICE_OUT_ALL_A2DP) != 0 && mAvrcpAbsVolSupported) 3562ba5270b88798c66fefc17a1b25b27894e4fb7862Jean-Michel Trivi || ((device & mFullVolumeDevices) != 0)) { 3563c9d1d5f35091226e96fcfa91817480f589eb36e2Matthew Xie index = (mIndexMax + 5)/10; 3564cd772d04345850e160a45613fcf6b86da0dce4cfEric Laurent } else { 356542b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent index = (getIndex(device) + 5)/10; 356642b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent } 356742b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent AudioSystem.setStreamVolumeIndex(mStreamType, index, device); 35689bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent } 35699bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent 3570fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent public void applyAllVolumes() { 3571fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent synchronized (VolumeStreamState.class) { 3572fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent // apply default volume first: by convention this will reset all 3573fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent // devices volumes in audio policy manager to the supplied value 3574fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent int index; 35758fa4d6f585f40ff5cf5f9bed316d92c64a306f21Eric Laurent if (isMuted_syncVSS()) { 3576fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent index = 0; 3577fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent } else { 3578fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent index = (getIndex(AudioSystem.DEVICE_OUT_DEFAULT) + 5)/10; 3579fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent } 3580fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent AudioSystem.setStreamVolumeIndex(mStreamType, index, AudioSystem.DEVICE_OUT_DEFAULT); 3581fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent // then apply device specific volumes 3582fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent Set set = mIndex.entrySet(); 3583fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent Iterator i = set.iterator(); 3584fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent while (i.hasNext()) { 3585fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent Map.Entry entry = (Map.Entry)i.next(); 3586fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent int device = ((Integer)entry.getKey()).intValue(); 3587fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent if (device != AudioSystem.DEVICE_OUT_DEFAULT) { 35888fa4d6f585f40ff5cf5f9bed316d92c64a306f21Eric Laurent if (isMuted_syncVSS()) { 3589fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent index = 0; 3590ba5270b88798c66fefc17a1b25b27894e4fb7862Jean-Michel Trivi } else if (((device & AudioSystem.DEVICE_OUT_ALL_A2DP) != 0 && 3591ba5270b88798c66fefc17a1b25b27894e4fb7862Jean-Michel Trivi mAvrcpAbsVolSupported) 3592ba5270b88798c66fefc17a1b25b27894e4fb7862Jean-Michel Trivi || ((device & mFullVolumeDevices) != 0)) 3593ba5270b88798c66fefc17a1b25b27894e4fb7862Jean-Michel Trivi { 3594fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent index = (mIndexMax + 5)/10; 3595fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent } else { 3596fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent index = ((Integer)entry.getValue() + 5)/10; 3597fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent } 3598fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent AudioSystem.setStreamVolumeIndex(mStreamType, index, device); 359942b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent } 36009bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent } 36019bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent } 360211a74a75653197a3d31fe91590cd8312f5270c44Jean-Michel Trivi } 360311a74a75653197a3d31fe91590cd8312f5270c44Jean-Michel Trivi 36049bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent public boolean adjustIndex(int deltaIndex, int device) { 360542b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent return setIndex(getIndex(device) + deltaIndex, 360642b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent device); 36079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 36089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3609fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent public boolean setIndex(int index, int device) { 3610fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent synchronized (VolumeStreamState.class) { 3611fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent int oldIndex = getIndex(device); 3612fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent index = getValidIndex(index); 3613fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent synchronized (mCameraSoundForced) { 3614fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent if ((mStreamType == AudioSystem.STREAM_SYSTEM_ENFORCED) && mCameraSoundForced) { 3615fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent index = mIndexMax; 3616fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent } 3617dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent } 3618fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent mIndex.put(device, index); 3619fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent 3620fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent if (oldIndex != index) { 3621fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent // Apply change to all streams using this one as alias 3622fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent // if changing volume of current device, also change volume of current 3623fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent // device on aliased stream 3624fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent boolean currentDevice = (device == getDeviceForStream(mStreamType)); 3625fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent int numStreamTypes = AudioSystem.getNumStreamTypes(); 3626fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent for (int streamType = numStreamTypes - 1; streamType >= 0; streamType--) { 3627fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent if (streamType != mStreamType && 3628fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent mStreamVolumeAlias[streamType] == mStreamType) { 3629fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent int scaledIndex = rescaleIndex(index, mStreamType, streamType); 3630bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent mStreamStates[streamType].setIndex(scaledIndex, 3631fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent device); 3632fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent if (currentDevice) { 3633fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent mStreamStates[streamType].setIndex(scaledIndex, 3634fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent getDeviceForStream(streamType)); 3635fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent } 3636bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent } 3637a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent } 3638fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent return true; 3639fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent } else { 3640fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent return false; 3641a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent } 36429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 36439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 36449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3645fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent public int getIndex(int device) { 3646fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent synchronized (VolumeStreamState.class) { 3647fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent Integer index = mIndex.get(device); 3648fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent if (index == null) { 3649fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent // there is always an entry for AudioSystem.DEVICE_OUT_DEFAULT 3650fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent index = mIndex.get(AudioSystem.DEVICE_OUT_DEFAULT); 3651fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent } 3652fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent return index.intValue(); 36539bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent } 36549bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent } 36559bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent 36569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int getMaxIndex() { 3657a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent return mIndexMax; 36589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 36599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3660fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent public void setAllIndexes(VolumeStreamState srcStream) { 3661fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent synchronized (VolumeStreamState.class) { 3662fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent int srcStreamType = srcStream.getStreamType(); 3663fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent // apply default device volume from source stream to all devices first in case 3664fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent // some devices are present in this stream state but not in source stream state 3665fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent int index = srcStream.getIndex(AudioSystem.DEVICE_OUT_DEFAULT); 366624e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent index = rescaleIndex(index, srcStreamType, mStreamType); 3667fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent Set set = mIndex.entrySet(); 3668fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent Iterator i = set.iterator(); 3669fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent while (i.hasNext()) { 3670fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent Map.Entry entry = (Map.Entry)i.next(); 3671fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent entry.setValue(index); 3672fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent } 3673fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent // Now apply actual volume for devices in source stream state 3674fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent set = srcStream.mIndex.entrySet(); 3675fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent i = set.iterator(); 3676fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent while (i.hasNext()) { 3677fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent Map.Entry entry = (Map.Entry)i.next(); 3678fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent int device = ((Integer)entry.getKey()).intValue(); 3679fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent index = ((Integer)entry.getValue()).intValue(); 3680fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent index = rescaleIndex(index, srcStreamType, mStreamType); 3681fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent 3682fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent setIndex(index, device); 3683fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent } 36846d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent } 36856d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent } 36866d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent 3687fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent public void setAllIndexesToMax() { 3688fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent synchronized (VolumeStreamState.class) { 3689fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent Set set = mIndex.entrySet(); 3690fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent Iterator i = set.iterator(); 3691fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent while (i.hasNext()) { 3692fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent Map.Entry entry = (Map.Entry)i.next(); 3693fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent entry.setValue(mIndexMax); 3694fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent } 3695dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent } 3696dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent } 3697dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent 3698fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent public void mute(IBinder cb, boolean state) { 3699fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent synchronized (VolumeStreamState.class) { 37008fa4d6f585f40ff5cf5f9bed316d92c64a306f21Eric Laurent VolumeDeathHandler handler = getDeathHandler_syncVSS(cb, state); 3701fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent if (handler == null) { 3702fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent Log.e(TAG, "Could not get client death handler for stream: "+mStreamType); 3703fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent return; 3704fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent } 37058fa4d6f585f40ff5cf5f9bed316d92c64a306f21Eric Laurent handler.mute_syncVSS(state); 37069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 37079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 37089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 37096d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent public int getStreamType() { 37106d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent return mStreamType; 37116d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent } 37126d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent 3713212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent public void checkFixedVolumeDevices() { 3714212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent synchronized (VolumeStreamState.class) { 3715212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent // ignore settings for fixed volume devices: volume should always be at max or 0 3716212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent if (mStreamVolumeAlias[mStreamType] == AudioSystem.STREAM_MUSIC) { 3717212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent Set set = mIndex.entrySet(); 3718212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent Iterator i = set.iterator(); 3719212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent while (i.hasNext()) { 3720212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent Map.Entry entry = (Map.Entry)i.next(); 3721212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent int device = ((Integer)entry.getKey()).intValue(); 3722212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent int index = ((Integer)entry.getValue()).intValue(); 3723ba5270b88798c66fefc17a1b25b27894e4fb7862Jean-Michel Trivi if (((device & mFullVolumeDevices) != 0) 3724ba5270b88798c66fefc17a1b25b27894e4fb7862Jean-Michel Trivi || (((device & mFixedVolumeDevices) != 0) && index != 0)) { 3725212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent entry.setValue(mIndexMax); 3726212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent } 37278fa4d6f585f40ff5cf5f9bed316d92c64a306f21Eric Laurent applyDeviceVolume_syncVSS(device); 3728212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent } 3729212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent } 3730212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent } 3731212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent } 3732212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent 37339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private int getValidIndex(int index) { 37349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (index < 0) { 37359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return 0; 3736da39290460b30e5080769f039d6dff352b3c7808Wally Yau } else if (mUseFixedVolume || mUseMasterVolume || index > mIndexMax) { 3737a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent return mIndexMax; 37389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 37399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 37409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return index; 37419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 37429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 37439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private class VolumeDeathHandler implements IBinder.DeathRecipient { 37449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private IBinder mICallback; // To be notified of client's death 37459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private int mMuteCount; // Number of active mutes for this client 37469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 37479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project VolumeDeathHandler(IBinder cb) { 37489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mICallback = cb; 37499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 37509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 37518fa4d6f585f40ff5cf5f9bed316d92c64a306f21Eric Laurent // must be called while synchronized VolumeStreamState.class 37528fa4d6f585f40ff5cf5f9bed316d92c64a306f21Eric Laurent public void mute_syncVSS(boolean state) { 375342b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent boolean updateVolume = false; 37543172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent if (state) { 37553172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent if (mMuteCount == 0) { 37563172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent // Register for client death notification 37573172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent try { 37583172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent // mICallback can be 0 if muted by AudioService 37593172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent if (mICallback != null) { 37603172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent mICallback.linkToDeath(this, 0); 37613172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent } 376242b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent VolumeStreamState.this.mDeathHandlers.add(this); 37633172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent // If the stream is not yet muted by any client, set level to 0 37648fa4d6f585f40ff5cf5f9bed316d92c64a306f21Eric Laurent if (!VolumeStreamState.this.isMuted_syncVSS()) { 376542b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent updateVolume = true; 37663172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent } 37673172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent } catch (RemoteException e) { 37683172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent // Client has died! 37693172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent binderDied(); 37703172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent return; 37713172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent } 37723172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent } else { 37733172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent Log.w(TAG, "stream: "+mStreamType+" was already muted by this client"); 37743172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent } 37753172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent mMuteCount++; 37763172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent } else { 37773172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent if (mMuteCount == 0) { 37783172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent Log.e(TAG, "unexpected unmute for stream: "+mStreamType); 37793172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent } else { 37803172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent mMuteCount--; 37813172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent if (mMuteCount == 0) { 37823172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent // Unregister from client death notification 378342b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent VolumeStreamState.this.mDeathHandlers.remove(this); 37843172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent // mICallback can be 0 if muted by AudioService 37853172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent if (mICallback != null) { 37863172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent mICallback.unlinkToDeath(this, 0); 37873172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent } 37888fa4d6f585f40ff5cf5f9bed316d92c64a306f21Eric Laurent if (!VolumeStreamState.this.isMuted_syncVSS()) { 378942b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent updateVolume = true; 37909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 37919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 37929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 37939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 379442b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent if (updateVolume) { 379542b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent sendMsg(mAudioHandler, 379642b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent MSG_SET_ALL_VOLUMES, 379742b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent SENDMSG_QUEUE, 379842b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent 0, 379942b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent 0, 380042b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent VolumeStreamState.this, 0); 380142b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent } 38029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 38039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 38049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void binderDied() { 38059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Log.w(TAG, "Volume service client died for stream: "+mStreamType); 38068fa4d6f585f40ff5cf5f9bed316d92c64a306f21Eric Laurent synchronized (VolumeStreamState.class) { 38078fa4d6f585f40ff5cf5f9bed316d92c64a306f21Eric Laurent if (mMuteCount != 0) { 38088fa4d6f585f40ff5cf5f9bed316d92c64a306f21Eric Laurent // Reset all active mute requests from this client. 38098fa4d6f585f40ff5cf5f9bed316d92c64a306f21Eric Laurent mMuteCount = 1; 38108fa4d6f585f40ff5cf5f9bed316d92c64a306f21Eric Laurent mute_syncVSS(false); 38118fa4d6f585f40ff5cf5f9bed316d92c64a306f21Eric Laurent } 38129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 38139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 38149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 38159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 38168fa4d6f585f40ff5cf5f9bed316d92c64a306f21Eric Laurent private int muteCount() { 38179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int count = 0; 38189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int size = mDeathHandlers.size(); 38199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = 0; i < size; i++) { 38209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project count += mDeathHandlers.get(i).mMuteCount; 38219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 38229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return count; 38239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 38249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 38258fa4d6f585f40ff5cf5f9bed316d92c64a306f21Eric Laurent // must be called while synchronized VolumeStreamState.class 38268fa4d6f585f40ff5cf5f9bed316d92c64a306f21Eric Laurent private boolean isMuted_syncVSS() { 382742b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent return muteCount() != 0; 382842b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent } 382942b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent 38308fa4d6f585f40ff5cf5f9bed316d92c64a306f21Eric Laurent // must be called while synchronized VolumeStreamState.class 38318fa4d6f585f40ff5cf5f9bed316d92c64a306f21Eric Laurent private VolumeDeathHandler getDeathHandler_syncVSS(IBinder cb, boolean state) { 38323172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent VolumeDeathHandler handler; 38333172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent int size = mDeathHandlers.size(); 38343172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent for (int i = 0; i < size; i++) { 38353172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent handler = mDeathHandlers.get(i); 38363172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent if (cb == handler.mICallback) { 38373172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent return handler; 3838ce952c8e13c535bedde77bcdb94dfcc7508475aaMike Lockwood } 3839ce952c8e13c535bedde77bcdb94dfcc7508475aaMike Lockwood } 38403172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent // If this is the first mute request for this client, create a new 38413172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent // client death handler. Otherwise, it is an out of sequence unmute request. 38423172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent if (state) { 38433172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent handler = new VolumeDeathHandler(cb); 38443172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent } else { 38453172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent Log.w(TAG, "stream was not muted by this client"); 38463172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent handler = null; 38473172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent } 38483172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent return handler; 3849ce952c8e13c535bedde77bcdb94dfcc7508475aaMike Lockwood } 3850bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent 3851bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent private void dump(PrintWriter pw) { 3852dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent pw.print(" Mute count: "); 3853dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent pw.println(muteCount()); 38542b29bc4c1cef64abdf3a68b60bdcf7207193e980John Spurlock pw.print(" Max: "); 38552b29bc4c1cef64abdf3a68b60bdcf7207193e980John Spurlock pw.println((mIndexMax + 5) / 10); 3856bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent pw.print(" Current: "); 3857bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent Set set = mIndex.entrySet(); 3858bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent Iterator i = set.iterator(); 3859bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent while (i.hasNext()) { 3860bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent Map.Entry entry = (Map.Entry)i.next(); 38612b29bc4c1cef64abdf3a68b60bdcf7207193e980John Spurlock final int device = (Integer) entry.getKey(); 38622b29bc4c1cef64abdf3a68b60bdcf7207193e980John Spurlock pw.print(Integer.toHexString(device)); 38632b29bc4c1cef64abdf3a68b60bdcf7207193e980John Spurlock final String deviceName = device == AudioSystem.DEVICE_OUT_DEFAULT ? "default" 38642b29bc4c1cef64abdf3a68b60bdcf7207193e980John Spurlock : AudioSystem.getOutputDeviceName(device); 38652b29bc4c1cef64abdf3a68b60bdcf7207193e980John Spurlock if (!deviceName.isEmpty()) { 38662b29bc4c1cef64abdf3a68b60bdcf7207193e980John Spurlock pw.print(" ("); 38672b29bc4c1cef64abdf3a68b60bdcf7207193e980John Spurlock pw.print(deviceName); 38682b29bc4c1cef64abdf3a68b60bdcf7207193e980John Spurlock pw.print(")"); 38692b29bc4c1cef64abdf3a68b60bdcf7207193e980John Spurlock } 38702b29bc4c1cef64abdf3a68b60bdcf7207193e980John Spurlock pw.print(": "); 38712b29bc4c1cef64abdf3a68b60bdcf7207193e980John Spurlock final int index = (((Integer) entry.getValue()) + 5) / 10; 38722b29bc4c1cef64abdf3a68b60bdcf7207193e980John Spurlock pw.print(index); 38732b29bc4c1cef64abdf3a68b60bdcf7207193e980John Spurlock if (i.hasNext()) { 38742b29bc4c1cef64abdf3a68b60bdcf7207193e980John Spurlock pw.print(", "); 38752b29bc4c1cef64abdf3a68b60bdcf7207193e980John Spurlock } 3876bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent } 3877bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent } 3878ce952c8e13c535bedde77bcdb94dfcc7508475aaMike Lockwood } 3879ce952c8e13c535bedde77bcdb94dfcc7508475aaMike Lockwood 38809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** Thread that handles native AudioSystem control. */ 38819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private class AudioSystemThread extends Thread { 38829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project AudioSystemThread() { 38839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project super("AudioService"); 38849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 38859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 38869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 38879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void run() { 38889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Set this thread up so the handler will work on it 38899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Looper.prepare(); 38909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 38919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project synchronized(AudioService.this) { 38929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mAudioHandler = new AudioHandler(); 38939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 38949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Notify that the handler has been created 38959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project AudioService.this.notify(); 38969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 38979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 38989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Listen for volume change requests that are set by VolumePanel 38999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Looper.loop(); 39009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 39019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 39029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 39039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** Handles internal volume messages in separate volume thread. */ 39049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private class AudioHandler extends Handler { 39059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 39069bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent private void setDeviceVolume(VolumeStreamState streamState, int device) { 39079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 39088fa4d6f585f40ff5cf5f9bed316d92c64a306f21Eric Laurent synchronized (VolumeStreamState.class) { 39098fa4d6f585f40ff5cf5f9bed316d92c64a306f21Eric Laurent // Apply volume 39108fa4d6f585f40ff5cf5f9bed316d92c64a306f21Eric Laurent streamState.applyDeviceVolume_syncVSS(device); 39118fa4d6f585f40ff5cf5f9bed316d92c64a306f21Eric Laurent 39128fa4d6f585f40ff5cf5f9bed316d92c64a306f21Eric Laurent // Apply change to all streams using this one as alias 39138fa4d6f585f40ff5cf5f9bed316d92c64a306f21Eric Laurent int numStreamTypes = AudioSystem.getNumStreamTypes(); 39148fa4d6f585f40ff5cf5f9bed316d92c64a306f21Eric Laurent for (int streamType = numStreamTypes - 1; streamType >= 0; streamType--) { 39158fa4d6f585f40ff5cf5f9bed316d92c64a306f21Eric Laurent if (streamType != streamState.mStreamType && 39168fa4d6f585f40ff5cf5f9bed316d92c64a306f21Eric Laurent mStreamVolumeAlias[streamType] == streamState.mStreamType) { 39178fa4d6f585f40ff5cf5f9bed316d92c64a306f21Eric Laurent // Make sure volume is also maxed out on A2DP device for aliased stream 39188fa4d6f585f40ff5cf5f9bed316d92c64a306f21Eric Laurent // that may have a different device selected 39198fa4d6f585f40ff5cf5f9bed316d92c64a306f21Eric Laurent int streamDevice = getDeviceForStream(streamType); 39208fa4d6f585f40ff5cf5f9bed316d92c64a306f21Eric Laurent if ((device != streamDevice) && mAvrcpAbsVolSupported && 39218fa4d6f585f40ff5cf5f9bed316d92c64a306f21Eric Laurent ((device & AudioSystem.DEVICE_OUT_ALL_A2DP) != 0)) { 39228fa4d6f585f40ff5cf5f9bed316d92c64a306f21Eric Laurent mStreamStates[streamType].applyDeviceVolume_syncVSS(device); 39238fa4d6f585f40ff5cf5f9bed316d92c64a306f21Eric Laurent } 39248fa4d6f585f40ff5cf5f9bed316d92c64a306f21Eric Laurent mStreamStates[streamType].applyDeviceVolume_syncVSS(streamDevice); 3925cd772d04345850e160a45613fcf6b86da0dce4cfEric Laurent } 3926a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent } 3927a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent } 39289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Post a persist volume msg 3929afbb047c3945e9c2b7e9bc6b25098d5fb80bba4eEric Laurent sendMsg(mAudioHandler, 3930afbb047c3945e9c2b7e9bc6b25098d5fb80bba4eEric Laurent MSG_PERSIST_VOLUME, 393198ad9b9d6fd34aad487933170f50b5519313df61Eric Laurent SENDMSG_QUEUE, 39329bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent device, 393342b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent 0, 3934afbb047c3945e9c2b7e9bc6b25098d5fb80bba4eEric Laurent streamState, 3935afbb047c3945e9c2b7e9bc6b25098d5fb80bba4eEric Laurent PERSIST_DELAY); 3936afbb047c3945e9c2b7e9bc6b25098d5fb80bba4eEric Laurent 39379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 39389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 39399bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent private void setAllVolumes(VolumeStreamState streamState) { 39409bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent 39419bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent // Apply volume 39429bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent streamState.applyAllVolumes(); 39439bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent 39449bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent // Apply change to all streams using this one as alias 39459bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent int numStreamTypes = AudioSystem.getNumStreamTypes(); 39469bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent for (int streamType = numStreamTypes - 1; streamType >= 0; streamType--) { 39479bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent if (streamType != streamState.mStreamType && 39486d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent mStreamVolumeAlias[streamType] == streamState.mStreamType) { 39499bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent mStreamStates[streamType].applyAllVolumes(); 39509bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent } 39519bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent } 39529bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent } 39539bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent 395442b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent private void persistVolume(VolumeStreamState streamState, int device) { 395583a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent if (mUseFixedVolume) { 395683a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent return; 395783a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent } 3958212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent if (isPlatformTelevision() && (streamState.mStreamType != AudioSystem.STREAM_MUSIC)) { 3959212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent return; 3960212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent } 396142b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent System.putIntForUser(mContentResolver, 396242b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent streamState.getSettingNameForDevice(device), 396342b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent (streamState.getIndex(device) + 5)/ 10, 396442b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent UserHandle.USER_CURRENT); 39659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 39669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3967ba195ebc76f23b6679443724ab58c9dc9f2df884Glenn Kasten private void persistRingerMode(int ringerMode) { 396883a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent if (mUseFixedVolume) { 396983a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent return; 397083a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent } 39718d9a1f66d9d3dbbd45a56d441a746ec11dba7645Jeff Sharkey Settings.Global.putInt(mContentResolver, Settings.Global.MODE_RINGER, ringerMode); 39729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 39739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 39745d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent private boolean onLoadSoundEffects() { 39755d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent int status; 39765d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent 39775d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent synchronized (mSoundEffectsLock) { 39784a5eeb9c727d77bb57fef87a70c8c9cc23dbfee3Eric Laurent if (!mSystemReady) { 39795d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent Log.w(TAG, "onLoadSoundEffects() called before boot complete"); 39805d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent return false; 39815d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent } 39825d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent 39835d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent if (mSoundPool != null) { 39845d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent return true; 39855d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent } 39865d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent 39875d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent loadTouchSoundAssets(); 39885d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent 398955a30c41b6c47d3afe6b13c25c64e8eec9f45e7cJean-Michel Trivi mSoundPool = new SoundPool.Builder() 399055a30c41b6c47d3afe6b13c25c64e8eec9f45e7cJean-Michel Trivi .setMaxStreams(NUM_SOUNDPOOL_CHANNELS) 399155a30c41b6c47d3afe6b13c25c64e8eec9f45e7cJean-Michel Trivi .setAudioAttributes(new AudioAttributes.Builder() 399255a30c41b6c47d3afe6b13c25c64e8eec9f45e7cJean-Michel Trivi .setUsage(AudioAttributes.USAGE_ASSISTANCE_SONIFICATION) 399355a30c41b6c47d3afe6b13c25c64e8eec9f45e7cJean-Michel Trivi .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION) 399455a30c41b6c47d3afe6b13c25c64e8eec9f45e7cJean-Michel Trivi .build()) 399555a30c41b6c47d3afe6b13c25c64e8eec9f45e7cJean-Michel Trivi .build(); 39965d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent mSoundPoolCallBack = null; 39975d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent mSoundPoolListenerThread = new SoundPoolListenerThread(); 39985d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent mSoundPoolListenerThread.start(); 39995d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent int attempts = 3; 40005d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent while ((mSoundPoolCallBack == null) && (attempts-- > 0)) { 40015d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent try { 40025d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent // Wait for mSoundPoolCallBack to be set by the other thread 4003167d1a27713ab64cd3c0aa70de96434083ef0400Glenn Kasten mSoundEffectsLock.wait(SOUND_EFFECTS_LOAD_TIMEOUT_MS); 40045d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent } catch (InterruptedException e) { 40055d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent Log.w(TAG, "Interrupted while waiting sound pool listener thread."); 40065d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent } 40075d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent } 40085d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent 40095d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent if (mSoundPoolCallBack == null) { 40105d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent Log.w(TAG, "onLoadSoundEffects() SoundPool listener or thread creation error"); 40115d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent if (mSoundPoolLooper != null) { 40125d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent mSoundPoolLooper.quit(); 40135d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent mSoundPoolLooper = null; 40145d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent } 40155d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent mSoundPoolListenerThread = null; 40165d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent mSoundPool.release(); 40175d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent mSoundPool = null; 40185d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent return false; 40195d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent } 40205d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent /* 40215d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent * poolId table: The value -1 in this table indicates that corresponding 40225d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent * file (same index in SOUND_EFFECT_FILES[] has not been loaded. 40235d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent * Once loaded, the value in poolId is the sample ID and the same 40245d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent * sample can be reused for another effect using the same file. 40255d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent */ 40265d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent int[] poolId = new int[SOUND_EFFECT_FILES.size()]; 40275d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent for (int fileIdx = 0; fileIdx < SOUND_EFFECT_FILES.size(); fileIdx++) { 40285d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent poolId[fileIdx] = -1; 40295d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent } 40305d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent /* 40315d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent * Effects whose value in SOUND_EFFECT_FILES_MAP[effect][1] is -1 must be loaded. 40325d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent * If load succeeds, value in SOUND_EFFECT_FILES_MAP[effect][1] is > 0: 40335d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent * this indicates we have a valid sample loaded for this effect. 40345d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent */ 40355d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent 40365d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent int numSamples = 0; 40375d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent for (int effect = 0; effect < AudioManager.NUM_SOUND_EFFECTS; effect++) { 40385d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent // Do not load sample if this effect uses the MediaPlayer 40395d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent if (SOUND_EFFECT_FILES_MAP[effect][1] == 0) { 40405d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent continue; 40415d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent } 40425d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent if (poolId[SOUND_EFFECT_FILES_MAP[effect][0]] == -1) { 40435d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent String filePath = Environment.getRootDirectory() 40445d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent + SOUND_EFFECTS_PATH 40455d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent + SOUND_EFFECT_FILES.get(SOUND_EFFECT_FILES_MAP[effect][0]); 40465d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent int sampleId = mSoundPool.load(filePath, 0); 40475d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent if (sampleId <= 0) { 40485d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent Log.w(TAG, "Soundpool could not load file: "+filePath); 40495d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent } else { 40505d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent SOUND_EFFECT_FILES_MAP[effect][1] = sampleId; 40515d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent poolId[SOUND_EFFECT_FILES_MAP[effect][0]] = sampleId; 40525d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent numSamples++; 40535d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent } 40545d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent } else { 40555d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent SOUND_EFFECT_FILES_MAP[effect][1] = 40565d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent poolId[SOUND_EFFECT_FILES_MAP[effect][0]]; 40575d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent } 40585d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent } 40595d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent // wait for all samples to be loaded 40605d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent if (numSamples > 0) { 40615d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent mSoundPoolCallBack.setSamples(poolId); 40625d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent 40635d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent attempts = 3; 40645d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent status = 1; 40655d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent while ((status == 1) && (attempts-- > 0)) { 40665d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent try { 4067167d1a27713ab64cd3c0aa70de96434083ef0400Glenn Kasten mSoundEffectsLock.wait(SOUND_EFFECTS_LOAD_TIMEOUT_MS); 40685d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent status = mSoundPoolCallBack.status(); 40695d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent } catch (InterruptedException e) { 40705d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent Log.w(TAG, "Interrupted while waiting sound pool callback."); 40715d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent } 40725d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent } 40735d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent } else { 40745d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent status = -1; 40755d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent } 40765d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent 40775d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent if (mSoundPoolLooper != null) { 40785d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent mSoundPoolLooper.quit(); 40795d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent mSoundPoolLooper = null; 40805d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent } 40815d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent mSoundPoolListenerThread = null; 40825d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent if (status != 0) { 40835d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent Log.w(TAG, 40845d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent "onLoadSoundEffects(), Error "+status+ " while loading samples"); 40855d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent for (int effect = 0; effect < AudioManager.NUM_SOUND_EFFECTS; effect++) { 40865d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent if (SOUND_EFFECT_FILES_MAP[effect][1] > 0) { 40875d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent SOUND_EFFECT_FILES_MAP[effect][1] = -1; 40885d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent } 40895d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent } 40905d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent 40915d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent mSoundPool.release(); 40925d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent mSoundPool = null; 40935d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent } 40945d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent } 40955d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent return (status == 0); 40965d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent } 40975d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent 40985d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent /** 40995d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent * Unloads samples from the sound pool. 41005d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent * This method can be called to free some memory when 41015d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent * sound effects are disabled. 41025d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent */ 41035d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent private void onUnloadSoundEffects() { 41045d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent synchronized (mSoundEffectsLock) { 41055d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent if (mSoundPool == null) { 41065d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent return; 41075d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent } 41085d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent 41095d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent int[] poolId = new int[SOUND_EFFECT_FILES.size()]; 41105d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent for (int fileIdx = 0; fileIdx < SOUND_EFFECT_FILES.size(); fileIdx++) { 41115d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent poolId[fileIdx] = 0; 41125d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent } 41135d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent 41145d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent for (int effect = 0; effect < AudioManager.NUM_SOUND_EFFECTS; effect++) { 41155d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent if (SOUND_EFFECT_FILES_MAP[effect][1] <= 0) { 41165d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent continue; 41175d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent } 41185d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent if (poolId[SOUND_EFFECT_FILES_MAP[effect][0]] == 0) { 41195d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent mSoundPool.unload(SOUND_EFFECT_FILES_MAP[effect][1]); 41205d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent SOUND_EFFECT_FILES_MAP[effect][1] = -1; 41215d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent poolId[SOUND_EFFECT_FILES_MAP[effect][0]] = -1; 41225d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent } 41235d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent } 41245d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent mSoundPool.release(); 41255d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent mSoundPool = null; 41265d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent } 41275d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent } 41285d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent 41295d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent private void onPlaySoundEffect(int effectType, int volume) { 41309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project synchronized (mSoundEffectsLock) { 41315d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent 41325d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent onLoadSoundEffects(); 41335d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent 41349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mSoundPool == null) { 41359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 41369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4137a2ef57dba9ac77d8eccacd646b2b8a8d99fe9d8bEric Laurent float volFloat; 413825101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent // use default if volume is not specified by caller 4139a2ef57dba9ac77d8eccacd646b2b8a8d99fe9d8bEric Laurent if (volume < 0) { 4140f2b0c11f4e797e183131261724d8de310dac5431Jean-Michel Trivi volFloat = (float)Math.pow(10, (float)sSoundEffectVolumeDb/20); 4141a2ef57dba9ac77d8eccacd646b2b8a8d99fe9d8bEric Laurent } else { 41428a2cfc309ab9126e90022916967c65a793c034f0RoboErik volFloat = volume / 1000.0f; 4143a2ef57dba9ac77d8eccacd646b2b8a8d99fe9d8bEric Laurent } 41449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 41459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (SOUND_EFFECT_FILES_MAP[effectType][1] > 0) { 41465d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent mSoundPool.play(SOUND_EFFECT_FILES_MAP[effectType][1], 41475d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent volFloat, volFloat, 0, 0, 1.0f); 41489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 41499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project MediaPlayer mediaPlayer = new MediaPlayer(); 415062b9aec7a0a4e1cf8cfec7e39ea3103ab510d72eGlenn Kasten try { 4151e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent String filePath = Environment.getRootDirectory() + SOUND_EFFECTS_PATH + 4152e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent SOUND_EFFECT_FILES.get(SOUND_EFFECT_FILES_MAP[effectType][0]); 415362b9aec7a0a4e1cf8cfec7e39ea3103ab510d72eGlenn Kasten mediaPlayer.setDataSource(filePath); 415462b9aec7a0a4e1cf8cfec7e39ea3103ab510d72eGlenn Kasten mediaPlayer.setAudioStreamType(AudioSystem.STREAM_SYSTEM); 415562b9aec7a0a4e1cf8cfec7e39ea3103ab510d72eGlenn Kasten mediaPlayer.prepare(); 4156068225de0197df07a0247b2877666ea91c22c992Glenn Kasten mediaPlayer.setVolume(volFloat); 415762b9aec7a0a4e1cf8cfec7e39ea3103ab510d72eGlenn Kasten mediaPlayer.setOnCompletionListener(new OnCompletionListener() { 415862b9aec7a0a4e1cf8cfec7e39ea3103ab510d72eGlenn Kasten public void onCompletion(MediaPlayer mp) { 415962b9aec7a0a4e1cf8cfec7e39ea3103ab510d72eGlenn Kasten cleanupPlayer(mp); 416062b9aec7a0a4e1cf8cfec7e39ea3103ab510d72eGlenn Kasten } 416162b9aec7a0a4e1cf8cfec7e39ea3103ab510d72eGlenn Kasten }); 416262b9aec7a0a4e1cf8cfec7e39ea3103ab510d72eGlenn Kasten mediaPlayer.setOnErrorListener(new OnErrorListener() { 416362b9aec7a0a4e1cf8cfec7e39ea3103ab510d72eGlenn Kasten public boolean onError(MediaPlayer mp, int what, int extra) { 416462b9aec7a0a4e1cf8cfec7e39ea3103ab510d72eGlenn Kasten cleanupPlayer(mp); 416562b9aec7a0a4e1cf8cfec7e39ea3103ab510d72eGlenn Kasten return true; 416662b9aec7a0a4e1cf8cfec7e39ea3103ab510d72eGlenn Kasten } 416762b9aec7a0a4e1cf8cfec7e39ea3103ab510d72eGlenn Kasten }); 416862b9aec7a0a4e1cf8cfec7e39ea3103ab510d72eGlenn Kasten mediaPlayer.start(); 416962b9aec7a0a4e1cf8cfec7e39ea3103ab510d72eGlenn Kasten } catch (IOException ex) { 417062b9aec7a0a4e1cf8cfec7e39ea3103ab510d72eGlenn Kasten Log.w(TAG, "MediaPlayer IOException: "+ex); 417162b9aec7a0a4e1cf8cfec7e39ea3103ab510d72eGlenn Kasten } catch (IllegalArgumentException ex) { 417262b9aec7a0a4e1cf8cfec7e39ea3103ab510d72eGlenn Kasten Log.w(TAG, "MediaPlayer IllegalArgumentException: "+ex); 417362b9aec7a0a4e1cf8cfec7e39ea3103ab510d72eGlenn Kasten } catch (IllegalStateException ex) { 417462b9aec7a0a4e1cf8cfec7e39ea3103ab510d72eGlenn Kasten Log.w(TAG, "MediaPlayer IllegalStateException: "+ex); 41759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 41769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 41779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 41789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 41799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 41809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private void cleanupPlayer(MediaPlayer mp) { 41819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mp != null) { 41829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 41839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mp.stop(); 41849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mp.release(); 41859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } catch (IllegalStateException ex) { 41869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Log.w(TAG, "MediaPlayer IllegalStateException: "+ex); 41879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 41889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 41899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 41909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4191fa640154f1f42121d81242b2f1a10f03e52f0014Eric Laurent private void setForceUse(int usage, int config) { 4192fa640154f1f42121d81242b2f1a10f03e52f0014Eric Laurent AudioSystem.setForceUse(usage, config); 4193fa640154f1f42121d81242b2f1a10f03e52f0014Eric Laurent } 4194fa640154f1f42121d81242b2f1a10f03e52f0014Eric Laurent 419505274f348e12983eb8613cc6eb9ae561e8197e28Eric Laurent private void onPersistSafeVolumeState(int state) { 419605274f348e12983eb8613cc6eb9ae561e8197e28Eric Laurent Settings.Global.putInt(mContentResolver, 419705274f348e12983eb8613cc6eb9ae561e8197e28Eric Laurent Settings.Global.AUDIO_SAFE_VOLUME_STATE, 419805274f348e12983eb8613cc6eb9ae561e8197e28Eric Laurent state); 419905274f348e12983eb8613cc6eb9ae561e8197e28Eric Laurent } 420005274f348e12983eb8613cc6eb9ae561e8197e28Eric Laurent 42019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 42029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void handleMessage(Message msg) { 4203afbb047c3945e9c2b7e9bc6b25098d5fb80bba4eEric Laurent switch (msg.what) { 42049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 42059bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent case MSG_SET_DEVICE_VOLUME: 42069bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent setDeviceVolume((VolumeStreamState) msg.obj, msg.arg1); 42079bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent break; 42089bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent 42099bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent case MSG_SET_ALL_VOLUMES: 42109bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent setAllVolumes((VolumeStreamState) msg.obj); 42119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 42129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 42139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case MSG_PERSIST_VOLUME: 421442b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent persistVolume((VolumeStreamState) msg.obj, msg.arg1); 42159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 42169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 42175c55a051ad7d86a464fb91426f1ea3c0250e38b3Mike Lockwood case MSG_PERSIST_MASTER_VOLUME: 421883a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent if (mUseFixedVolume) { 421983a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent return; 422083a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent } 4221bc0fab1fc2db832ef86d8a33466ec4d68b103ca0Eric Laurent Settings.System.putFloatForUser(mContentResolver, 4222bc0fab1fc2db832ef86d8a33466ec4d68b103ca0Eric Laurent Settings.System.VOLUME_MASTER, 42238a2cfc309ab9126e90022916967c65a793c034f0RoboErik msg.arg1 / (float)1000.0, 4224bc0fab1fc2db832ef86d8a33466ec4d68b103ca0Eric Laurent UserHandle.USER_CURRENT); 42255c55a051ad7d86a464fb91426f1ea3c0250e38b3Mike Lockwood break; 42265c55a051ad7d86a464fb91426f1ea3c0250e38b3Mike Lockwood 422757978ed86286a33d5b1a0fd000ca3406ba9d87b3Justin Koh case MSG_PERSIST_MASTER_VOLUME_MUTE: 422883a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent if (mUseFixedVolume) { 422983a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent return; 423083a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent } 4231bc0fab1fc2db832ef86d8a33466ec4d68b103ca0Eric Laurent Settings.System.putIntForUser(mContentResolver, 4232bc0fab1fc2db832ef86d8a33466ec4d68b103ca0Eric Laurent Settings.System.VOLUME_MASTER_MUTE, 4233bc0fab1fc2db832ef86d8a33466ec4d68b103ca0Eric Laurent msg.arg1, 4234b53453fae037d67e421011936c8fdffe7ba43922Julia Reynolds msg.arg2); 423557978ed86286a33d5b1a0fd000ca3406ba9d87b3Justin Koh break; 423657978ed86286a33d5b1a0fd000ca3406ba9d87b3Justin Koh 42379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case MSG_PERSIST_RINGER_MODE: 4238ba195ebc76f23b6679443724ab58c9dc9f2df884Glenn Kasten // note that the value persisted is the current ringer mode, not the 4239ba195ebc76f23b6679443724ab58c9dc9f2df884Glenn Kasten // value of ringer mode as of the time the request was made to persist 4240661f2cf45860d2e10924e6b69966a9afe255f28bJohn Spurlock persistRingerMode(getRingerModeInternal()); 42419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 42429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 42439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case MSG_MEDIA_SERVER_DIED: 4244eb4b8a27e3219726691a868793d2247dc9d2a317Eric Laurent if (!mSystemReady || 4245eb4b8a27e3219726691a868793d2247dc9d2a317Eric Laurent (AudioSystem.checkAudioFlinger() != AudioSystem.AUDIO_STATUS_OK)) { 424689e74ba1419732dd5c7f939e48d4aa7989fd3a51Eric Laurent Log.e(TAG, "Media server died."); 4247afbb047c3945e9c2b7e9bc6b25098d5fb80bba4eEric Laurent sendMsg(mAudioHandler, MSG_MEDIA_SERVER_DIED, SENDMSG_NOOP, 0, 0, 424889e74ba1419732dd5c7f939e48d4aa7989fd3a51Eric Laurent null, 500); 4249dfb881f96af7898151940a4bbc52e45e6043d38bEric Laurent break; 425089e74ba1419732dd5c7f939e48d4aa7989fd3a51Eric Laurent } 42519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Log.e(TAG, "Media server started."); 4252dfb881f96af7898151940a4bbc52e45e6043d38bEric Laurent 42533c652ca5a546e7227a5f4bdbf0f81552b2c91383Eric Laurent // indicate to audio HAL that we start the reconfiguration phase after a media 42543c652ca5a546e7227a5f4bdbf0f81552b2c91383Eric Laurent // server crash 4255dfb881f96af7898151940a4bbc52e45e6043d38bEric Laurent // Note that we only execute this when the media server 42563c652ca5a546e7227a5f4bdbf0f81552b2c91383Eric Laurent // process restarts after a crash, not the first time it is started. 42573c652ca5a546e7227a5f4bdbf0f81552b2c91383Eric Laurent AudioSystem.setParameters("restarting=true"); 42583c652ca5a546e7227a5f4bdbf0f81552b2c91383Eric Laurent 4259fd116ad1ab02f6060a0b2201f018317fa32e28b4Glenn Kasten readAndSetLowRamDevice(); 4260fd116ad1ab02f6060a0b2201f018317fa32e28b4Glenn Kasten 4261c42ac9d4d03f62c3a1ba197a28a81fda44bd8b7fEric Laurent // Restore device connection states 42626bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent synchronized (mConnectedDevices) { 42636bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent Set set = mConnectedDevices.entrySet(); 42646bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent Iterator i = set.iterator(); 42659bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent while (i.hasNext()) { 42666bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent Map.Entry device = (Map.Entry)i.next(); 42676bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent AudioSystem.setDeviceConnectionState( 42686bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent ((Integer)device.getKey()).intValue(), 42696bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent AudioSystem.DEVICE_STATE_AVAILABLE, 42706bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent (String)device.getValue()); 42716bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent } 4272c42ac9d4d03f62c3a1ba197a28a81fda44bd8b7fEric Laurent } 4273c42ac9d4d03f62c3a1ba197a28a81fda44bd8b7fEric Laurent // Restore call state 4274c42ac9d4d03f62c3a1ba197a28a81fda44bd8b7fEric Laurent AudioSystem.setPhoneState(mMode); 4275c42ac9d4d03f62c3a1ba197a28a81fda44bd8b7fEric Laurent 4276d5603c126acdd94d9f7400bb1d04188020a425b4Eric Laurent // Restore forced usage for communcations and record 4277c42ac9d4d03f62c3a1ba197a28a81fda44bd8b7fEric Laurent AudioSystem.setForceUse(AudioSystem.FOR_COMMUNICATION, mForcedUseForComm); 4278d5603c126acdd94d9f7400bb1d04188020a425b4Eric Laurent AudioSystem.setForceUse(AudioSystem.FOR_RECORD, mForcedUseForComm); 4279dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent AudioSystem.setForceUse(AudioSystem.FOR_SYSTEM, mCameraSoundForced ? 4280dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent AudioSystem.FORCE_SYSTEM_ENFORCED : AudioSystem.FORCE_NONE); 4281c42ac9d4d03f62c3a1ba197a28a81fda44bd8b7fEric Laurent 4282a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent // Restore stream volumes 42839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int numStreamTypes = AudioSystem.getNumStreamTypes(); 42849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int streamType = numStreamTypes - 1; streamType >= 0; streamType--) { 42859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project VolumeStreamState streamState = mStreamStates[streamType]; 4286c42ac9d4d03f62c3a1ba197a28a81fda44bd8b7fEric Laurent AudioSystem.initStreamVolume(streamType, 0, (streamState.mIndexMax + 5) / 10); 42879bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent 42889bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent streamState.applyAllVolumes(); 42899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4290c42ac9d4d03f62c3a1ba197a28a81fda44bd8b7fEric Laurent 4291c42ac9d4d03f62c3a1ba197a28a81fda44bd8b7fEric Laurent // Restore ringer mode 4292661f2cf45860d2e10924e6b69966a9afe255f28bJohn Spurlock setRingerModeInt(getRingerModeInternal(), false); 42933c652ca5a546e7227a5f4bdbf0f81552b2c91383Eric Laurent 42949063154a793b0ab38b3c5992cbaed046427b4a82Mike Lockwood // Restore master volume 42959063154a793b0ab38b3c5992cbaed046427b4a82Mike Lockwood restoreMasterVolume(); 42969063154a793b0ab38b3c5992cbaed046427b4a82Mike Lockwood 4297f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi // Reset device orientation (if monitored for this device) 4298d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent if (mMonitorOrientation) { 4299f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi setOrientationForAudioSystem(); 4300f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi } 4301bb6f8711a7f804d39c45218db2d6339940cc5d35Jean-Michel Trivi if (mMonitorRotation) { 4302bb6f8711a7f804d39c45218db2d6339940cc5d35Jean-Michel Trivi setRotationForAudioSystem(); 4303bb6f8711a7f804d39c45218db2d6339940cc5d35Jean-Michel Trivi } 4304f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi 43057847211fb4699bf6018e29d214a918ed6657319bEric Laurent synchronized (mBluetoothA2dpEnabledLock) { 43067847211fb4699bf6018e29d214a918ed6657319bEric Laurent AudioSystem.setForceUse(AudioSystem.FOR_MEDIA, 43077847211fb4699bf6018e29d214a918ed6657319bEric Laurent mBluetoothA2dpEnabled ? 43087847211fb4699bf6018e29d214a918ed6657319bEric Laurent AudioSystem.FORCE_NONE : AudioSystem.FORCE_NO_BT_A2DP); 43097847211fb4699bf6018e29d214a918ed6657319bEric Laurent } 4310bff5ca576ef55bfdd51a0d2ff39f4bac614fa728Eric Laurent 4311bff5ca576ef55bfdd51a0d2ff39f4bac614fa728Eric Laurent synchronized (mSettingsLock) { 4312bff5ca576ef55bfdd51a0d2ff39f4bac614fa728Eric Laurent AudioSystem.setForceUse(AudioSystem.FOR_DOCK, 4313bff5ca576ef55bfdd51a0d2ff39f4bac614fa728Eric Laurent mDockAudioMediaEnabled ? 4314bff5ca576ef55bfdd51a0d2ff39f4bac614fa728Eric Laurent AudioSystem.FORCE_ANALOG_DOCK : AudioSystem.FORCE_NONE); 4315bff5ca576ef55bfdd51a0d2ff39f4bac614fa728Eric Laurent } 4316212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent if (mHdmiManager != null) { 4317212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent synchronized (mHdmiManager) { 4318212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent if (mHdmiTvClient != null) { 4319212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent setHdmiSystemAudioSupported(mHdmiSystemAudioSupported); 4320212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent } 4321212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent } 43226f34f5ab8ab1b1db7887e5405d8b0031e105ab05Jungshik Jang } 43237f5eb9fe3c10d8d83ff0e2b0fc60a05c2e6d5b02Eric Laurent 43247f5eb9fe3c10d8d83ff0e2b0fc60a05c2e6d5b02Eric Laurent synchronized (mAudioPolicies) { 43257f5eb9fe3c10d8d83ff0e2b0fc60a05c2e6d5b02Eric Laurent for(AudioPolicyProxy policy : mAudioPolicies.values()) { 43267f5eb9fe3c10d8d83ff0e2b0fc60a05c2e6d5b02Eric Laurent policy.connectMixes(); 43277f5eb9fe3c10d8d83ff0e2b0fc60a05c2e6d5b02Eric Laurent } 43287f5eb9fe3c10d8d83ff0e2b0fc60a05c2e6d5b02Eric Laurent } 43297f5eb9fe3c10d8d83ff0e2b0fc60a05c2e6d5b02Eric Laurent 43303c652ca5a546e7227a5f4bdbf0f81552b2c91383Eric Laurent // indicate the end of reconfiguration phase to audio HAL 43313c652ca5a546e7227a5f4bdbf0f81552b2c91383Eric Laurent AudioSystem.setParameters("restarting=false"); 43329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 43339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 43345d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent case MSG_UNLOAD_SOUND_EFFECTS: 43355d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent onUnloadSoundEffects(); 43365d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent break; 43375d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent 4338117b7bb5b5a4457711f59bde3dcc83d8f111c524Eric Laurent case MSG_LOAD_SOUND_EFFECTS: 43395d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent //FIXME: onLoadSoundEffects() should be executed in a separate thread as it 43405d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent // can take several dozens of milliseconds to complete 43415d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent boolean loaded = onLoadSoundEffects(); 43425d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent if (msg.obj != null) { 43435d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent LoadSoundEffectReply reply = (LoadSoundEffectReply)msg.obj; 43445d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent synchronized (reply) { 43455d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent reply.mStatus = loaded ? 0 : -1; 43465d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent reply.notify(); 43475d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent } 43485d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent } 4349117b7bb5b5a4457711f59bde3dcc83d8f111c524Eric Laurent break; 4350117b7bb5b5a4457711f59bde3dcc83d8f111c524Eric Laurent 43519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case MSG_PLAY_SOUND_EFFECT: 43525d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent onPlaySoundEffect(msg.arg1, msg.arg2); 43539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 43544c637b9e34f4c8db69a64ad21a4e2bcfa7485b5fJean-Michel Trivi 43554c637b9e34f4c8db69a64ad21a4e2bcfa7485b5fJean-Michel Trivi case MSG_BTA2DP_DOCK_TIMEOUT: 43564c637b9e34f4c8db69a64ad21a4e2bcfa7485b5fJean-Michel Trivi // msg.obj == address of BTA2DP device 43576bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent synchronized (mConnectedDevices) { 43586bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent makeA2dpDeviceUnavailableNow( (String) msg.obj ); 43596bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent } 43604c637b9e34f4c8db69a64ad21a4e2bcfa7485b5fJean-Michel Trivi break; 4361fa640154f1f42121d81242b2f1a10f03e52f0014Eric Laurent 4362fa640154f1f42121d81242b2f1a10f03e52f0014Eric Laurent case MSG_SET_FORCE_USE: 4363c390bed06b4a572e273ead1254da9a932e04dce3Eric Laurent case MSG_SET_FORCE_BT_A2DP_USE: 4364fa640154f1f42121d81242b2f1a10f03e52f0014Eric Laurent setForceUse(msg.arg1, msg.arg2); 4365fa640154f1f42121d81242b2f1a10f03e52f0014Eric Laurent break; 4366d589fea865e90859324f00d21765fa7d7759e465Jean-Michel Trivi 4367dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent case MSG_BT_HEADSET_CNCT_FAILED: 4368dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent resetBluetoothSco(); 4369dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent break; 4370b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent 4371b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent case MSG_SET_WIRED_DEVICE_CONNECTION_STATE: 4372b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent onSetWiredDeviceConnectionState(msg.arg1, msg.arg2, (String)msg.obj); 4373fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi mAudioEventWakeLock.release(); 4374b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent break; 4375b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent 43760a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood case MSG_SET_A2DP_SRC_CONNECTION_STATE: 43770a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood onSetA2dpSourceConnectionState((BluetoothDevice)msg.obj, msg.arg1); 43780a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood mAudioEventWakeLock.release(); 43790a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood break; 43800a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood 43810a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood case MSG_SET_A2DP_SINK_CONNECTION_STATE: 43820a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood onSetA2dpSinkConnectionState((BluetoothDevice)msg.obj, msg.arg1); 4383fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi mAudioEventWakeLock.release(); 4384b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent break; 4385632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn 4386632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn case MSG_REPORT_NEW_ROUTES: { 4387632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn int N = mRoutesObservers.beginBroadcast(); 4388632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn if (N > 0) { 4389632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn AudioRoutesInfo routes; 4390632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn synchronized (mCurAudioRoutes) { 4391632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn routes = new AudioRoutesInfo(mCurAudioRoutes); 4392632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn } 4393632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn while (N > 0) { 4394632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn N--; 4395632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn IAudioRoutesObserver obs = mRoutesObservers.getBroadcastItem(N); 4396632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn try { 4397632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn obs.dispatchAudioRoutesChanged(routes); 4398632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn } catch (RemoteException e) { 4399632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn } 4400632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn } 4401632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn } 4402632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn mRoutesObservers.finishBroadcast(); 4403632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn break; 4404632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn } 44053114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi 4406c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent case MSG_CHECK_MUSIC_ACTIVE: 4407c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent onCheckMusicActive(); 4408c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent break; 44095bfaeaef3fc348d66f48b86be08655e91dff910aEric Laurent 44105bfaeaef3fc348d66f48b86be08655e91dff910aEric Laurent case MSG_BROADCAST_AUDIO_BECOMING_NOISY: 44115bfaeaef3fc348d66f48b86be08655e91dff910aEric Laurent onSendBecomingNoisyIntent(); 44125bfaeaef3fc348d66f48b86be08655e91dff910aEric Laurent break; 4413d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent 4414d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent case MSG_CONFIGURE_SAFE_MEDIA_VOLUME_FORCED: 4415d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent case MSG_CONFIGURE_SAFE_MEDIA_VOLUME: 4416d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent onConfigureSafeVolume((msg.what == MSG_CONFIGURE_SAFE_MEDIA_VOLUME_FORCED)); 4417d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent break; 441805274f348e12983eb8613cc6eb9ae561e8197e28Eric Laurent case MSG_PERSIST_SAFE_VOLUME_STATE: 441905274f348e12983eb8613cc6eb9ae561e8197e28Eric Laurent onPersistSafeVolumeState(msg.arg1); 442005274f348e12983eb8613cc6eb9ae561e8197e28Eric Laurent break; 4421a578c48e6c8677bcb54340aadb9470f8a275e56cJean-Michel Trivi 44222a57ca931fefe817b6110101289721acaacfc808Eric Laurent case MSG_BROADCAST_BT_CONNECTION_STATE: 44232a57ca931fefe817b6110101289721acaacfc808Eric Laurent onBroadcastScoConnectionState(msg.arg1); 44242a57ca931fefe817b6110101289721acaacfc808Eric Laurent break; 44254a5eeb9c727d77bb57fef87a70c8c9cc23dbfee3Eric Laurent 44264a5eeb9c727d77bb57fef87a70c8c9cc23dbfee3Eric Laurent case MSG_SYSTEM_READY: 44274a5eeb9c727d77bb57fef87a70c8c9cc23dbfee3Eric Laurent onSystemReady(); 44284a5eeb9c727d77bb57fef87a70c8c9cc23dbfee3Eric Laurent break; 4429aa5ee4d65f8788e2a0afcd198367450853fd72acJohn Spurlock 4430aa5ee4d65f8788e2a0afcd198367450853fd72acJohn Spurlock case MSG_PERSIST_MUSIC_ACTIVE_MS: 4431aa5ee4d65f8788e2a0afcd198367450853fd72acJohn Spurlock final int musicActiveMs = msg.arg1; 4432aa5ee4d65f8788e2a0afcd198367450853fd72acJohn Spurlock Settings.Secure.putIntForUser(mContentResolver, 4433aa5ee4d65f8788e2a0afcd198367450853fd72acJohn Spurlock Settings.Secure.UNSAFE_VOLUME_MUSIC_ACTIVE_MS, musicActiveMs, 4434aa5ee4d65f8788e2a0afcd198367450853fd72acJohn Spurlock UserHandle.USER_CURRENT); 4435aa5ee4d65f8788e2a0afcd198367450853fd72acJohn Spurlock break; 4436b53453fae037d67e421011936c8fdffe7ba43922Julia Reynolds case MSG_PERSIST_MICROPHONE_MUTE: 4437b53453fae037d67e421011936c8fdffe7ba43922Julia Reynolds Settings.System.putIntForUser(mContentResolver, 4438b53453fae037d67e421011936c8fdffe7ba43922Julia Reynolds Settings.System.MICROPHONE_MUTE, 4439b53453fae037d67e421011936c8fdffe7ba43922Julia Reynolds msg.arg1, 4440b53453fae037d67e421011936c8fdffe7ba43922Julia Reynolds msg.arg2); 4441b53453fae037d67e421011936c8fdffe7ba43922Julia Reynolds break; 44429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 44439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 44449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 44459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4446b109615ebebd6f3b9ae789412279f576c3ace46bJason Parekh private class SettingsObserver extends ContentObserver { 4447a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent 4448b109615ebebd6f3b9ae789412279f576c3ace46bJason Parekh SettingsObserver() { 4449b109615ebebd6f3b9ae789412279f576c3ace46bJason Parekh super(new Handler()); 4450b109615ebebd6f3b9ae789412279f576c3ace46bJason Parekh mContentResolver.registerContentObserver(Settings.System.getUriFor( 4451b109615ebebd6f3b9ae789412279f576c3ace46bJason Parekh Settings.System.MODE_RINGER_STREAMS_AFFECTED), false, this); 44527ee1e4ff7346a278a6722108fbc1869240b3e866Eric Laurent mContentResolver.registerContentObserver(Settings.Global.getUriFor( 44537ee1e4ff7346a278a6722108fbc1869240b3e866Eric Laurent Settings.Global.DOCK_AUDIO_MEDIA_ENABLED), false, this); 4454b109615ebebd6f3b9ae789412279f576c3ace46bJason Parekh } 4455b109615ebebd6f3b9ae789412279f576c3ace46bJason Parekh 4456b109615ebebd6f3b9ae789412279f576c3ace46bJason Parekh @Override 4457b109615ebebd6f3b9ae789412279f576c3ace46bJason Parekh public void onChange(boolean selfChange) { 4458b109615ebebd6f3b9ae789412279f576c3ace46bJason Parekh super.onChange(selfChange); 4459ba195ebc76f23b6679443724ab58c9dc9f2df884Glenn Kasten // FIXME This synchronized is not necessary if mSettingsLock only protects mRingerMode. 4460ba195ebc76f23b6679443724ab58c9dc9f2df884Glenn Kasten // However there appear to be some missing locks around mRingerModeMutedStreams 4461ba195ebc76f23b6679443724ab58c9dc9f2df884Glenn Kasten // and mRingerModeAffectedStreams, so will leave this synchronized for now. 4462ba195ebc76f23b6679443724ab58c9dc9f2df884Glenn Kasten // mRingerModeMutedStreams and mMuteAffectedStreams are safe (only accessed once). 4463a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent synchronized (mSettingsLock) { 446424e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent if (updateRingerModeAffectedStreams()) { 4465a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent /* 4466a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent * Ensure all stream types that should be affected by ringer mode 4467a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent * are in the proper state. 4468a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent */ 4469661f2cf45860d2e10924e6b69966a9afe255f28bJohn Spurlock setRingerModeInt(getRingerModeInternal(), false); 4470a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent } 44717ee1e4ff7346a278a6722108fbc1869240b3e866Eric Laurent readDockAudioSettings(mContentResolver); 4472a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent } 4473b109615ebebd6f3b9ae789412279f576c3ace46bJason Parekh } 4474b109615ebebd6f3b9ae789412279f576c3ace46bJason Parekh } 4475a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent 44766bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent // must be called synchronized on mConnectedDevices 44774c637b9e34f4c8db69a64ad21a4e2bcfa7485b5fJean-Michel Trivi private void makeA2dpDeviceAvailable(String address) { 44787847211fb4699bf6018e29d214a918ed6657319bEric Laurent // enable A2DP before notifying A2DP connection to avoid unecessary processing in 44797847211fb4699bf6018e29d214a918ed6657319bEric Laurent // audio policy manager 4480c9d1d5f35091226e96fcfa91817480f589eb36e2Matthew Xie VolumeStreamState streamState = mStreamStates[AudioSystem.STREAM_MUSIC]; 4481c9d1d5f35091226e96fcfa91817480f589eb36e2Matthew Xie sendMsg(mAudioHandler, MSG_SET_DEVICE_VOLUME, SENDMSG_QUEUE, 4482c9d1d5f35091226e96fcfa91817480f589eb36e2Matthew Xie AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, 0, streamState, 0); 44837847211fb4699bf6018e29d214a918ed6657319bEric Laurent setBluetoothA2dpOnInt(true); 44844c637b9e34f4c8db69a64ad21a4e2bcfa7485b5fJean-Michel Trivi AudioSystem.setDeviceConnectionState(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, 44854c637b9e34f4c8db69a64ad21a4e2bcfa7485b5fJean-Michel Trivi AudioSystem.DEVICE_STATE_AVAILABLE, 44864c637b9e34f4c8db69a64ad21a4e2bcfa7485b5fJean-Michel Trivi address); 44874c637b9e34f4c8db69a64ad21a4e2bcfa7485b5fJean-Michel Trivi // Reset A2DP suspend state each time a new sink is connected 44884c637b9e34f4c8db69a64ad21a4e2bcfa7485b5fJean-Michel Trivi AudioSystem.setParameters("A2dpSuspended=false"); 44894c637b9e34f4c8db69a64ad21a4e2bcfa7485b5fJean-Michel Trivi mConnectedDevices.put( new Integer(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP), 44904c637b9e34f4c8db69a64ad21a4e2bcfa7485b5fJean-Michel Trivi address); 44914c637b9e34f4c8db69a64ad21a4e2bcfa7485b5fJean-Michel Trivi } 44924c637b9e34f4c8db69a64ad21a4e2bcfa7485b5fJean-Michel Trivi 44935bfaeaef3fc348d66f48b86be08655e91dff910aEric Laurent private void onSendBecomingNoisyIntent() { 44945ac72a29593ab9a20337a2225df52bdf4754be02Dianne Hackborn sendBroadcastToAll(new Intent(AudioManager.ACTION_AUDIO_BECOMING_NOISY)); 44959841818b9a0280abf59343c9e00a2976dbc084faMike Lockwood } 44969841818b9a0280abf59343c9e00a2976dbc084faMike Lockwood 44976bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent // must be called synchronized on mConnectedDevices 44984c637b9e34f4c8db69a64ad21a4e2bcfa7485b5fJean-Michel Trivi private void makeA2dpDeviceUnavailableNow(String address) { 4499c9d1d5f35091226e96fcfa91817480f589eb36e2Matthew Xie synchronized (mA2dpAvrcpLock) { 4500c9d1d5f35091226e96fcfa91817480f589eb36e2Matthew Xie mAvrcpAbsVolSupported = false; 4501c9d1d5f35091226e96fcfa91817480f589eb36e2Matthew Xie } 45024c637b9e34f4c8db69a64ad21a4e2bcfa7485b5fJean-Michel Trivi AudioSystem.setDeviceConnectionState(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, 45034c637b9e34f4c8db69a64ad21a4e2bcfa7485b5fJean-Michel Trivi AudioSystem.DEVICE_STATE_UNAVAILABLE, 45044c637b9e34f4c8db69a64ad21a4e2bcfa7485b5fJean-Michel Trivi address); 45054c637b9e34f4c8db69a64ad21a4e2bcfa7485b5fJean-Michel Trivi mConnectedDevices.remove(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP); 45065535ea8ef876be25121a6336ffab5a0bf8dbd031RoboErik synchronized (mCurAudioRoutes) { 45075535ea8ef876be25121a6336ffab5a0bf8dbd031RoboErik // Remove A2DP routes as well 45085535ea8ef876be25121a6336ffab5a0bf8dbd031RoboErik if (mCurAudioRoutes.mBluetoothName != null) { 45095535ea8ef876be25121a6336ffab5a0bf8dbd031RoboErik mCurAudioRoutes.mBluetoothName = null; 45105535ea8ef876be25121a6336ffab5a0bf8dbd031RoboErik sendMsg(mAudioHandler, MSG_REPORT_NEW_ROUTES, 45115535ea8ef876be25121a6336ffab5a0bf8dbd031RoboErik SENDMSG_NOOP, 0, 0, null, 0); 45125535ea8ef876be25121a6336ffab5a0bf8dbd031RoboErik } 45135535ea8ef876be25121a6336ffab5a0bf8dbd031RoboErik } 45144c637b9e34f4c8db69a64ad21a4e2bcfa7485b5fJean-Michel Trivi } 45154c637b9e34f4c8db69a64ad21a4e2bcfa7485b5fJean-Michel Trivi 45166bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent // must be called synchronized on mConnectedDevices 45174c637b9e34f4c8db69a64ad21a4e2bcfa7485b5fJean-Michel Trivi private void makeA2dpDeviceUnavailableLater(String address) { 45183b5912602bec6ccbe8eef8a576730b1565f0067cEric Laurent // prevent any activity on the A2DP audio output to avoid unwanted 45193b5912602bec6ccbe8eef8a576730b1565f0067cEric Laurent // reconnection of the sink. 45203b5912602bec6ccbe8eef8a576730b1565f0067cEric Laurent AudioSystem.setParameters("A2dpSuspended=true"); 45214c637b9e34f4c8db69a64ad21a4e2bcfa7485b5fJean-Michel Trivi // the device will be made unavailable later, so consider it disconnected right away 45224c637b9e34f4c8db69a64ad21a4e2bcfa7485b5fJean-Michel Trivi mConnectedDevices.remove(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP); 45234c637b9e34f4c8db69a64ad21a4e2bcfa7485b5fJean-Michel Trivi // send the delayed message to make the device unavailable later 45244c637b9e34f4c8db69a64ad21a4e2bcfa7485b5fJean-Michel Trivi Message msg = mAudioHandler.obtainMessage(MSG_BTA2DP_DOCK_TIMEOUT, address); 45254c637b9e34f4c8db69a64ad21a4e2bcfa7485b5fJean-Michel Trivi mAudioHandler.sendMessageDelayed(msg, BTA2DP_DOCK_TIMEOUT_MILLIS); 45264c637b9e34f4c8db69a64ad21a4e2bcfa7485b5fJean-Michel Trivi 45274c637b9e34f4c8db69a64ad21a4e2bcfa7485b5fJean-Michel Trivi } 45284c637b9e34f4c8db69a64ad21a4e2bcfa7485b5fJean-Michel Trivi 45296bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent // must be called synchronized on mConnectedDevices 45300a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood private void makeA2dpSrcAvailable(String address) { 45310a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood AudioSystem.setDeviceConnectionState(AudioSystem.DEVICE_IN_BLUETOOTH_A2DP, 45320a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood AudioSystem.DEVICE_STATE_AVAILABLE, 45330a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood address); 45340a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood mConnectedDevices.put( new Integer(AudioSystem.DEVICE_IN_BLUETOOTH_A2DP), 45350a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood address); 45360a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood } 45370a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood 45380a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood // must be called synchronized on mConnectedDevices 45390a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood private void makeA2dpSrcUnavailable(String address) { 45400a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood AudioSystem.setDeviceConnectionState(AudioSystem.DEVICE_IN_BLUETOOTH_A2DP, 45410a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood AudioSystem.DEVICE_STATE_UNAVAILABLE, 45420a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood address); 45430a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood mConnectedDevices.remove(AudioSystem.DEVICE_IN_BLUETOOTH_A2DP); 45440a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood } 45450a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood 45460a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood // must be called synchronized on mConnectedDevices 4547a847ba4080675d395de725cfac5dfd9d5a993d4eJean-Michel Trivi private void cancelA2dpDeviceTimeout() { 45484c637b9e34f4c8db69a64ad21a4e2bcfa7485b5fJean-Michel Trivi mAudioHandler.removeMessages(MSG_BTA2DP_DOCK_TIMEOUT); 45494c637b9e34f4c8db69a64ad21a4e2bcfa7485b5fJean-Michel Trivi } 45504c637b9e34f4c8db69a64ad21a4e2bcfa7485b5fJean-Michel Trivi 45516bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent // must be called synchronized on mConnectedDevices 4552a847ba4080675d395de725cfac5dfd9d5a993d4eJean-Michel Trivi private boolean hasScheduledA2dpDockTimeout() { 4553a847ba4080675d395de725cfac5dfd9d5a993d4eJean-Michel Trivi return mAudioHandler.hasMessages(MSG_BTA2DP_DOCK_TIMEOUT); 4554a847ba4080675d395de725cfac5dfd9d5a993d4eJean-Michel Trivi } 4555a847ba4080675d395de725cfac5dfd9d5a993d4eJean-Michel Trivi 45560a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood private void onSetA2dpSinkConnectionState(BluetoothDevice btDevice, int state) 45576bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent { 45580a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood if (DEBUG_VOL) { 45590a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood Log.d(TAG, "onSetA2dpSinkConnectionState btDevice="+btDevice+"state="+state); 45600a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood } 45616bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent if (btDevice == null) { 45626bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent return; 45636bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent } 45646bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent String address = btDevice.getAddress(); 45656bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent if (!BluetoothAdapter.checkBluetoothAddress(address)) { 45666bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent address = ""; 45676bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent } 45685a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du 45696bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent synchronized (mConnectedDevices) { 45706bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent boolean isConnected = 45716bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent (mConnectedDevices.containsKey(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP) && 45726bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent mConnectedDevices.get(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP).equals(address)); 45736bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent 45746bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent if (isConnected && state != BluetoothProfile.STATE_CONNECTED) { 45756bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent if (btDevice.isBluetoothDock()) { 45766bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent if (state == BluetoothProfile.STATE_DISCONNECTED) { 45776bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent // introduction of a delay for transient disconnections of docks when 45786bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent // power is rapidly turned off/on, this message will be canceled if 45796bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent // we reconnect the dock under a preset delay 45806bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent makeA2dpDeviceUnavailableLater(address); 45816bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent // the next time isConnected is evaluated, it will be false for the dock 45826bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent } 45836bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent } else { 45846bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent makeA2dpDeviceUnavailableNow(address); 45856bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent } 4586632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn synchronized (mCurAudioRoutes) { 4587632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn if (mCurAudioRoutes.mBluetoothName != null) { 4588632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn mCurAudioRoutes.mBluetoothName = null; 4589632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn sendMsg(mAudioHandler, MSG_REPORT_NEW_ROUTES, 4590632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn SENDMSG_NOOP, 0, 0, null, 0); 4591632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn } 4592632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn } 45936bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent } else if (!isConnected && state == BluetoothProfile.STATE_CONNECTED) { 45946bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent if (btDevice.isBluetoothDock()) { 45956bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent // this could be a reconnection after a transient disconnection 45966bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent cancelA2dpDeviceTimeout(); 45976bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent mDockAddress = address; 45986bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent } else { 45996bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent // this could be a connection of another A2DP device before the timeout of 46006bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent // a dock: cancel the dock timeout, and make the dock unavailable now 46016bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent if(hasScheduledA2dpDockTimeout()) { 46026bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent cancelA2dpDeviceTimeout(); 46036bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent makeA2dpDeviceUnavailableNow(mDockAddress); 46046bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent } 46056bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent } 46066bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent makeA2dpDeviceAvailable(address); 4607632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn synchronized (mCurAudioRoutes) { 4608632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn String name = btDevice.getAliasName(); 4609632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn if (!TextUtils.equals(mCurAudioRoutes.mBluetoothName, name)) { 4610632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn mCurAudioRoutes.mBluetoothName = name; 4611632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn sendMsg(mAudioHandler, MSG_REPORT_NEW_ROUTES, 4612632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn SENDMSG_NOOP, 0, 0, null, 0); 4613632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn } 4614632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn } 46156bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent } 46166bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent } 46176bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent } 46186bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent 46190a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood private void onSetA2dpSourceConnectionState(BluetoothDevice btDevice, int state) 46200a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood { 46210a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood if (DEBUG_VOL) { 46220a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood Log.d(TAG, "onSetA2dpSourceConnectionState btDevice="+btDevice+" state="+state); 46230a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood } 46240a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood if (btDevice == null) { 46250a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood return; 46260a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood } 46270a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood String address = btDevice.getAddress(); 46280a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood if (!BluetoothAdapter.checkBluetoothAddress(address)) { 46290a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood address = ""; 46300a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood } 46310a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood 46320a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood synchronized (mConnectedDevices) { 46330a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood boolean isConnected = 46340a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood (mConnectedDevices.containsKey(AudioSystem.DEVICE_IN_BLUETOOTH_A2DP) && 46350a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood mConnectedDevices.get(AudioSystem.DEVICE_IN_BLUETOOTH_A2DP).equals(address)); 46360a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood 46370a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood if (isConnected && state != BluetoothProfile.STATE_CONNECTED) { 46380a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood makeA2dpSrcUnavailable(address); 46390a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood } else if (!isConnected && state == BluetoothProfile.STATE_CONNECTED) { 46400a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood makeA2dpSrcAvailable(address); 46410a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood } 46420a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood } 46430a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood } 46440a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood 46455a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du public void avrcpSupportsAbsoluteVolume(String address, boolean support) { 46465a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du // address is not used for now, but may be used when multiple a2dp devices are supported 46475a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du synchronized (mA2dpAvrcpLock) { 46485a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du mAvrcpAbsVolSupported = support; 4649c9d1d5f35091226e96fcfa91817480f589eb36e2Matthew Xie sendMsg(mAudioHandler, MSG_SET_DEVICE_VOLUME, SENDMSG_QUEUE, 4650cd772d04345850e160a45613fcf6b86da0dce4cfEric Laurent AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, 0, 4651cd772d04345850e160a45613fcf6b86da0dce4cfEric Laurent mStreamStates[AudioSystem.STREAM_MUSIC], 0); 4652cd772d04345850e160a45613fcf6b86da0dce4cfEric Laurent sendMsg(mAudioHandler, MSG_SET_DEVICE_VOLUME, SENDMSG_QUEUE, 4653cd772d04345850e160a45613fcf6b86da0dce4cfEric Laurent AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, 0, 4654cd772d04345850e160a45613fcf6b86da0dce4cfEric Laurent mStreamStates[AudioSystem.STREAM_RING], 0); 46555a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du } 46565a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du } 46575a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du 465859f482764e346a5c5ac118ee1f7b24da645c2559Eric Laurent private boolean handleDeviceConnection(boolean connected, int device, String params) { 465959f482764e346a5c5ac118ee1f7b24da645c2559Eric Laurent synchronized (mConnectedDevices) { 466059f482764e346a5c5ac118ee1f7b24da645c2559Eric Laurent boolean isConnected = (mConnectedDevices.containsKey(device) && 46619841818b9a0280abf59343c9e00a2976dbc084faMike Lockwood (params.isEmpty() || mConnectedDevices.get(device).equals(params))); 466259f482764e346a5c5ac118ee1f7b24da645c2559Eric Laurent 466359f482764e346a5c5ac118ee1f7b24da645c2559Eric Laurent if (isConnected && !connected) { 466459f482764e346a5c5ac118ee1f7b24da645c2559Eric Laurent AudioSystem.setDeviceConnectionState(device, 466559f482764e346a5c5ac118ee1f7b24da645c2559Eric Laurent AudioSystem.DEVICE_STATE_UNAVAILABLE, 46669841818b9a0280abf59343c9e00a2976dbc084faMike Lockwood mConnectedDevices.get(device)); 466759f482764e346a5c5ac118ee1f7b24da645c2559Eric Laurent mConnectedDevices.remove(device); 466859f482764e346a5c5ac118ee1f7b24da645c2559Eric Laurent return true; 466959f482764e346a5c5ac118ee1f7b24da645c2559Eric Laurent } else if (!isConnected && connected) { 467059f482764e346a5c5ac118ee1f7b24da645c2559Eric Laurent AudioSystem.setDeviceConnectionState(device, 467159f482764e346a5c5ac118ee1f7b24da645c2559Eric Laurent AudioSystem.DEVICE_STATE_AVAILABLE, 467259f482764e346a5c5ac118ee1f7b24da645c2559Eric Laurent params); 467359f482764e346a5c5ac118ee1f7b24da645c2559Eric Laurent mConnectedDevices.put(new Integer(device), params); 467459f482764e346a5c5ac118ee1f7b24da645c2559Eric Laurent return true; 467559f482764e346a5c5ac118ee1f7b24da645c2559Eric Laurent } 467659f482764e346a5c5ac118ee1f7b24da645c2559Eric Laurent } 467759f482764e346a5c5ac118ee1f7b24da645c2559Eric Laurent return false; 467859f482764e346a5c5ac118ee1f7b24da645c2559Eric Laurent } 467959f482764e346a5c5ac118ee1f7b24da645c2559Eric Laurent 4680b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent // Devices which removal triggers intent ACTION_AUDIO_BECOMING_NOISY. The intent is only 4681b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent // sent if none of these devices is connected. 4682b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent int mBecomingNoisyIntentDevices = 4683b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent AudioSystem.DEVICE_OUT_WIRED_HEADSET | AudioSystem.DEVICE_OUT_WIRED_HEADPHONE | 4684948d32748caaac5be06c991ebf00f74265a7849fEric Laurent AudioSystem.DEVICE_OUT_ALL_A2DP | AudioSystem.DEVICE_OUT_HDMI | 4685794da7a0543cbecffefb73794aa68d1a93e41adfEric Laurent AudioSystem.DEVICE_OUT_ANLG_DOCK_HEADSET | AudioSystem.DEVICE_OUT_DGTL_DOCK_HEADSET | 468643cc8bbbbd5e6418cdfa0fa4b26c9f5c3a28c029Jon Eklund AudioSystem.DEVICE_OUT_ALL_USB | AudioSystem.DEVICE_OUT_LINE; 4687b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent 4688b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent // must be called before removing the device from mConnectedDevices 4689b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent private int checkSendBecomingNoisyIntent(int device, int state) { 4690b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent int delay = 0; 4691b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent if ((state == 0) && ((device & mBecomingNoisyIntentDevices) != 0)) { 4692b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent int devices = 0; 4693b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent for (int dev : mConnectedDevices.keySet()) { 469427c30e4426302581a266c89d0ef880b340d7b061Eric Laurent if (((dev & AudioSystem.DEVICE_BIT_IN) == 0) && 469527c30e4426302581a266c89d0ef880b340d7b061Eric Laurent ((dev & mBecomingNoisyIntentDevices) != 0)) { 4696b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent devices |= dev; 4697b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent } 4698b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent } 4699b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent if (devices == device) { 47005bfaeaef3fc348d66f48b86be08655e91dff910aEric Laurent sendMsg(mAudioHandler, 47015bfaeaef3fc348d66f48b86be08655e91dff910aEric Laurent MSG_BROADCAST_AUDIO_BECOMING_NOISY, 47025bfaeaef3fc348d66f48b86be08655e91dff910aEric Laurent SENDMSG_REPLACE, 47035bfaeaef3fc348d66f48b86be08655e91dff910aEric Laurent 0, 47045bfaeaef3fc348d66f48b86be08655e91dff910aEric Laurent 0, 47055bfaeaef3fc348d66f48b86be08655e91dff910aEric Laurent null, 47065bfaeaef3fc348d66f48b86be08655e91dff910aEric Laurent 0); 4707b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent delay = 1000; 4708b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent } 4709b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent } 4710b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent 47110a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood if (mAudioHandler.hasMessages(MSG_SET_A2DP_SRC_CONNECTION_STATE) || 47120a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood mAudioHandler.hasMessages(MSG_SET_A2DP_SINK_CONNECTION_STATE) || 4713b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent mAudioHandler.hasMessages(MSG_SET_WIRED_DEVICE_CONNECTION_STATE)) { 4714adbe8bf85f3c8230d16ae5cb3f5d9736e09ed84aEric Laurent synchronized (mLastDeviceConnectMsgTime) { 4715adbe8bf85f3c8230d16ae5cb3f5d9736e09ed84aEric Laurent long time = SystemClock.uptimeMillis(); 4716adbe8bf85f3c8230d16ae5cb3f5d9736e09ed84aEric Laurent if (mLastDeviceConnectMsgTime > time) { 4717c525cf7a33430f44246f63d1c68c4cda4b92254eMatthew Xie delay = (int)(mLastDeviceConnectMsgTime - time) + 30; 4718adbe8bf85f3c8230d16ae5cb3f5d9736e09ed84aEric Laurent } 4719adbe8bf85f3c8230d16ae5cb3f5d9736e09ed84aEric Laurent } 4720b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent } 4721b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent return delay; 4722b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent } 4723b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent 4724b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent private void sendDeviceConnectionIntent(int device, int state, String name) 4725b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent { 4726b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent Intent intent = new Intent(); 4727b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent 4728b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent intent.putExtra("state", state); 4729b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent intent.putExtra("name", name); 4730b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY); 4731b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent 4732632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn int connType = 0; 4733632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn 4734b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent if (device == AudioSystem.DEVICE_OUT_WIRED_HEADSET) { 4735632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn connType = AudioRoutesInfo.MAIN_HEADSET; 4736b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent intent.setAction(Intent.ACTION_HEADSET_PLUG); 4737b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent intent.putExtra("microphone", 1); 473843cc8bbbbd5e6418cdfa0fa4b26c9f5c3a28c029Jon Eklund } else if (device == AudioSystem.DEVICE_OUT_WIRED_HEADPHONE || 473943cc8bbbbd5e6418cdfa0fa4b26c9f5c3a28c029Jon Eklund device == AudioSystem.DEVICE_OUT_LINE) { 474043cc8bbbbd5e6418cdfa0fa4b26c9f5c3a28c029Jon Eklund /*do apps care about line-out vs headphones?*/ 4741632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn connType = AudioRoutesInfo.MAIN_HEADPHONES; 4742b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent intent.setAction(Intent.ACTION_HEADSET_PLUG); 4743b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent intent.putExtra("microphone", 0); 4744b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent } else if (device == AudioSystem.DEVICE_OUT_ANLG_DOCK_HEADSET) { 4745632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn connType = AudioRoutesInfo.MAIN_DOCK_SPEAKERS; 4746c5258433dd353769ccfa2e5e769a7379378a3a0bJean-Michel Trivi intent.setAction(AudioManager.ACTION_ANALOG_AUDIO_DOCK_PLUG); 4747b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent } else if (device == AudioSystem.DEVICE_OUT_DGTL_DOCK_HEADSET) { 4748632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn connType = AudioRoutesInfo.MAIN_DOCK_SPEAKERS; 4749c5258433dd353769ccfa2e5e769a7379378a3a0bJean-Michel Trivi intent.setAction(AudioManager.ACTION_DIGITAL_AUDIO_DOCK_PLUG); 47506fa4245589c93025d91aab7dc6681babdd91ee41Eric Laurent } else if (device == AudioSystem.DEVICE_OUT_HDMI || 47516fa4245589c93025d91aab7dc6681babdd91ee41Eric Laurent device == AudioSystem.DEVICE_OUT_HDMI_ARC) { 4752632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn connType = AudioRoutesInfo.MAIN_HDMI; 475337d7804627eecaf04e170793c2f5703d5d6d44e8Jean-Michel Trivi configureHdmiPlugIntent(intent, state); 4754b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent } 4755b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent 4756632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn synchronized (mCurAudioRoutes) { 4757632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn if (connType != 0) { 4758632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn int newConn = mCurAudioRoutes.mMainType; 4759632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn if (state != 0) { 4760632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn newConn |= connType; 4761632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn } else { 4762632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn newConn &= ~connType; 4763632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn } 4764632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn if (newConn != mCurAudioRoutes.mMainType) { 4765632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn mCurAudioRoutes.mMainType = newConn; 4766632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn sendMsg(mAudioHandler, MSG_REPORT_NEW_ROUTES, 4767632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn SENDMSG_NOOP, 0, 0, null, 0); 4768632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn } 4769632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn } 4770632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn } 4771632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn 47725ac72a29593ab9a20337a2225df52bdf4754be02Dianne Hackborn final long ident = Binder.clearCallingIdentity(); 47735ac72a29593ab9a20337a2225df52bdf4754be02Dianne Hackborn try { 47745ac72a29593ab9a20337a2225df52bdf4754be02Dianne Hackborn ActivityManagerNative.broadcastStickyIntent(intent, null, UserHandle.USER_ALL); 47755ac72a29593ab9a20337a2225df52bdf4754be02Dianne Hackborn } finally { 47765ac72a29593ab9a20337a2225df52bdf4754be02Dianne Hackborn Binder.restoreCallingIdentity(ident); 47775ac72a29593ab9a20337a2225df52bdf4754be02Dianne Hackborn } 4778b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent } 4779b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent 4780b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent private void onSetWiredDeviceConnectionState(int device, int state, String name) 4781b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent { 4782b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent synchronized (mConnectedDevices) { 4783b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent if ((state == 0) && ((device == AudioSystem.DEVICE_OUT_WIRED_HEADSET) || 478443cc8bbbbd5e6418cdfa0fa4b26c9f5c3a28c029Jon Eklund (device == AudioSystem.DEVICE_OUT_WIRED_HEADPHONE) || 478543cc8bbbbd5e6418cdfa0fa4b26c9f5c3a28c029Jon Eklund (device == AudioSystem.DEVICE_OUT_LINE))) { 4786b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent setBluetoothA2dpOnInt(true); 4787b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent } 4788ae4506e9b5fc3e0c6d9862fbc05b9af7d6742a6eEric Laurent boolean isUsb = ((device & ~AudioSystem.DEVICE_OUT_ALL_USB) == 0) || 4789ae4506e9b5fc3e0c6d9862fbc05b9af7d6742a6eEric Laurent (((device & AudioSystem.DEVICE_BIT_IN) != 0) && 4790ae4506e9b5fc3e0c6d9862fbc05b9af7d6742a6eEric Laurent ((device & ~AudioSystem.DEVICE_IN_ALL_USB) == 0)); 4791db45484e4b5858d14da93d3a06311b93bf0cf320Mike Lockwood handleDeviceConnection((state == 1), device, (isUsb ? name : "")); 4792f1a457d06c53a901ea08d2d3fb6e766bc06c4d4fEric Laurent if (state != 0) { 4793f1a457d06c53a901ea08d2d3fb6e766bc06c4d4fEric Laurent if ((device == AudioSystem.DEVICE_OUT_WIRED_HEADSET) || 479443cc8bbbbd5e6418cdfa0fa4b26c9f5c3a28c029Jon Eklund (device == AudioSystem.DEVICE_OUT_WIRED_HEADPHONE) || 479543cc8bbbbd5e6418cdfa0fa4b26c9f5c3a28c029Jon Eklund (device == AudioSystem.DEVICE_OUT_LINE)) { 4796f1a457d06c53a901ea08d2d3fb6e766bc06c4d4fEric Laurent setBluetoothA2dpOnInt(false); 4797f1a457d06c53a901ea08d2d3fb6e766bc06c4d4fEric Laurent } 4798f1a457d06c53a901ea08d2d3fb6e766bc06c4d4fEric Laurent if ((device & mSafeMediaVolumeDevices) != 0) { 4799f1a457d06c53a901ea08d2d3fb6e766bc06c4d4fEric Laurent sendMsg(mAudioHandler, 4800f1a457d06c53a901ea08d2d3fb6e766bc06c4d4fEric Laurent MSG_CHECK_MUSIC_ACTIVE, 4801f1a457d06c53a901ea08d2d3fb6e766bc06c4d4fEric Laurent SENDMSG_REPLACE, 4802f1a457d06c53a901ea08d2d3fb6e766bc06c4d4fEric Laurent 0, 4803f1a457d06c53a901ea08d2d3fb6e766bc06c4d4fEric Laurent 0, 4804f1a457d06c53a901ea08d2d3fb6e766bc06c4d4fEric Laurent null, 4805f1a457d06c53a901ea08d2d3fb6e766bc06c4d4fEric Laurent MUSIC_ACTIVE_POLL_PERIOD_MS); 4806f1a457d06c53a901ea08d2d3fb6e766bc06c4d4fEric Laurent } 4807212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent // Television devices without CEC service apply software volume on HDMI output 4808212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent if (isPlatformTelevision() && ((device & AudioSystem.DEVICE_OUT_HDMI) != 0)) { 4809212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent mFixedVolumeDevices |= AudioSystem.DEVICE_OUT_HDMI; 4810212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent checkAllFixedVolumeDevices(); 4811212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent if (mHdmiManager != null) { 4812212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent synchronized (mHdmiManager) { 4813212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent if (mHdmiPlaybackClient != null) { 4814212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent mHdmiCecSink = false; 4815212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent mHdmiPlaybackClient.queryDisplayStatus(mHdmiDisplayStatusCallback); 4816212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent } 4817212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent } 4818212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent } 4819212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent } 4820212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent } else { 4821212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent if (isPlatformTelevision() && ((device & AudioSystem.DEVICE_OUT_HDMI) != 0)) { 4822212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent if (mHdmiManager != null) { 4823212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent synchronized (mHdmiManager) { 4824212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent mHdmiCecSink = false; 4825212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent } 4826212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent } 4827212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent } 4828b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent } 4829ae4506e9b5fc3e0c6d9862fbc05b9af7d6742a6eEric Laurent if (!isUsb && (device != AudioSystem.DEVICE_IN_WIRED_HEADSET)) { 4830db45484e4b5858d14da93d3a06311b93bf0cf320Mike Lockwood sendDeviceConnectionIntent(device, state, name); 4831db45484e4b5858d14da93d3a06311b93bf0cf320Mike Lockwood } 4832b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent } 4833b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent } 4834b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent 483537d7804627eecaf04e170793c2f5703d5d6d44e8Jean-Michel Trivi private void configureHdmiPlugIntent(Intent intent, int state) { 4836c5258433dd353769ccfa2e5e769a7379378a3a0bJean-Michel Trivi intent.setAction(AudioManager.ACTION_HDMI_AUDIO_PLUG); 4837c5258433dd353769ccfa2e5e769a7379378a3a0bJean-Michel Trivi intent.putExtra(AudioManager.EXTRA_AUDIO_PLUG_STATE, state); 483837d7804627eecaf04e170793c2f5703d5d6d44e8Jean-Michel Trivi if (state == 1) { 483937d7804627eecaf04e170793c2f5703d5d6d44e8Jean-Michel Trivi ArrayList<AudioPort> ports = new ArrayList<AudioPort>(); 484037d7804627eecaf04e170793c2f5703d5d6d44e8Jean-Michel Trivi int[] portGeneration = new int[1]; 484137d7804627eecaf04e170793c2f5703d5d6d44e8Jean-Michel Trivi int status = AudioSystem.listAudioPorts(ports, portGeneration); 484237d7804627eecaf04e170793c2f5703d5d6d44e8Jean-Michel Trivi if (status == AudioManager.SUCCESS) { 484337d7804627eecaf04e170793c2f5703d5d6d44e8Jean-Michel Trivi for (AudioPort port : ports) { 484437d7804627eecaf04e170793c2f5703d5d6d44e8Jean-Michel Trivi if (port instanceof AudioDevicePort) { 484537d7804627eecaf04e170793c2f5703d5d6d44e8Jean-Michel Trivi final AudioDevicePort devicePort = (AudioDevicePort) port; 48466fa4245589c93025d91aab7dc6681babdd91ee41Eric Laurent if (devicePort.type() == AudioManager.DEVICE_OUT_HDMI || 48476fa4245589c93025d91aab7dc6681babdd91ee41Eric Laurent devicePort.type() == AudioManager.DEVICE_OUT_HDMI_ARC) { 484837d7804627eecaf04e170793c2f5703d5d6d44e8Jean-Michel Trivi // format the list of supported encodings 484937d7804627eecaf04e170793c2f5703d5d6d44e8Jean-Michel Trivi int[] formats = devicePort.formats(); 485037d7804627eecaf04e170793c2f5703d5d6d44e8Jean-Michel Trivi if (formats.length > 0) { 485137d7804627eecaf04e170793c2f5703d5d6d44e8Jean-Michel Trivi ArrayList<Integer> encodingList = new ArrayList(1); 485237d7804627eecaf04e170793c2f5703d5d6d44e8Jean-Michel Trivi for (int format : formats) { 485337d7804627eecaf04e170793c2f5703d5d6d44e8Jean-Michel Trivi // a format in the list can be 0, skip it 485437d7804627eecaf04e170793c2f5703d5d6d44e8Jean-Michel Trivi if (format != AudioFormat.ENCODING_INVALID) { 485537d7804627eecaf04e170793c2f5703d5d6d44e8Jean-Michel Trivi encodingList.add(format); 485637d7804627eecaf04e170793c2f5703d5d6d44e8Jean-Michel Trivi } 485737d7804627eecaf04e170793c2f5703d5d6d44e8Jean-Michel Trivi } 485837d7804627eecaf04e170793c2f5703d5d6d44e8Jean-Michel Trivi int[] encodingArray = new int[encodingList.size()]; 485937d7804627eecaf04e170793c2f5703d5d6d44e8Jean-Michel Trivi for (int i = 0 ; i < encodingArray.length ; i++) { 486037d7804627eecaf04e170793c2f5703d5d6d44e8Jean-Michel Trivi encodingArray[i] = encodingList.get(i); 486137d7804627eecaf04e170793c2f5703d5d6d44e8Jean-Michel Trivi } 4862c5258433dd353769ccfa2e5e769a7379378a3a0bJean-Michel Trivi intent.putExtra(AudioManager.EXTRA_ENCODINGS, encodingArray); 486337d7804627eecaf04e170793c2f5703d5d6d44e8Jean-Michel Trivi } 486437d7804627eecaf04e170793c2f5703d5d6d44e8Jean-Michel Trivi // find the maximum supported number of channels 486537d7804627eecaf04e170793c2f5703d5d6d44e8Jean-Michel Trivi int maxChannels = 0; 486637d7804627eecaf04e170793c2f5703d5d6d44e8Jean-Michel Trivi for (int mask : devicePort.channelMasks()) { 486737d7804627eecaf04e170793c2f5703d5d6d44e8Jean-Michel Trivi int channelCount = AudioFormat.channelCountFromOutChannelMask(mask); 486837d7804627eecaf04e170793c2f5703d5d6d44e8Jean-Michel Trivi if (channelCount > maxChannels) { 486937d7804627eecaf04e170793c2f5703d5d6d44e8Jean-Michel Trivi maxChannels = channelCount; 487037d7804627eecaf04e170793c2f5703d5d6d44e8Jean-Michel Trivi } 487137d7804627eecaf04e170793c2f5703d5d6d44e8Jean-Michel Trivi } 4872c5258433dd353769ccfa2e5e769a7379378a3a0bJean-Michel Trivi intent.putExtra(AudioManager.EXTRA_MAX_CHANNEL_COUNT, maxChannels); 487337d7804627eecaf04e170793c2f5703d5d6d44e8Jean-Michel Trivi } 487437d7804627eecaf04e170793c2f5703d5d6d44e8Jean-Michel Trivi } 487537d7804627eecaf04e170793c2f5703d5d6d44e8Jean-Michel Trivi } 487637d7804627eecaf04e170793c2f5703d5d6d44e8Jean-Michel Trivi } 487737d7804627eecaf04e170793c2f5703d5d6d44e8Jean-Michel Trivi } 487837d7804627eecaf04e170793c2f5703d5d6d44e8Jean-Michel Trivi } 487937d7804627eecaf04e170793c2f5703d5d6d44e8Jean-Michel Trivi 4880a847ba4080675d395de725cfac5dfd9d5a993d4eJean-Michel Trivi /* cache of the address of the last dock the device was connected to */ 4881a847ba4080675d395de725cfac5dfd9d5a993d4eJean-Michel Trivi private String mDockAddress; 4882a847ba4080675d395de725cfac5dfd9d5a993d4eJean-Michel Trivi 4883a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent /** 4884a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent * Receiver for misc intent broadcasts the Phone app cares about. 4885a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent */ 4886a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent private class AudioServiceBroadcastReceiver extends BroadcastReceiver { 4887a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent @Override 4888a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent public void onReceive(Context context, Intent intent) { 4889a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent String action = intent.getAction(); 4890ae4506e9b5fc3e0c6d9862fbc05b9af7d6742a6eEric Laurent int outDevice; 4891ae4506e9b5fc3e0c6d9862fbc05b9af7d6742a6eEric Laurent int inDevice; 489259f482764e346a5c5ac118ee1f7b24da645c2559Eric Laurent int state; 4893a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent 4894758559e6b7e310cf46cc269437f44decd58d68d6Jean-Michel Trivi if (action.equals(Intent.ACTION_DOCK_EVENT)) { 4895758559e6b7e310cf46cc269437f44decd58d68d6Jean-Michel Trivi int dockState = intent.getIntExtra(Intent.EXTRA_DOCK_STATE, 4896758559e6b7e310cf46cc269437f44decd58d68d6Jean-Michel Trivi Intent.EXTRA_DOCK_STATE_UNDOCKED); 4897758559e6b7e310cf46cc269437f44decd58d68d6Jean-Michel Trivi int config; 4898758559e6b7e310cf46cc269437f44decd58d68d6Jean-Michel Trivi switch (dockState) { 4899758559e6b7e310cf46cc269437f44decd58d68d6Jean-Michel Trivi case Intent.EXTRA_DOCK_STATE_DESK: 4900758559e6b7e310cf46cc269437f44decd58d68d6Jean-Michel Trivi config = AudioSystem.FORCE_BT_DESK_DOCK; 4901758559e6b7e310cf46cc269437f44decd58d68d6Jean-Michel Trivi break; 4902758559e6b7e310cf46cc269437f44decd58d68d6Jean-Michel Trivi case Intent.EXTRA_DOCK_STATE_CAR: 4903758559e6b7e310cf46cc269437f44decd58d68d6Jean-Michel Trivi config = AudioSystem.FORCE_BT_CAR_DOCK; 4904758559e6b7e310cf46cc269437f44decd58d68d6Jean-Michel Trivi break; 490521e941bf43362ddc6639a9f2d0828053360f53d7Praveen Bharathi case Intent.EXTRA_DOCK_STATE_LE_DESK: 490608ed1b9d2099ec8231b21353b33b901492ea9885Eric Laurent config = AudioSystem.FORCE_ANALOG_DOCK; 490721e941bf43362ddc6639a9f2d0828053360f53d7Praveen Bharathi break; 490821e941bf43362ddc6639a9f2d0828053360f53d7Praveen Bharathi case Intent.EXTRA_DOCK_STATE_HE_DESK: 490921e941bf43362ddc6639a9f2d0828053360f53d7Praveen Bharathi config = AudioSystem.FORCE_DIGITAL_DOCK; 491021e941bf43362ddc6639a9f2d0828053360f53d7Praveen Bharathi break; 4911758559e6b7e310cf46cc269437f44decd58d68d6Jean-Michel Trivi case Intent.EXTRA_DOCK_STATE_UNDOCKED: 4912758559e6b7e310cf46cc269437f44decd58d68d6Jean-Michel Trivi default: 4913758559e6b7e310cf46cc269437f44decd58d68d6Jean-Michel Trivi config = AudioSystem.FORCE_NONE; 4914758559e6b7e310cf46cc269437f44decd58d68d6Jean-Michel Trivi } 491508ed1b9d2099ec8231b21353b33b901492ea9885Eric Laurent // Low end docks have a menu to enable or disable audio 491608ed1b9d2099ec8231b21353b33b901492ea9885Eric Laurent // (see mDockAudioMediaEnabled) 491708ed1b9d2099ec8231b21353b33b901492ea9885Eric Laurent if (!((dockState == Intent.EXTRA_DOCK_STATE_LE_DESK) || 491808ed1b9d2099ec8231b21353b33b901492ea9885Eric Laurent ((dockState == Intent.EXTRA_DOCK_STATE_UNDOCKED) && 491908ed1b9d2099ec8231b21353b33b901492ea9885Eric Laurent (mDockState == Intent.EXTRA_DOCK_STATE_LE_DESK)))) { 492008ed1b9d2099ec8231b21353b33b901492ea9885Eric Laurent AudioSystem.setForceUse(AudioSystem.FOR_DOCK, config); 492108ed1b9d2099ec8231b21353b33b901492ea9885Eric Laurent } 492208ed1b9d2099ec8231b21353b33b901492ea9885Eric Laurent mDockState = dockState; 492382aa7f017daaaeb96c13e6e3491d5037ab471085Jaikumar Ganesh } else if (action.equals(BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED)) { 492459f482764e346a5c5ac118ee1f7b24da645c2559Eric Laurent state = intent.getIntExtra(BluetoothProfile.EXTRA_STATE, 492582aa7f017daaaeb96c13e6e3491d5037ab471085Jaikumar Ganesh BluetoothProfile.STATE_DISCONNECTED); 4926ae4506e9b5fc3e0c6d9862fbc05b9af7d6742a6eEric Laurent outDevice = AudioSystem.DEVICE_OUT_BLUETOOTH_SCO; 4927ae4506e9b5fc3e0c6d9862fbc05b9af7d6742a6eEric Laurent inDevice = AudioSystem.DEVICE_IN_BLUETOOTH_SCO_HEADSET; 4928a56d1c72190462aa9e377906583eceb58e0efcddNick Pelly String address = null; 4929dca56b9432e2cc851d1a58920071fed2e1e3d142Eric Laurent 4930dca56b9432e2cc851d1a58920071fed2e1e3d142Eric Laurent BluetoothDevice btDevice = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE); 4931dca56b9432e2cc851d1a58920071fed2e1e3d142Eric Laurent if (btDevice == null) { 4932dca56b9432e2cc851d1a58920071fed2e1e3d142Eric Laurent return; 4933dca56b9432e2cc851d1a58920071fed2e1e3d142Eric Laurent } 4934dca56b9432e2cc851d1a58920071fed2e1e3d142Eric Laurent 4935dca56b9432e2cc851d1a58920071fed2e1e3d142Eric Laurent address = btDevice.getAddress(); 4936dca56b9432e2cc851d1a58920071fed2e1e3d142Eric Laurent BluetoothClass btClass = btDevice.getBluetoothClass(); 4937dca56b9432e2cc851d1a58920071fed2e1e3d142Eric Laurent if (btClass != null) { 4938dca56b9432e2cc851d1a58920071fed2e1e3d142Eric Laurent switch (btClass.getDeviceClass()) { 4939dca56b9432e2cc851d1a58920071fed2e1e3d142Eric Laurent case BluetoothClass.Device.AUDIO_VIDEO_WEARABLE_HEADSET: 4940dca56b9432e2cc851d1a58920071fed2e1e3d142Eric Laurent case BluetoothClass.Device.AUDIO_VIDEO_HANDSFREE: 4941ae4506e9b5fc3e0c6d9862fbc05b9af7d6742a6eEric Laurent outDevice = AudioSystem.DEVICE_OUT_BLUETOOTH_SCO_HEADSET; 4942dca56b9432e2cc851d1a58920071fed2e1e3d142Eric Laurent break; 4943dca56b9432e2cc851d1a58920071fed2e1e3d142Eric Laurent case BluetoothClass.Device.AUDIO_VIDEO_CAR_AUDIO: 4944ae4506e9b5fc3e0c6d9862fbc05b9af7d6742a6eEric Laurent outDevice = AudioSystem.DEVICE_OUT_BLUETOOTH_SCO_CARKIT; 4945dca56b9432e2cc851d1a58920071fed2e1e3d142Eric Laurent break; 4946d5603c126acdd94d9f7400bb1d04188020a425b4Eric Laurent } 4947d5603c126acdd94d9f7400bb1d04188020a425b4Eric Laurent } 4948d5603c126acdd94d9f7400bb1d04188020a425b4Eric Laurent 4949dca56b9432e2cc851d1a58920071fed2e1e3d142Eric Laurent if (!BluetoothAdapter.checkBluetoothAddress(address)) { 4950dca56b9432e2cc851d1a58920071fed2e1e3d142Eric Laurent address = ""; 4951dca56b9432e2cc851d1a58920071fed2e1e3d142Eric Laurent } 4952d5603c126acdd94d9f7400bb1d04188020a425b4Eric Laurent 495359f482764e346a5c5ac118ee1f7b24da645c2559Eric Laurent boolean connected = (state == BluetoothProfile.STATE_CONNECTED); 4954ae4506e9b5fc3e0c6d9862fbc05b9af7d6742a6eEric Laurent boolean success = handleDeviceConnection(connected, outDevice, address) && 4955ae4506e9b5fc3e0c6d9862fbc05b9af7d6742a6eEric Laurent handleDeviceConnection(connected, inDevice, address); 4956ae4506e9b5fc3e0c6d9862fbc05b9af7d6742a6eEric Laurent if (success) { 49576bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent synchronized (mScoClients) { 495859f482764e346a5c5ac118ee1f7b24da645c2559Eric Laurent if (connected) { 495959f482764e346a5c5ac118ee1f7b24da645c2559Eric Laurent mBluetoothHeadsetDevice = btDevice; 496059f482764e346a5c5ac118ee1f7b24da645c2559Eric Laurent } else { 49616bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent mBluetoothHeadsetDevice = null; 49626bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent resetBluetoothSco(); 49636bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent } 496462ef767b15a712bab31cc0d5508a330906f535c2Eric Laurent } 4965a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent } 4966c5258433dd353769ccfa2e5e769a7379378a3a0bJean-Michel Trivi } else if (action.equals(AudioManager.ACTION_USB_AUDIO_ACCESSORY_PLUG)) { 4967df3614693dd4fe52a116dcd28bd74eae80818a4fPaul McLean state = intent.getIntExtra("state", 0); 4968df3614693dd4fe52a116dcd28bd74eae80818a4fPaul McLean 4969df3614693dd4fe52a116dcd28bd74eae80818a4fPaul McLean int alsaCard = intent.getIntExtra("card", -1); 4970df3614693dd4fe52a116dcd28bd74eae80818a4fPaul McLean int alsaDevice = intent.getIntExtra("device", -1); 4971df3614693dd4fe52a116dcd28bd74eae80818a4fPaul McLean 4972df3614693dd4fe52a116dcd28bd74eae80818a4fPaul McLean String params = (alsaCard == -1 && alsaDevice == -1 ? "" 4973df3614693dd4fe52a116dcd28bd74eae80818a4fPaul McLean : "card=" + alsaCard + ";device=" + alsaDevice); 4974df3614693dd4fe52a116dcd28bd74eae80818a4fPaul McLean 4975df3614693dd4fe52a116dcd28bd74eae80818a4fPaul McLean // Playback Device 4976ae4506e9b5fc3e0c6d9862fbc05b9af7d6742a6eEric Laurent outDevice = AudioSystem.DEVICE_OUT_USB_ACCESSORY; 4977ae4506e9b5fc3e0c6d9862fbc05b9af7d6742a6eEric Laurent setWiredDeviceConnectionState(outDevice, state, params); 4978c5258433dd353769ccfa2e5e769a7379378a3a0bJean-Michel Trivi } else if (action.equals(AudioManager.ACTION_USB_AUDIO_DEVICE_PLUG)) { 49795f5163548424ed3a4d7ea259848f82fb74aaf75dGlenn Kasten // FIXME Does not yet handle the case where the setting is changed 49805f5163548424ed3a4d7ea259848f82fb74aaf75dGlenn Kasten // after device connection. Ideally we should handle the settings change 49815f5163548424ed3a4d7ea259848f82fb74aaf75dGlenn Kasten // in SettingsObserver. Here we should log that a USB device is connected 49825f5163548424ed3a4d7ea259848f82fb74aaf75dGlenn Kasten // and disconnected with its address (card , device) and force the 49835f5163548424ed3a4d7ea259848f82fb74aaf75dGlenn Kasten // connection or disconnection when the setting changes. 498434cc4db180c20569e62db5860c0b206be65b5117Glenn Kasten int isDisabled = Settings.Secure.getInt(mContentResolver, 498534cc4db180c20569e62db5860c0b206be65b5117Glenn Kasten Settings.Secure.USB_AUDIO_AUTOMATIC_ROUTING_DISABLED, 0); 49865f5163548424ed3a4d7ea259848f82fb74aaf75dGlenn Kasten if (isDisabled != 0) { 49875f5163548424ed3a4d7ea259848f82fb74aaf75dGlenn Kasten return; 49885f5163548424ed3a4d7ea259848f82fb74aaf75dGlenn Kasten } 49895f5163548424ed3a4d7ea259848f82fb74aaf75dGlenn Kasten 499059f482764e346a5c5ac118ee1f7b24da645c2559Eric Laurent state = intent.getIntExtra("state", 0); 4991c837a451946b64d70ed7c642fbde03c182c28b6fPaul McLean 499259f482764e346a5c5ac118ee1f7b24da645c2559Eric Laurent int alsaCard = intent.getIntExtra("card", -1); 499359f482764e346a5c5ac118ee1f7b24da645c2559Eric Laurent int alsaDevice = intent.getIntExtra("device", -1); 4994c837a451946b64d70ed7c642fbde03c182c28b6fPaul McLean boolean hasPlayback = intent.getBooleanExtra("hasPlayback", false); 4995c837a451946b64d70ed7c642fbde03c182c28b6fPaul McLean boolean hasCapture = intent.getBooleanExtra("hasCapture", false); 4996c837a451946b64d70ed7c642fbde03c182c28b6fPaul McLean boolean hasMIDI = intent.getBooleanExtra("hasMIDI", false); 4997c837a451946b64d70ed7c642fbde03c182c28b6fPaul McLean 49989841818b9a0280abf59343c9e00a2976dbc084faMike Lockwood String params = (alsaCard == -1 && alsaDevice == -1 ? "" 49999841818b9a0280abf59343c9e00a2976dbc084faMike Lockwood : "card=" + alsaCard + ";device=" + alsaDevice); 5000c837a451946b64d70ed7c642fbde03c182c28b6fPaul McLean 5001c837a451946b64d70ed7c642fbde03c182c28b6fPaul McLean // Playback Device 5002df3614693dd4fe52a116dcd28bd74eae80818a4fPaul McLean if (hasPlayback) { 5003ae4506e9b5fc3e0c6d9862fbc05b9af7d6742a6eEric Laurent outDevice = AudioSystem.DEVICE_OUT_USB_DEVICE; 5004ae4506e9b5fc3e0c6d9862fbc05b9af7d6742a6eEric Laurent setWiredDeviceConnectionState(outDevice, state, params); 5005df3614693dd4fe52a116dcd28bd74eae80818a4fPaul McLean } 5006c837a451946b64d70ed7c642fbde03c182c28b6fPaul McLean 5007c837a451946b64d70ed7c642fbde03c182c28b6fPaul McLean // Capture Device 5008df3614693dd4fe52a116dcd28bd74eae80818a4fPaul McLean if (hasCapture) { 5009ae4506e9b5fc3e0c6d9862fbc05b9af7d6742a6eEric Laurent inDevice = AudioSystem.DEVICE_IN_USB_DEVICE; 5010ae4506e9b5fc3e0c6d9862fbc05b9af7d6742a6eEric Laurent setWiredDeviceConnectionState(inDevice, state, params); 5011df3614693dd4fe52a116dcd28bd74eae80818a4fPaul McLean } 5012df3614693dd4fe52a116dcd28bd74eae80818a4fPaul McLean } else if (action.equals(BluetoothHeadset.ACTION_AUDIO_STATE_CHANGED)) { 501362ef767b15a712bab31cc0d5508a330906f535c2Eric Laurent boolean broadcast = false; 501459f482764e346a5c5ac118ee1f7b24da645c2559Eric Laurent int scoAudioState = AudioManager.SCO_AUDIO_STATE_ERROR; 50153def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent synchronized (mScoClients) { 501662ef767b15a712bab31cc0d5508a330906f535c2Eric Laurent int btState = intent.getIntExtra(BluetoothProfile.EXTRA_STATE, -1); 5017dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent // broadcast intent if the connection was initated by AudioService 5018dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent if (!mScoClients.isEmpty() && 5019dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent (mScoAudioState == SCO_STATE_ACTIVE_INTERNAL || 5020dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent mScoAudioState == SCO_STATE_ACTIVATE_REQ || 5021dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent mScoAudioState == SCO_STATE_DEACTIVATE_REQ)) { 502262ef767b15a712bab31cc0d5508a330906f535c2Eric Laurent broadcast = true; 502362ef767b15a712bab31cc0d5508a330906f535c2Eric Laurent } 502462ef767b15a712bab31cc0d5508a330906f535c2Eric Laurent switch (btState) { 502562ef767b15a712bab31cc0d5508a330906f535c2Eric Laurent case BluetoothHeadset.STATE_AUDIO_CONNECTED: 502659f482764e346a5c5ac118ee1f7b24da645c2559Eric Laurent scoAudioState = AudioManager.SCO_AUDIO_STATE_CONNECTED; 5027dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent if (mScoAudioState != SCO_STATE_ACTIVE_INTERNAL && 5028dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent mScoAudioState != SCO_STATE_DEACTIVATE_REQ && 5029dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent mScoAudioState != SCO_STATE_DEACTIVATE_EXT_REQ) { 503062ef767b15a712bab31cc0d5508a330906f535c2Eric Laurent mScoAudioState = SCO_STATE_ACTIVE_EXTERNAL; 50313def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent } 503262ef767b15a712bab31cc0d5508a330906f535c2Eric Laurent break; 503362ef767b15a712bab31cc0d5508a330906f535c2Eric Laurent case BluetoothHeadset.STATE_AUDIO_DISCONNECTED: 503459f482764e346a5c5ac118ee1f7b24da645c2559Eric Laurent scoAudioState = AudioManager.SCO_AUDIO_STATE_DISCONNECTED; 503562ef767b15a712bab31cc0d5508a330906f535c2Eric Laurent mScoAudioState = SCO_STATE_INACTIVE; 5036d7454be47f4111c0478a502353e11dea401378bdEric Laurent clearAllScoClients(0, false); 503762ef767b15a712bab31cc0d5508a330906f535c2Eric Laurent break; 503862ef767b15a712bab31cc0d5508a330906f535c2Eric Laurent case BluetoothHeadset.STATE_AUDIO_CONNECTING: 5039dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent if (mScoAudioState != SCO_STATE_ACTIVE_INTERNAL && 5040dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent mScoAudioState != SCO_STATE_DEACTIVATE_REQ && 5041dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent mScoAudioState != SCO_STATE_DEACTIVATE_EXT_REQ) { 504262ef767b15a712bab31cc0d5508a330906f535c2Eric Laurent mScoAudioState = SCO_STATE_ACTIVE_EXTERNAL; 50433def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent } 504462ef767b15a712bab31cc0d5508a330906f535c2Eric Laurent default: 504562ef767b15a712bab31cc0d5508a330906f535c2Eric Laurent // do not broadcast CONNECTING or invalid state 504662ef767b15a712bab31cc0d5508a330906f535c2Eric Laurent broadcast = false; 504762ef767b15a712bab31cc0d5508a330906f535c2Eric Laurent break; 50483def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent } 50493def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent } 505062ef767b15a712bab31cc0d5508a330906f535c2Eric Laurent if (broadcast) { 505159f482764e346a5c5ac118ee1f7b24da645c2559Eric Laurent broadcastScoConnectionState(scoAudioState); 5052dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent //FIXME: this is to maintain compatibility with deprecated intent 5053dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent // AudioManager.ACTION_SCO_AUDIO_STATE_CHANGED. Remove when appropriate. 505462ef767b15a712bab31cc0d5508a330906f535c2Eric Laurent Intent newIntent = new Intent(AudioManager.ACTION_SCO_AUDIO_STATE_CHANGED); 505559f482764e346a5c5ac118ee1f7b24da645c2559Eric Laurent newIntent.putExtra(AudioManager.EXTRA_SCO_AUDIO_STATE, scoAudioState); 50565ac72a29593ab9a20337a2225df52bdf4754be02Dianne Hackborn sendStickyBroadcastToAll(newIntent); 505762ef767b15a712bab31cc0d5508a330906f535c2Eric Laurent } 5058950e8cb40a6d826af4cc2eef9d3908c1b70486e6Eric Laurent } else if (action.equals(Intent.ACTION_SCREEN_ON)) { 5059318f0fe43bdc4b2f6764edd91d6b78d9875ffdebJon Eklund if (mMonitorRotation) { 5060318f0fe43bdc4b2f6764edd91d6b78d9875ffdebJon Eklund mOrientationListener.onOrientationChanged(0); //argument is ignored anyway 5061318f0fe43bdc4b2f6764edd91d6b78d9875ffdebJon Eklund mOrientationListener.enable(); 5062318f0fe43bdc4b2f6764edd91d6b78d9875ffdebJon Eklund } 5063950e8cb40a6d826af4cc2eef9d3908c1b70486e6Eric Laurent AudioSystem.setParameters("screen_state=on"); 5064950e8cb40a6d826af4cc2eef9d3908c1b70486e6Eric Laurent } else if (action.equals(Intent.ACTION_SCREEN_OFF)) { 5065318f0fe43bdc4b2f6764edd91d6b78d9875ffdebJon Eklund if (mMonitorRotation) { 5066318f0fe43bdc4b2f6764edd91d6b78d9875ffdebJon Eklund //reduce wakeups (save current) by only listening when display is on 5067318f0fe43bdc4b2f6764edd91d6b78d9875ffdebJon Eklund mOrientationListener.disable(); 5068318f0fe43bdc4b2f6764edd91d6b78d9875ffdebJon Eklund } 5069950e8cb40a6d826af4cc2eef9d3908c1b70486e6Eric Laurent AudioSystem.setParameters("screen_state=off"); 5070961cae92540763226648813d111c5b5c3b0f1597Dianne Hackborn } else if (action.equals(Intent.ACTION_CONFIGURATION_CHANGED)) { 5071f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi handleConfigurationChanged(context); 5072bc0fab1fc2db832ef86d8a33466ec4d68b103ca0Eric Laurent } else if (action.equals(Intent.ACTION_USER_SWITCHED)) { 5073f4a8eb22112c534f436357b50f231778c5c15c25Jean-Michel Trivi // attempt to stop music playback for background user 50745bfaeaef3fc348d66f48b86be08655e91dff910aEric Laurent sendMsg(mAudioHandler, 50755bfaeaef3fc348d66f48b86be08655e91dff910aEric Laurent MSG_BROADCAST_AUDIO_BECOMING_NOISY, 50765bfaeaef3fc348d66f48b86be08655e91dff910aEric Laurent SENDMSG_REPLACE, 50775bfaeaef3fc348d66f48b86be08655e91dff910aEric Laurent 0, 50785bfaeaef3fc348d66f48b86be08655e91dff910aEric Laurent 0, 50795bfaeaef3fc348d66f48b86be08655e91dff910aEric Laurent null, 50805bfaeaef3fc348d66f48b86be08655e91dff910aEric Laurent 0); 5081f4a8eb22112c534f436357b50f231778c5c15c25Jean-Michel Trivi // the current audio focus owner is no longer valid 5082fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi mMediaFocusControl.discardAudioFocusOwner(); 5083f4a8eb22112c534f436357b50f231778c5c15c25Jean-Michel Trivi 50845bfaeaef3fc348d66f48b86be08655e91dff910aEric Laurent // load volume settings for new user 5085bc0fab1fc2db832ef86d8a33466ec4d68b103ca0Eric Laurent readAudioSettings(true /*userSwitch*/); 5086bc0fab1fc2db832ef86d8a33466ec4d68b103ca0Eric Laurent // preserve STREAM_MUSIC volume from one user to the next. 5087bc0fab1fc2db832ef86d8a33466ec4d68b103ca0Eric Laurent sendMsg(mAudioHandler, 5088bc0fab1fc2db832ef86d8a33466ec4d68b103ca0Eric Laurent MSG_SET_ALL_VOLUMES, 5089bc0fab1fc2db832ef86d8a33466ec4d68b103ca0Eric Laurent SENDMSG_QUEUE, 5090bc0fab1fc2db832ef86d8a33466ec4d68b103ca0Eric Laurent 0, 5091bc0fab1fc2db832ef86d8a33466ec4d68b103ca0Eric Laurent 0, 5092bc0fab1fc2db832ef86d8a33466ec4d68b103ca0Eric Laurent mStreamStates[AudioSystem.STREAM_MUSIC], 0); 5093a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent } 5094a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent } 5095c837a451946b64d70ed7c642fbde03c182c28b6fPaul McLean } // end class AudioServiceBroadcastReceiver 5096d5176cfe6eae954e9cef1e2ec17859a5089e1330Jean-Michel Trivi 5097d5176cfe6eae954e9cef1e2ec17859a5089e1330Jean-Michel Trivi //========================================================================================== 5098fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi // RemoteControlDisplay / RemoteControlClient / Remote info 5099d5176cfe6eae954e9cef1e2ec17859a5089e1330Jean-Michel Trivi //========================================================================================== 5100f108cdd9ee5efe354d87edd02a07b323298c116cJean-Michel Trivi public boolean registerRemoteController(IRemoteControlDisplay rcd, int w, int h, 5101f108cdd9ee5efe354d87edd02a07b323298c116cJean-Michel Trivi ComponentName listenerComp) { 5102f108cdd9ee5efe354d87edd02a07b323298c116cJean-Michel Trivi return mMediaFocusControl.registerRemoteController(rcd, w, h, listenerComp); 5103f108cdd9ee5efe354d87edd02a07b323298c116cJean-Michel Trivi } 5104f108cdd9ee5efe354d87edd02a07b323298c116cJean-Michel Trivi 51057ddd226e7c6e759feaf2747a90be1cc06acf37a3Jean-Michel Trivi public boolean registerRemoteControlDisplay(IRemoteControlDisplay rcd, int w, int h) { 5106f108cdd9ee5efe354d87edd02a07b323298c116cJean-Michel Trivi return mMediaFocusControl.registerRemoteControlDisplay(rcd, w, h); 5107e5e1e870fdb35f5291790e6d178bde7126f6fe35Jean-Michel Trivi } 5108e5e1e870fdb35f5291790e6d178bde7126f6fe35Jean-Michel Trivi 5109fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi public void unregisterRemoteControlDisplay(IRemoteControlDisplay rcd) { 5110fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi mMediaFocusControl.unregisterRemoteControlDisplay(rcd); 5111d5176cfe6eae954e9cef1e2ec17859a5089e1330Jean-Michel Trivi } 5112d5176cfe6eae954e9cef1e2ec17859a5089e1330Jean-Michel Trivi 5113fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi public void remoteControlDisplayUsesBitmapSize(IRemoteControlDisplay rcd, int w, int h) { 5114fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi mMediaFocusControl.remoteControlDisplayUsesBitmapSize(rcd, w, h); 5115d5176cfe6eae954e9cef1e2ec17859a5089e1330Jean-Michel Trivi } 5116d5176cfe6eae954e9cef1e2ec17859a5089e1330Jean-Michel Trivi 5117fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi public void remoteControlDisplayWantsPlaybackPositionSync(IRemoteControlDisplay rcd, 5118fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi boolean wantsSync) { 5119fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi mMediaFocusControl.remoteControlDisplayWantsPlaybackPositionSync(rcd, wantsSync); 5120d5176cfe6eae954e9cef1e2ec17859a5089e1330Jean-Michel Trivi } 5121d5176cfe6eae954e9cef1e2ec17859a5089e1330Jean-Michel Trivi 51223346a802087f621c6441bc512dfcc17b07143fc6John Spurlock @Override 5123fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi public void setRemoteStreamVolume(int index) { 51243346a802087f621c6441bc512dfcc17b07143fc6John Spurlock enforceSelfOrSystemUI("set the remote stream volume"); 5125fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi mMediaFocusControl.setRemoteStreamVolume(index); 5126d327f21626217aa3c9c0cdb7a84a742c531e59a3Jean-Michel Trivi } 5127d327f21626217aa3c9c0cdb7a84a742c531e59a3Jean-Michel Trivi 5128fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi //========================================================================================== 5129fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi // Audio Focus 5130fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi //========================================================================================== 5131fd6ad747e6c268753d0edf7a5a59b6815b190854Jean-Michel Trivi public int requestAudioFocus(AudioAttributes aa, int durationHint, IBinder cb, 5132958876fe55ea0fdeb73c72240a2f2bab32833443Jean-Michel Trivi IAudioFocusDispatcher fd, String clientId, String callingPackageName, int flags, 51330212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi IAudioPolicyCallback pcb) { 5134958876fe55ea0fdeb73c72240a2f2bab32833443Jean-Michel Trivi // permission checks 5135958876fe55ea0fdeb73c72240a2f2bab32833443Jean-Michel Trivi if ((flags & AudioManager.AUDIOFOCUS_FLAG_LOCK) == AudioManager.AUDIOFOCUS_FLAG_LOCK) { 5136958876fe55ea0fdeb73c72240a2f2bab32833443Jean-Michel Trivi if (mMediaFocusControl.IN_VOICE_COMM_FOCUS_ID.equals(clientId)) { 5137958876fe55ea0fdeb73c72240a2f2bab32833443Jean-Michel Trivi if (PackageManager.PERMISSION_GRANTED != mContext.checkCallingOrSelfPermission( 5138958876fe55ea0fdeb73c72240a2f2bab32833443Jean-Michel Trivi android.Manifest.permission.MODIFY_PHONE_STATE)) { 5139958876fe55ea0fdeb73c72240a2f2bab32833443Jean-Michel Trivi Log.e(TAG, "Invalid permission to (un)lock audio focus", new Exception()); 5140958876fe55ea0fdeb73c72240a2f2bab32833443Jean-Michel Trivi return AudioManager.AUDIOFOCUS_REQUEST_FAILED; 5141958876fe55ea0fdeb73c72240a2f2bab32833443Jean-Michel Trivi } 5142958876fe55ea0fdeb73c72240a2f2bab32833443Jean-Michel Trivi } else { 5143958876fe55ea0fdeb73c72240a2f2bab32833443Jean-Michel Trivi // only a registered audio policy can be used to lock focus 5144958876fe55ea0fdeb73c72240a2f2bab32833443Jean-Michel Trivi synchronized (mAudioPolicies) { 51450212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi if (!mAudioPolicies.containsKey(pcb.asBinder())) { 51460212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi Log.e(TAG, "Invalid unregistered AudioPolicy to (un)lock audio focus"); 5147958876fe55ea0fdeb73c72240a2f2bab32833443Jean-Michel Trivi return AudioManager.AUDIOFOCUS_REQUEST_FAILED; 5148958876fe55ea0fdeb73c72240a2f2bab32833443Jean-Michel Trivi } 5149958876fe55ea0fdeb73c72240a2f2bab32833443Jean-Michel Trivi } 5150958876fe55ea0fdeb73c72240a2f2bab32833443Jean-Michel Trivi } 5151958876fe55ea0fdeb73c72240a2f2bab32833443Jean-Michel Trivi } 5152958876fe55ea0fdeb73c72240a2f2bab32833443Jean-Michel Trivi 5153fd6ad747e6c268753d0edf7a5a59b6815b190854Jean-Michel Trivi return mMediaFocusControl.requestAudioFocus(aa, durationHint, cb, fd, 5154fd6ad747e6c268753d0edf7a5a59b6815b190854Jean-Michel Trivi clientId, callingPackageName, flags); 51554294b83927f51e5c115ebaafd2e185ba5de91436Jean-Michel Trivi } 51564294b83927f51e5c115ebaafd2e185ba5de91436Jean-Michel Trivi 5157958876fe55ea0fdeb73c72240a2f2bab32833443Jean-Michel Trivi public int abandonAudioFocus(IAudioFocusDispatcher fd, String clientId, AudioAttributes aa) { 5158958876fe55ea0fdeb73c72240a2f2bab32833443Jean-Michel Trivi return mMediaFocusControl.abandonAudioFocus(fd, clientId, aa); 5159c68022258ebd3dd97a5079ba99f4f3cd12b223b0Jean-Michel Trivi } 5160c68022258ebd3dd97a5079ba99f4f3cd12b223b0Jean-Michel Trivi 5161fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi public void unregisterAudioFocusClient(String clientId) { 5162fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi mMediaFocusControl.unregisterAudioFocusClient(clientId); 51633114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi } 51643114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi 51652380566debfc57eb1cc07db1306ccee23b84ddd4Jean-Michel Trivi public int getCurrentAudioFocus() { 51662380566debfc57eb1cc07db1306ccee23b84ddd4Jean-Michel Trivi return mMediaFocusControl.getCurrentAudioFocus(); 51672380566debfc57eb1cc07db1306ccee23b84ddd4Jean-Michel Trivi } 51682380566debfc57eb1cc07db1306ccee23b84ddd4Jean-Michel Trivi 5169f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi //========================================================================================== 5170f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi // Device orientation 5171f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi //========================================================================================== 5172f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi /** 5173bb6f8711a7f804d39c45218db2d6339940cc5d35Jean-Michel Trivi * Handles device configuration changes that may map to a change in the orientation 5174bb6f8711a7f804d39c45218db2d6339940cc5d35Jean-Michel Trivi * or orientation. 5175bb6f8711a7f804d39c45218db2d6339940cc5d35Jean-Michel Trivi * Monitoring orientation and rotation is optional, and is defined by the definition and value 5176bb6f8711a7f804d39c45218db2d6339940cc5d35Jean-Michel Trivi * of the "ro.audio.monitorOrientation" and "ro.audio.monitorRotation" system properties. 5177f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi */ 5178f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi private void handleConfigurationChanged(Context context) { 5179f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi try { 5180f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi // reading new orientation "safely" (i.e. under try catch) in case anything 5181f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi // goes wrong when obtaining resources and configuration 5182d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent Configuration config = context.getResources().getConfiguration(); 5183bb6f8711a7f804d39c45218db2d6339940cc5d35Jean-Michel Trivi // TODO merge rotation and orientation 5184d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent if (mMonitorOrientation) { 5185d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent int newOrientation = config.orientation; 5186d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent if (newOrientation != mDeviceOrientation) { 5187d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent mDeviceOrientation = newOrientation; 5188d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent setOrientationForAudioSystem(); 5189d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent } 5190f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi } 5191d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent sendMsg(mAudioHandler, 5192d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent MSG_CONFIGURE_SAFE_MEDIA_VOLUME, 5193d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent SENDMSG_REPLACE, 5194d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent 0, 5195d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent 0, 5196d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent null, 5197d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent 0); 5198dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent 5199dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent boolean cameraSoundForced = mContext.getResources().getBoolean( 5200dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent com.android.internal.R.bool.config_camera_sound_forced); 5201dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent synchronized (mSettingsLock) { 52028fa4d6f585f40ff5cf5f9bed316d92c64a306f21Eric Laurent boolean cameraSoundForcedChanged = false; 5203dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent synchronized (mCameraSoundForced) { 5204dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent if (cameraSoundForced != mCameraSoundForced) { 5205dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent mCameraSoundForced = cameraSoundForced; 52068fa4d6f585f40ff5cf5f9bed316d92c64a306f21Eric Laurent cameraSoundForcedChanged = true; 52078fa4d6f585f40ff5cf5f9bed316d92c64a306f21Eric Laurent } 52088fa4d6f585f40ff5cf5f9bed316d92c64a306f21Eric Laurent } 52098fa4d6f585f40ff5cf5f9bed316d92c64a306f21Eric Laurent if (cameraSoundForcedChanged) { 52108fa4d6f585f40ff5cf5f9bed316d92c64a306f21Eric Laurent if (!isPlatformTelevision()) { 52118fa4d6f585f40ff5cf5f9bed316d92c64a306f21Eric Laurent VolumeStreamState s = mStreamStates[AudioSystem.STREAM_SYSTEM_ENFORCED]; 52128fa4d6f585f40ff5cf5f9bed316d92c64a306f21Eric Laurent if (cameraSoundForced) { 52138fa4d6f585f40ff5cf5f9bed316d92c64a306f21Eric Laurent s.setAllIndexesToMax(); 52148fa4d6f585f40ff5cf5f9bed316d92c64a306f21Eric Laurent mRingerModeAffectedStreams &= 52158fa4d6f585f40ff5cf5f9bed316d92c64a306f21Eric Laurent ~(1 << AudioSystem.STREAM_SYSTEM_ENFORCED); 52168fa4d6f585f40ff5cf5f9bed316d92c64a306f21Eric Laurent } else { 52178fa4d6f585f40ff5cf5f9bed316d92c64a306f21Eric Laurent s.setAllIndexes(mStreamStates[AudioSystem.STREAM_SYSTEM]); 52188fa4d6f585f40ff5cf5f9bed316d92c64a306f21Eric Laurent mRingerModeAffectedStreams |= 52198fa4d6f585f40ff5cf5f9bed316d92c64a306f21Eric Laurent (1 << AudioSystem.STREAM_SYSTEM_ENFORCED); 5220dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent } 52218fa4d6f585f40ff5cf5f9bed316d92c64a306f21Eric Laurent // take new state into account for streams muted by ringer mode 5222661f2cf45860d2e10924e6b69966a9afe255f28bJohn Spurlock setRingerModeInt(getRingerModeInternal(), false); 5223dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent } 52248fa4d6f585f40ff5cf5f9bed316d92c64a306f21Eric Laurent 52258fa4d6f585f40ff5cf5f9bed316d92c64a306f21Eric Laurent sendMsg(mAudioHandler, 52268fa4d6f585f40ff5cf5f9bed316d92c64a306f21Eric Laurent MSG_SET_FORCE_USE, 52278fa4d6f585f40ff5cf5f9bed316d92c64a306f21Eric Laurent SENDMSG_QUEUE, 52288fa4d6f585f40ff5cf5f9bed316d92c64a306f21Eric Laurent AudioSystem.FOR_SYSTEM, 52298fa4d6f585f40ff5cf5f9bed316d92c64a306f21Eric Laurent cameraSoundForced ? 52308fa4d6f585f40ff5cf5f9bed316d92c64a306f21Eric Laurent AudioSystem.FORCE_SYSTEM_ENFORCED : AudioSystem.FORCE_NONE, 52318fa4d6f585f40ff5cf5f9bed316d92c64a306f21Eric Laurent null, 52328fa4d6f585f40ff5cf5f9bed316d92c64a306f21Eric Laurent 0); 52338fa4d6f585f40ff5cf5f9bed316d92c64a306f21Eric Laurent 52348fa4d6f585f40ff5cf5f9bed316d92c64a306f21Eric Laurent sendMsg(mAudioHandler, 52358fa4d6f585f40ff5cf5f9bed316d92c64a306f21Eric Laurent MSG_SET_ALL_VOLUMES, 52368fa4d6f585f40ff5cf5f9bed316d92c64a306f21Eric Laurent SENDMSG_QUEUE, 52378fa4d6f585f40ff5cf5f9bed316d92c64a306f21Eric Laurent 0, 52388fa4d6f585f40ff5cf5f9bed316d92c64a306f21Eric Laurent 0, 52398fa4d6f585f40ff5cf5f9bed316d92c64a306f21Eric Laurent mStreamStates[AudioSystem.STREAM_SYSTEM_ENFORCED], 0); 5240dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent } 5241dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent } 52423346a802087f621c6441bc512dfcc17b07143fc6John Spurlock mVolumeController.setLayoutDirection(config.getLayoutDirection()); 5243f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi } catch (Exception e) { 5244bb6f8711a7f804d39c45218db2d6339940cc5d35Jean-Michel Trivi Log.e(TAG, "Error handling configuration change: ", e); 5245f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi } 5246f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi } 5247f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi 5248f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi private void setOrientationForAudioSystem() { 5249f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi switch (mDeviceOrientation) { 5250f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi case Configuration.ORIENTATION_LANDSCAPE: 5251f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi //Log.i(TAG, "orientation is landscape"); 5252f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi AudioSystem.setParameters("orientation=landscape"); 5253f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi break; 5254f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi case Configuration.ORIENTATION_PORTRAIT: 5255f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi //Log.i(TAG, "orientation is portrait"); 5256f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi AudioSystem.setParameters("orientation=portrait"); 5257f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi break; 5258f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi case Configuration.ORIENTATION_SQUARE: 5259f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi //Log.i(TAG, "orientation is square"); 5260f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi AudioSystem.setParameters("orientation=square"); 5261f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi break; 5262f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi case Configuration.ORIENTATION_UNDEFINED: 5263f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi //Log.i(TAG, "orientation is undefined"); 5264f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi AudioSystem.setParameters("orientation=undefined"); 5265f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi break; 5266f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi default: 5267f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi Log.e(TAG, "Unknown orientation"); 5268f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi } 5269f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi } 5270f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi 5271bb6f8711a7f804d39c45218db2d6339940cc5d35Jean-Michel Trivi private void setRotationForAudioSystem() { 5272bb6f8711a7f804d39c45218db2d6339940cc5d35Jean-Michel Trivi switch (mDeviceRotation) { 5273bb6f8711a7f804d39c45218db2d6339940cc5d35Jean-Michel Trivi case Surface.ROTATION_0: 5274bb6f8711a7f804d39c45218db2d6339940cc5d35Jean-Michel Trivi AudioSystem.setParameters("rotation=0"); 5275bb6f8711a7f804d39c45218db2d6339940cc5d35Jean-Michel Trivi break; 5276bb6f8711a7f804d39c45218db2d6339940cc5d35Jean-Michel Trivi case Surface.ROTATION_90: 5277bb6f8711a7f804d39c45218db2d6339940cc5d35Jean-Michel Trivi AudioSystem.setParameters("rotation=90"); 5278bb6f8711a7f804d39c45218db2d6339940cc5d35Jean-Michel Trivi break; 5279bb6f8711a7f804d39c45218db2d6339940cc5d35Jean-Michel Trivi case Surface.ROTATION_180: 5280bb6f8711a7f804d39c45218db2d6339940cc5d35Jean-Michel Trivi AudioSystem.setParameters("rotation=180"); 5281bb6f8711a7f804d39c45218db2d6339940cc5d35Jean-Michel Trivi break; 5282bb6f8711a7f804d39c45218db2d6339940cc5d35Jean-Michel Trivi case Surface.ROTATION_270: 5283bb6f8711a7f804d39c45218db2d6339940cc5d35Jean-Michel Trivi AudioSystem.setParameters("rotation=270"); 5284bb6f8711a7f804d39c45218db2d6339940cc5d35Jean-Michel Trivi break; 5285bb6f8711a7f804d39c45218db2d6339940cc5d35Jean-Michel Trivi default: 5286bb6f8711a7f804d39c45218db2d6339940cc5d35Jean-Michel Trivi Log.e(TAG, "Unknown device rotation"); 5287bb6f8711a7f804d39c45218db2d6339940cc5d35Jean-Michel Trivi } 5288bb6f8711a7f804d39c45218db2d6339940cc5d35Jean-Michel Trivi } 5289bb6f8711a7f804d39c45218db2d6339940cc5d35Jean-Michel Trivi 5290f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi 52917847211fb4699bf6018e29d214a918ed6657319bEric Laurent // Handles request to override default use of A2DP for media. 52927847211fb4699bf6018e29d214a918ed6657319bEric Laurent public void setBluetoothA2dpOnInt(boolean on) { 52937847211fb4699bf6018e29d214a918ed6657319bEric Laurent synchronized (mBluetoothA2dpEnabledLock) { 52947847211fb4699bf6018e29d214a918ed6657319bEric Laurent mBluetoothA2dpEnabled = on; 5295c390bed06b4a572e273ead1254da9a932e04dce3Eric Laurent mAudioHandler.removeMessages(MSG_SET_FORCE_BT_A2DP_USE); 5296c390bed06b4a572e273ead1254da9a932e04dce3Eric Laurent AudioSystem.setForceUse(AudioSystem.FOR_MEDIA, 5297c390bed06b4a572e273ead1254da9a932e04dce3Eric Laurent mBluetoothA2dpEnabled ? AudioSystem.FORCE_NONE : AudioSystem.FORCE_NO_BT_A2DP); 52987847211fb4699bf6018e29d214a918ed6657319bEric Laurent } 52997847211fb4699bf6018e29d214a918ed6657319bEric Laurent } 53007847211fb4699bf6018e29d214a918ed6657319bEric Laurent 5301d5176cfe6eae954e9cef1e2ec17859a5089e1330Jean-Michel Trivi @Override 5302098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey public void setRingtonePlayer(IRingtonePlayer player) { 5303098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey mContext.enforceCallingOrSelfPermission(REMOTE_AUDIO_PLAYBACK, null); 5304098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey mRingtonePlayer = player; 5305098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey } 5306098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey 5307098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey @Override 5308098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey public IRingtonePlayer getRingtonePlayer() { 5309098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey return mRingtonePlayer; 5310098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey } 5311098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey 5312098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey @Override 5313632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn public AudioRoutesInfo startWatchingRoutes(IAudioRoutesObserver observer) { 5314632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn synchronized (mCurAudioRoutes) { 5315632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn AudioRoutesInfo routes = new AudioRoutesInfo(mCurAudioRoutes); 5316632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn mRoutesObservers.register(observer); 5317632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn return routes; 5318632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn } 5319632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn } 5320632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn 5321c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent 5322c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent //========================================================================================== 5323c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent // Safe media volume management. 5324c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent // MUSIC stream volume level is limited when headphones are connected according to safety 5325c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent // regulation. When the user attempts to raise the volume above the limit, a warning is 5326c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent // displayed and the user has to acknowlegde before the volume is actually changed. 5327c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent // The volume index corresponding to the limit is stored in config_safe_media_volume_index 5328c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent // property. Platforms with a different limit must set this property accordingly in their 5329c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent // overlay. 5330c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent //========================================================================================== 5331c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent 5332d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent // mSafeMediaVolumeState indicates whether the media volume is limited over headphones. 5333d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent // It is SAFE_MEDIA_VOLUME_NOT_CONFIGURED at boot time until a network service is connected 5334d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent // or the configure time is elapsed. It is then set to SAFE_MEDIA_VOLUME_ACTIVE or 5335d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent // SAFE_MEDIA_VOLUME_DISABLED according to country option. If not SAFE_MEDIA_VOLUME_DISABLED, it 5336d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent // can be set to SAFE_MEDIA_VOLUME_INACTIVE by calling AudioService.disableSafeMediaVolume() 5337d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent // (when user opts out). 5338351346092acdfbfcc1d9ebf98d539d2a1196c5e8John Spurlock private static final int SAFE_MEDIA_VOLUME_NOT_CONFIGURED = 0; 5339351346092acdfbfcc1d9ebf98d539d2a1196c5e8John Spurlock private static final int SAFE_MEDIA_VOLUME_DISABLED = 1; 5340351346092acdfbfcc1d9ebf98d539d2a1196c5e8John Spurlock private static final int SAFE_MEDIA_VOLUME_INACTIVE = 2; // confirmed 5341351346092acdfbfcc1d9ebf98d539d2a1196c5e8John Spurlock private static final int SAFE_MEDIA_VOLUME_ACTIVE = 3; // unconfirmed 5342d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent private Integer mSafeMediaVolumeState; 5343d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent 5344d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent private int mMcc = 0; 5345c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent // mSafeMediaVolumeIndex is the cached value of config_safe_media_volume_index property 5346d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent private int mSafeMediaVolumeIndex; 5347c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent // mSafeMediaVolumeDevices lists the devices for which safe media volume is enforced, 5348c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent private final int mSafeMediaVolumeDevices = AudioSystem.DEVICE_OUT_WIRED_HEADSET | 5349c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent AudioSystem.DEVICE_OUT_WIRED_HEADPHONE; 5350c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent // mMusicActiveMs is the cumulative time of music activity since safe volume was disabled. 5351c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent // When this time reaches UNSAFE_VOLUME_MUSIC_ACTIVE_MS_MAX, the safe media volume is re-enabled 5352c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent // automatically. mMusicActiveMs is rounded to a multiple of MUSIC_ACTIVE_POLL_PERIOD_MS. 5353c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent private int mMusicActiveMs; 5354c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent private static final int UNSAFE_VOLUME_MUSIC_ACTIVE_MS_MAX = (20 * 3600 * 1000); // 20 hours 5355c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent private static final int MUSIC_ACTIVE_POLL_PERIOD_MS = 60000; // 1 minute polling interval 5356d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent private static final int SAFE_VOLUME_CONFIGURE_TIMEOUT_MS = 30000; // 30s after boot completed 5357c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent 5358c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent private void setSafeMediaVolumeEnabled(boolean on) { 5359d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent synchronized (mSafeMediaVolumeState) { 5360d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent if ((mSafeMediaVolumeState != SAFE_MEDIA_VOLUME_NOT_CONFIGURED) && 5361d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent (mSafeMediaVolumeState != SAFE_MEDIA_VOLUME_DISABLED)) { 5362d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent if (on && (mSafeMediaVolumeState == SAFE_MEDIA_VOLUME_INACTIVE)) { 5363d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent mSafeMediaVolumeState = SAFE_MEDIA_VOLUME_ACTIVE; 5364d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent enforceSafeMediaVolume(); 5365d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent } else if (!on && (mSafeMediaVolumeState == SAFE_MEDIA_VOLUME_ACTIVE)) { 5366d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent mSafeMediaVolumeState = SAFE_MEDIA_VOLUME_INACTIVE; 5367aa5ee4d65f8788e2a0afcd198367450853fd72acJohn Spurlock mMusicActiveMs = 1; // nonzero = confirmed 5368aa5ee4d65f8788e2a0afcd198367450853fd72acJohn Spurlock saveMusicActiveMs(); 5369d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent sendMsg(mAudioHandler, 5370d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent MSG_CHECK_MUSIC_ACTIVE, 5371d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent SENDMSG_REPLACE, 5372d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent 0, 5373d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent 0, 5374d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent null, 5375d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent MUSIC_ACTIVE_POLL_PERIOD_MS); 5376d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent } 5377c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent } 5378c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent } 5379c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent } 5380c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent 5381c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent private void enforceSafeMediaVolume() { 5382c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent VolumeStreamState streamState = mStreamStates[AudioSystem.STREAM_MUSIC]; 5383c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent int devices = mSafeMediaVolumeDevices; 5384c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent int i = 0; 5385c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent 5386c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent while (devices != 0) { 5387c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent int device = 1 << i++; 5388c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent if ((device & devices) == 0) { 5389c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent continue; 5390c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent } 539142b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent int index = streamState.getIndex(device); 5392c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent if (index > mSafeMediaVolumeIndex) { 539342b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent streamState.setIndex(mSafeMediaVolumeIndex, device); 539442b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent sendMsg(mAudioHandler, 539542b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent MSG_SET_DEVICE_VOLUME, 539642b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent SENDMSG_QUEUE, 539742b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent device, 539842b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent 0, 539942b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent streamState, 540042b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent 0); 5401c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent } 5402c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent devices &= ~device; 5403c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent } 5404c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent } 5405c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent 5406c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent private boolean checkSafeMediaVolume(int streamType, int index, int device) { 5407d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent synchronized (mSafeMediaVolumeState) { 5408d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent if ((mSafeMediaVolumeState == SAFE_MEDIA_VOLUME_ACTIVE) && 5409c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent (mStreamVolumeAlias[streamType] == AudioSystem.STREAM_MUSIC) && 5410c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent ((device & mSafeMediaVolumeDevices) != 0) && 5411c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent (index > mSafeMediaVolumeIndex)) { 5412c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent return false; 5413c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent } 5414c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent return true; 5415c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent } 5416c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent } 5417c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent 54183346a802087f621c6441bc512dfcc17b07143fc6John Spurlock @Override 5419c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent public void disableSafeMediaVolume() { 54203346a802087f621c6441bc512dfcc17b07143fc6John Spurlock enforceSelfOrSystemUI("disable the safe media volume"); 5421d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent synchronized (mSafeMediaVolumeState) { 5422c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent setSafeMediaVolumeEnabled(false); 5423fde16d5879ea88a971004c984093409468b6139cEric Laurent if (mPendingVolumeCommand != null) { 5424fde16d5879ea88a971004c984093409468b6139cEric Laurent onSetStreamVolume(mPendingVolumeCommand.mStreamType, 5425fde16d5879ea88a971004c984093409468b6139cEric Laurent mPendingVolumeCommand.mIndex, 5426fde16d5879ea88a971004c984093409468b6139cEric Laurent mPendingVolumeCommand.mFlags, 5427fde16d5879ea88a971004c984093409468b6139cEric Laurent mPendingVolumeCommand.mDevice); 5428fde16d5879ea88a971004c984093409468b6139cEric Laurent mPendingVolumeCommand = null; 5429fde16d5879ea88a971004c984093409468b6139cEric Laurent } 5430c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent } 5431c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent } 5432c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent 543341d974631c5f525da49c88d34cecedd5a4cfeda8Jungshik Jang //========================================================================================== 543441d974631c5f525da49c88d34cecedd5a4cfeda8Jungshik Jang // Hdmi Cec system audio mode. 543541d974631c5f525da49c88d34cecedd5a4cfeda8Jungshik Jang // If Hdmi Cec's system audio mode is on, audio service should notify volume change 543641d974631c5f525da49c88d34cecedd5a4cfeda8Jungshik Jang // to HdmiControlService so that audio recevier can handle volume change. 543741d974631c5f525da49c88d34cecedd5a4cfeda8Jungshik Jang //========================================================================================== 543841d974631c5f525da49c88d34cecedd5a4cfeda8Jungshik Jang 5439212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent private class MyDisplayStatusCallback implements HdmiPlaybackClient.DisplayStatusCallback { 5440212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent public void onComplete(int status) { 5441212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent if (mHdmiManager != null) { 5442212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent synchronized (mHdmiManager) { 5443212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent mHdmiCecSink = (status != HdmiControlManager.POWER_STATUS_UNKNOWN); 5444212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent // Television devices without CEC service apply software volume on HDMI output 5445212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent if (isPlatformTelevision() && !mHdmiCecSink) { 5446212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent mFixedVolumeDevices &= ~AudioSystem.DEVICE_OUT_HDMI; 5447212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent } 5448212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent checkAllFixedVolumeDevices(); 5449212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent } 5450212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent } 5451212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent } 5452212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent }; 5453212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent 545441d974631c5f525da49c88d34cecedd5a4cfeda8Jungshik Jang // If HDMI-CEC system audio is supported 545541d974631c5f525da49c88d34cecedd5a4cfeda8Jungshik Jang private boolean mHdmiSystemAudioSupported = false; 545641d974631c5f525da49c88d34cecedd5a4cfeda8Jungshik Jang // Set only when device is tv. 545741d974631c5f525da49c88d34cecedd5a4cfeda8Jungshik Jang private HdmiTvClient mHdmiTvClient; 54580b03f9909be438f45b32ce2a6a2c2c5208a82cc9Eric Laurent // true if the device has system feature PackageManager.FEATURE_LEANBACK. 5459212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent // cached HdmiControlManager interface 5460212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent private HdmiControlManager mHdmiManager; 5461212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent // Set only when device is a set-top box. 5462212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent private HdmiPlaybackClient mHdmiPlaybackClient; 5463212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent // true if we are a set-top box, an HDMI sink is connected and it supports CEC. 5464212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent private boolean mHdmiCecSink; 5465212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent 5466212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent private MyDisplayStatusCallback mHdmiDisplayStatusCallback = new MyDisplayStatusCallback(); 546741d974631c5f525da49c88d34cecedd5a4cfeda8Jungshik Jang 546841d974631c5f525da49c88d34cecedd5a4cfeda8Jungshik Jang @Override 546912307ca810e8100981b2b60e3f2c6a7e451b9774Jungshik Jang public int setHdmiSystemAudioSupported(boolean on) { 5470212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent int device = AudioSystem.DEVICE_NONE; 5471212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent if (mHdmiManager != null) { 5472212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent synchronized (mHdmiManager) { 5473212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent if (mHdmiTvClient == null) { 5474212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent Log.w(TAG, "Only Hdmi-Cec enabled TV device supports system audio mode."); 5475212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent return device; 5476212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent } 547741d974631c5f525da49c88d34cecedd5a4cfeda8Jungshik Jang 5478212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent synchronized (mHdmiTvClient) { 5479212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent if (mHdmiSystemAudioSupported != on) { 5480212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent mHdmiSystemAudioSupported = on; 5481212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent AudioSystem.setForceUse(AudioSystem.FOR_HDMI_SYSTEM_AUDIO, 5482212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent on ? AudioSystem.FORCE_HDMI_SYSTEM_AUDIO_ENFORCED : 5483212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent AudioSystem.FORCE_NONE); 5484212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent } 5485212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent device = AudioSystem.getDevicesForStream(AudioSystem.STREAM_MUSIC); 5486212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent } 54876f34f5ab8ab1b1db7887e5405d8b0031e105ab05Jungshik Jang } 54886f34f5ab8ab1b1db7887e5405d8b0031e105ab05Jungshik Jang } 5489212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent return device; 54906f34f5ab8ab1b1db7887e5405d8b0031e105ab05Jungshik Jang } 54916f34f5ab8ab1b1db7887e5405d8b0031e105ab05Jungshik Jang 5492e7d6d97f0d95b9e8982b0d4d9f5e8ce688291940Terry Heo @Override 5493e7d6d97f0d95b9e8982b0d4d9f5e8ce688291940Terry Heo public boolean isHdmiSystemAudioSupported() { 5494e7d6d97f0d95b9e8982b0d4d9f5e8ce688291940Terry Heo return mHdmiSystemAudioSupported; 5495e7d6d97f0d95b9e8982b0d4d9f5e8ce688291940Terry Heo } 5496e7d6d97f0d95b9e8982b0d4d9f5e8ce688291940Terry Heo 5497dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent //========================================================================================== 5498873cc45da2463a11182fe94a2565364d7e1709bbJean-Michel Trivi // Accessibility: taking touch exploration into account for selecting the default 5499873cc45da2463a11182fe94a2565364d7e1709bbJean-Michel Trivi // stream override timeout when adjusting volume 5500873cc45da2463a11182fe94a2565364d7e1709bbJean-Michel Trivi //========================================================================================== 5501873cc45da2463a11182fe94a2565364d7e1709bbJean-Michel Trivi private static class StreamOverride 5502873cc45da2463a11182fe94a2565364d7e1709bbJean-Michel Trivi implements AccessibilityManager.TouchExplorationStateChangeListener { 5503873cc45da2463a11182fe94a2565364d7e1709bbJean-Michel Trivi 5504873cc45da2463a11182fe94a2565364d7e1709bbJean-Michel Trivi // AudioService.getActiveStreamType() will return: 5505873cc45da2463a11182fe94a2565364d7e1709bbJean-Michel Trivi // - STREAM_NOTIFICATION on tablets during this period after a notification stopped 5506873cc45da2463a11182fe94a2565364d7e1709bbJean-Michel Trivi // - STREAM_MUSIC on phones during this period after music or talkback/voice search prompt 5507873cc45da2463a11182fe94a2565364d7e1709bbJean-Michel Trivi // stopped 5508873cc45da2463a11182fe94a2565364d7e1709bbJean-Michel Trivi private static final int DEFAULT_STREAM_TYPE_OVERRIDE_DELAY_MS = 5000; 5509873cc45da2463a11182fe94a2565364d7e1709bbJean-Michel Trivi private static final int TOUCH_EXPLORE_STREAM_TYPE_OVERRIDE_DELAY_MS = 1000; 5510873cc45da2463a11182fe94a2565364d7e1709bbJean-Michel Trivi 5511873cc45da2463a11182fe94a2565364d7e1709bbJean-Michel Trivi static int sDelayMs; 5512873cc45da2463a11182fe94a2565364d7e1709bbJean-Michel Trivi 5513873cc45da2463a11182fe94a2565364d7e1709bbJean-Michel Trivi static void init(Context ctxt) { 5514873cc45da2463a11182fe94a2565364d7e1709bbJean-Michel Trivi AccessibilityManager accessibilityManager = 5515873cc45da2463a11182fe94a2565364d7e1709bbJean-Michel Trivi (AccessibilityManager) ctxt.getSystemService(Context.ACCESSIBILITY_SERVICE); 5516873cc45da2463a11182fe94a2565364d7e1709bbJean-Michel Trivi updateDefaultStreamOverrideDelay( 5517873cc45da2463a11182fe94a2565364d7e1709bbJean-Michel Trivi accessibilityManager.isTouchExplorationEnabled()); 5518873cc45da2463a11182fe94a2565364d7e1709bbJean-Michel Trivi accessibilityManager.addTouchExplorationStateChangeListener( 5519873cc45da2463a11182fe94a2565364d7e1709bbJean-Michel Trivi new StreamOverride()); 5520873cc45da2463a11182fe94a2565364d7e1709bbJean-Michel Trivi } 5521873cc45da2463a11182fe94a2565364d7e1709bbJean-Michel Trivi 5522873cc45da2463a11182fe94a2565364d7e1709bbJean-Michel Trivi @Override 5523873cc45da2463a11182fe94a2565364d7e1709bbJean-Michel Trivi public void onTouchExplorationStateChanged(boolean enabled) { 5524873cc45da2463a11182fe94a2565364d7e1709bbJean-Michel Trivi updateDefaultStreamOverrideDelay(enabled); 5525873cc45da2463a11182fe94a2565364d7e1709bbJean-Michel Trivi } 5526873cc45da2463a11182fe94a2565364d7e1709bbJean-Michel Trivi 5527873cc45da2463a11182fe94a2565364d7e1709bbJean-Michel Trivi private static void updateDefaultStreamOverrideDelay(boolean touchExploreEnabled) { 5528873cc45da2463a11182fe94a2565364d7e1709bbJean-Michel Trivi if (touchExploreEnabled) { 5529873cc45da2463a11182fe94a2565364d7e1709bbJean-Michel Trivi sDelayMs = TOUCH_EXPLORE_STREAM_TYPE_OVERRIDE_DELAY_MS; 5530873cc45da2463a11182fe94a2565364d7e1709bbJean-Michel Trivi } else { 5531873cc45da2463a11182fe94a2565364d7e1709bbJean-Michel Trivi sDelayMs = DEFAULT_STREAM_TYPE_OVERRIDE_DELAY_MS; 5532873cc45da2463a11182fe94a2565364d7e1709bbJean-Michel Trivi } 5533873cc45da2463a11182fe94a2565364d7e1709bbJean-Michel Trivi if (DEBUG_VOL) Log.d(TAG, "Touch exploration enabled=" + touchExploreEnabled 5534873cc45da2463a11182fe94a2565364d7e1709bbJean-Michel Trivi + " stream override delay is now " + sDelayMs + " ms"); 5535873cc45da2463a11182fe94a2565364d7e1709bbJean-Michel Trivi } 5536873cc45da2463a11182fe94a2565364d7e1709bbJean-Michel Trivi } 5537873cc45da2463a11182fe94a2565364d7e1709bbJean-Michel Trivi 5538873cc45da2463a11182fe94a2565364d7e1709bbJean-Michel Trivi //========================================================================================== 5539dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent // Camera shutter sound policy. 5540dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent // config_camera_sound_forced configuration option in config.xml defines if the camera shutter 5541dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent // sound is forced (sound even if the device is in silent mode) or not. This option is false by 5542dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent // default and can be overridden by country specific overlay in values-mccXXX/config.xml. 5543dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent //========================================================================================== 5544dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent 5545dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent // cached value of com.android.internal.R.bool.config_camera_sound_forced 5546dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent private Boolean mCameraSoundForced; 5547dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent 5548dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent // called by android.hardware.Camera to populate CameraInfo.canDisableShutterSound 5549dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent public boolean isCameraSoundForced() { 5550dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent synchronized (mCameraSoundForced) { 5551dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent return mCameraSoundForced; 5552dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent } 5553dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent } 5554dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent 5555dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent private static final String[] RINGER_MODE_NAMES = new String[] { 5556dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent "SILENT", 5557dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent "VIBRATE", 5558dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent "NORMAL" 5559dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent }; 5560dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent 5561dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent private void dumpRingerMode(PrintWriter pw) { 5562dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent pw.println("\nRinger mode: "); 5563661f2cf45860d2e10924e6b69966a9afe255f28bJohn Spurlock pw.println("- mode (internal) = " + RINGER_MODE_NAMES[mRingerMode]); 5564661f2cf45860d2e10924e6b69966a9afe255f28bJohn Spurlock pw.println("- mode (external) = " + RINGER_MODE_NAMES[mRingerModeExternal]); 5565dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent pw.print("- ringer mode affected streams = 0x"); 5566dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent pw.println(Integer.toHexString(mRingerModeAffectedStreams)); 5567dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent pw.print("- ringer mode muted streams = 0x"); 5568dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent pw.println(Integer.toHexString(mRingerModeMutedStreams)); 5569661f2cf45860d2e10924e6b69966a9afe255f28bJohn Spurlock pw.print("- delegate = "); pw.println(mRingerModeDelegate); 5570dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent } 5571dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent 5572632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn @Override 5573d5176cfe6eae954e9cef1e2ec17859a5089e1330Jean-Michel Trivi protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 5574eb4cc492c93ab9635dde78b958a834120412e72aJeff Sharkey mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DUMP, TAG); 5575eb4cc492c93ab9635dde78b958a834120412e72aJeff Sharkey 5576fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi mMediaFocusControl.dump(pw); 5577bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent dumpStreamStates(pw); 5578dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent dumpRingerMode(pw); 5579632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn pw.println("\nAudio routes:"); 5580632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn pw.print(" mMainType=0x"); pw.println(Integer.toHexString(mCurAudioRoutes.mMainType)); 5581632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn pw.print(" mBluetoothName="); pw.println(mCurAudioRoutes.mBluetoothName); 5582351346092acdfbfcc1d9ebf98d539d2a1196c5e8John Spurlock 5583351346092acdfbfcc1d9ebf98d539d2a1196c5e8John Spurlock pw.println("\nOther state:"); 55843346a802087f621c6441bc512dfcc17b07143fc6John Spurlock pw.print(" mVolumeController="); pw.println(mVolumeController); 5585351346092acdfbfcc1d9ebf98d539d2a1196c5e8John Spurlock pw.print(" mSafeMediaVolumeState="); 5586351346092acdfbfcc1d9ebf98d539d2a1196c5e8John Spurlock pw.println(safeMediaVolumeStateToString(mSafeMediaVolumeState)); 5587351346092acdfbfcc1d9ebf98d539d2a1196c5e8John Spurlock pw.print(" mSafeMediaVolumeIndex="); pw.println(mSafeMediaVolumeIndex); 5588351346092acdfbfcc1d9ebf98d539d2a1196c5e8John Spurlock pw.print(" mPendingVolumeCommand="); pw.println(mPendingVolumeCommand); 5589351346092acdfbfcc1d9ebf98d539d2a1196c5e8John Spurlock pw.print(" mMusicActiveMs="); pw.println(mMusicActiveMs); 5590aa5ee4d65f8788e2a0afcd198367450853fd72acJohn Spurlock pw.print(" mMcc="); pw.println(mMcc); 5591661f2cf45860d2e10924e6b69966a9afe255f28bJohn Spurlock pw.print(" mHasVibrator="); pw.println(mHasVibrator); 55921b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi 55931b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi dumpAudioPolicies(pw); 5594351346092acdfbfcc1d9ebf98d539d2a1196c5e8John Spurlock } 5595351346092acdfbfcc1d9ebf98d539d2a1196c5e8John Spurlock 5596351346092acdfbfcc1d9ebf98d539d2a1196c5e8John Spurlock private static String safeMediaVolumeStateToString(Integer state) { 5597351346092acdfbfcc1d9ebf98d539d2a1196c5e8John Spurlock switch(state) { 5598351346092acdfbfcc1d9ebf98d539d2a1196c5e8John Spurlock case SAFE_MEDIA_VOLUME_NOT_CONFIGURED: return "SAFE_MEDIA_VOLUME_NOT_CONFIGURED"; 5599351346092acdfbfcc1d9ebf98d539d2a1196c5e8John Spurlock case SAFE_MEDIA_VOLUME_DISABLED: return "SAFE_MEDIA_VOLUME_DISABLED"; 5600351346092acdfbfcc1d9ebf98d539d2a1196c5e8John Spurlock case SAFE_MEDIA_VOLUME_INACTIVE: return "SAFE_MEDIA_VOLUME_INACTIVE"; 5601351346092acdfbfcc1d9ebf98d539d2a1196c5e8John Spurlock case SAFE_MEDIA_VOLUME_ACTIVE: return "SAFE_MEDIA_VOLUME_ACTIVE"; 5602351346092acdfbfcc1d9ebf98d539d2a1196c5e8John Spurlock } 5603351346092acdfbfcc1d9ebf98d539d2a1196c5e8John Spurlock return null; 5604d5176cfe6eae954e9cef1e2ec17859a5089e1330Jean-Michel Trivi } 5605fd116ad1ab02f6060a0b2201f018317fa32e28b4Glenn Kasten 5606fd116ad1ab02f6060a0b2201f018317fa32e28b4Glenn Kasten // Inform AudioFlinger of our device's low RAM attribute 5607fd116ad1ab02f6060a0b2201f018317fa32e28b4Glenn Kasten private static void readAndSetLowRamDevice() 5608fd116ad1ab02f6060a0b2201f018317fa32e28b4Glenn Kasten { 5609fd116ad1ab02f6060a0b2201f018317fa32e28b4Glenn Kasten int status = AudioSystem.setLowRamDevice(ActivityManager.isLowRamDeviceStatic()); 5610fd116ad1ab02f6060a0b2201f018317fa32e28b4Glenn Kasten if (status != 0) { 5611fd116ad1ab02f6060a0b2201f018317fa32e28b4Glenn Kasten Log.w(TAG, "AudioFlinger informed of device's low RAM attribute; status " + status); 5612fd116ad1ab02f6060a0b2201f018317fa32e28b4Glenn Kasten } 5613fd116ad1ab02f6060a0b2201f018317fa32e28b4Glenn Kasten } 56143346a802087f621c6441bc512dfcc17b07143fc6John Spurlock 56153346a802087f621c6441bc512dfcc17b07143fc6John Spurlock private void enforceSelfOrSystemUI(String action) { 56163346a802087f621c6441bc512dfcc17b07143fc6John Spurlock mContext.enforceCallingOrSelfPermission(android.Manifest.permission.STATUS_BAR_SERVICE, 56173346a802087f621c6441bc512dfcc17b07143fc6John Spurlock "Only SystemUI can " + action); 56183346a802087f621c6441bc512dfcc17b07143fc6John Spurlock } 56193346a802087f621c6441bc512dfcc17b07143fc6John Spurlock 56203346a802087f621c6441bc512dfcc17b07143fc6John Spurlock @Override 56213346a802087f621c6441bc512dfcc17b07143fc6John Spurlock public void setVolumeController(final IVolumeController controller) { 56223346a802087f621c6441bc512dfcc17b07143fc6John Spurlock enforceSelfOrSystemUI("set the volume controller"); 56233346a802087f621c6441bc512dfcc17b07143fc6John Spurlock 56243346a802087f621c6441bc512dfcc17b07143fc6John Spurlock // return early if things are not actually changing 56253346a802087f621c6441bc512dfcc17b07143fc6John Spurlock if (mVolumeController.isSameBinder(controller)) { 56263346a802087f621c6441bc512dfcc17b07143fc6John Spurlock return; 56273346a802087f621c6441bc512dfcc17b07143fc6John Spurlock } 56283346a802087f621c6441bc512dfcc17b07143fc6John Spurlock 56293346a802087f621c6441bc512dfcc17b07143fc6John Spurlock // dismiss the old volume controller 56303346a802087f621c6441bc512dfcc17b07143fc6John Spurlock mVolumeController.postDismiss(); 56313346a802087f621c6441bc512dfcc17b07143fc6John Spurlock if (controller != null) { 56323346a802087f621c6441bc512dfcc17b07143fc6John Spurlock // we are about to register a new controller, listen for its death 56333346a802087f621c6441bc512dfcc17b07143fc6John Spurlock try { 56343346a802087f621c6441bc512dfcc17b07143fc6John Spurlock controller.asBinder().linkToDeath(new DeathRecipient() { 56353346a802087f621c6441bc512dfcc17b07143fc6John Spurlock @Override 56363346a802087f621c6441bc512dfcc17b07143fc6John Spurlock public void binderDied() { 56373346a802087f621c6441bc512dfcc17b07143fc6John Spurlock if (mVolumeController.isSameBinder(controller)) { 56383346a802087f621c6441bc512dfcc17b07143fc6John Spurlock Log.w(TAG, "Current remote volume controller died, unregistering"); 56393346a802087f621c6441bc512dfcc17b07143fc6John Spurlock setVolumeController(null); 56403346a802087f621c6441bc512dfcc17b07143fc6John Spurlock } 56413346a802087f621c6441bc512dfcc17b07143fc6John Spurlock } 56423346a802087f621c6441bc512dfcc17b07143fc6John Spurlock }, 0); 56433346a802087f621c6441bc512dfcc17b07143fc6John Spurlock } catch (RemoteException e) { 56443346a802087f621c6441bc512dfcc17b07143fc6John Spurlock // noop 56453346a802087f621c6441bc512dfcc17b07143fc6John Spurlock } 56463346a802087f621c6441bc512dfcc17b07143fc6John Spurlock } 56473346a802087f621c6441bc512dfcc17b07143fc6John Spurlock mVolumeController.setController(controller); 564833f4e04e32fac42f158733d6a731e50490fa9951John Spurlock if (DEBUG_VOL) Log.d(TAG, "Volume controller: " + mVolumeController); 564933f4e04e32fac42f158733d6a731e50490fa9951John Spurlock } 565033f4e04e32fac42f158733d6a731e50490fa9951John Spurlock 565133f4e04e32fac42f158733d6a731e50490fa9951John Spurlock @Override 565233f4e04e32fac42f158733d6a731e50490fa9951John Spurlock public void notifyVolumeControllerVisible(final IVolumeController controller, boolean visible) { 565333f4e04e32fac42f158733d6a731e50490fa9951John Spurlock enforceSelfOrSystemUI("notify about volume controller visibility"); 565433f4e04e32fac42f158733d6a731e50490fa9951John Spurlock 565533f4e04e32fac42f158733d6a731e50490fa9951John Spurlock // return early if the controller is not current 565633f4e04e32fac42f158733d6a731e50490fa9951John Spurlock if (!mVolumeController.isSameBinder(controller)) { 565733f4e04e32fac42f158733d6a731e50490fa9951John Spurlock return; 565833f4e04e32fac42f158733d6a731e50490fa9951John Spurlock } 565933f4e04e32fac42f158733d6a731e50490fa9951John Spurlock 566033f4e04e32fac42f158733d6a731e50490fa9951John Spurlock mVolumeController.setVisible(visible); 566133f4e04e32fac42f158733d6a731e50490fa9951John Spurlock if (DEBUG_VOL) Log.d(TAG, "Volume controller visible: " + visible); 56623346a802087f621c6441bc512dfcc17b07143fc6John Spurlock } 5663d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik 5664d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik public static class VolumeController { 5665d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik private static final String TAG = "VolumeController"; 5666d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik 5667d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik private IVolumeController mController; 566833f4e04e32fac42f158733d6a731e50490fa9951John Spurlock private boolean mVisible; 566933f4e04e32fac42f158733d6a731e50490fa9951John Spurlock private long mNextLongPress; 567033f4e04e32fac42f158733d6a731e50490fa9951John Spurlock private int mLongPressTimeout; 5671d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik 5672d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik public void setController(IVolumeController controller) { 5673d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik mController = controller; 567433f4e04e32fac42f158733d6a731e50490fa9951John Spurlock mVisible = false; 567533f4e04e32fac42f158733d6a731e50490fa9951John Spurlock } 567633f4e04e32fac42f158733d6a731e50490fa9951John Spurlock 567733f4e04e32fac42f158733d6a731e50490fa9951John Spurlock public void loadSettings(ContentResolver cr) { 567833f4e04e32fac42f158733d6a731e50490fa9951John Spurlock mLongPressTimeout = Settings.Secure.getIntForUser(cr, 567933f4e04e32fac42f158733d6a731e50490fa9951John Spurlock Settings.Secure.LONG_PRESS_TIMEOUT, 500, UserHandle.USER_CURRENT); 568033f4e04e32fac42f158733d6a731e50490fa9951John Spurlock } 568133f4e04e32fac42f158733d6a731e50490fa9951John Spurlock 568233f4e04e32fac42f158733d6a731e50490fa9951John Spurlock public boolean suppressAdjustment(int resolvedStream, int flags) { 568333f4e04e32fac42f158733d6a731e50490fa9951John Spurlock boolean suppress = false; 568433f4e04e32fac42f158733d6a731e50490fa9951John Spurlock if (resolvedStream == AudioSystem.STREAM_RING && mController != null) { 568533f4e04e32fac42f158733d6a731e50490fa9951John Spurlock final long now = SystemClock.uptimeMillis(); 568633f4e04e32fac42f158733d6a731e50490fa9951John Spurlock if ((flags & AudioManager.FLAG_SHOW_UI) != 0 && !mVisible) { 568733f4e04e32fac42f158733d6a731e50490fa9951John Spurlock // ui will become visible 568833f4e04e32fac42f158733d6a731e50490fa9951John Spurlock if (mNextLongPress < now) { 568933f4e04e32fac42f158733d6a731e50490fa9951John Spurlock mNextLongPress = now + mLongPressTimeout; 569033f4e04e32fac42f158733d6a731e50490fa9951John Spurlock } 569133f4e04e32fac42f158733d6a731e50490fa9951John Spurlock suppress = true; 569233f4e04e32fac42f158733d6a731e50490fa9951John Spurlock } else if (mNextLongPress > 0) { // in a long-press 569333f4e04e32fac42f158733d6a731e50490fa9951John Spurlock if (now > mNextLongPress) { 569433f4e04e32fac42f158733d6a731e50490fa9951John Spurlock // long press triggered, no more suppression 569533f4e04e32fac42f158733d6a731e50490fa9951John Spurlock mNextLongPress = 0; 569633f4e04e32fac42f158733d6a731e50490fa9951John Spurlock } else { 569733f4e04e32fac42f158733d6a731e50490fa9951John Spurlock // keep suppressing until the long press triggers 569833f4e04e32fac42f158733d6a731e50490fa9951John Spurlock suppress = true; 569933f4e04e32fac42f158733d6a731e50490fa9951John Spurlock } 570033f4e04e32fac42f158733d6a731e50490fa9951John Spurlock } 570133f4e04e32fac42f158733d6a731e50490fa9951John Spurlock } 570233f4e04e32fac42f158733d6a731e50490fa9951John Spurlock return suppress; 570333f4e04e32fac42f158733d6a731e50490fa9951John Spurlock } 570433f4e04e32fac42f158733d6a731e50490fa9951John Spurlock 570533f4e04e32fac42f158733d6a731e50490fa9951John Spurlock public void setVisible(boolean visible) { 570633f4e04e32fac42f158733d6a731e50490fa9951John Spurlock mVisible = visible; 5707d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik } 5708d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik 5709d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik public boolean isSameBinder(IVolumeController controller) { 5710d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik return Objects.equals(asBinder(), binder(controller)); 5711d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik } 5712d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik 5713d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik public IBinder asBinder() { 5714d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik return binder(mController); 5715d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik } 5716d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik 5717d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik private static IBinder binder(IVolumeController controller) { 5718d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik return controller == null ? null : controller.asBinder(); 5719d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik } 5720d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik 5721d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik @Override 5722d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik public String toString() { 572333f4e04e32fac42f158733d6a731e50490fa9951John Spurlock return "VolumeController(" + asBinder() + ",mVisible=" + mVisible + ")"; 5724d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik } 5725d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik 5726d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik public void postDisplaySafeVolumeWarning(int flags) { 5727d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik if (mController == null) 5728d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik return; 5729d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik try { 5730d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik mController.displaySafeVolumeWarning(flags); 5731d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik } catch (RemoteException e) { 5732d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik Log.w(TAG, "Error calling displaySafeVolumeWarning", e); 5733d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik } 5734d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik } 5735d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik 5736d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik public void postVolumeChanged(int streamType, int flags) { 5737d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik if (mController == null) 5738d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik return; 5739d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik try { 5740d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik mController.volumeChanged(streamType, flags); 5741d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik } catch (RemoteException e) { 5742d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik Log.w(TAG, "Error calling volumeChanged", e); 5743d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik } 5744d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik } 5745d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik 5746d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik public void postMasterVolumeChanged(int flags) { 5747d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik if (mController == null) 5748d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik return; 5749d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik try { 5750d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik mController.masterVolumeChanged(flags); 5751d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik } catch (RemoteException e) { 5752d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik Log.w(TAG, "Error calling masterVolumeChanged", e); 5753d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik } 5754d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik } 5755d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik 5756d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik public void postMasterMuteChanged(int flags) { 5757d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik if (mController == null) 5758d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik return; 5759d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik try { 5760d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik mController.masterMuteChanged(flags); 5761d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik } catch (RemoteException e) { 5762d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik Log.w(TAG, "Error calling masterMuteChanged", e); 5763d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik } 5764d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik } 5765d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik 5766d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik public void setLayoutDirection(int layoutDirection) { 5767d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik if (mController == null) 5768d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik return; 5769d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik try { 5770d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik mController.setLayoutDirection(layoutDirection); 5771d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik } catch (RemoteException e) { 5772d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik Log.w(TAG, "Error calling setLayoutDirection", e); 5773d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik } 5774d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik } 5775d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik 5776d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik public void postDismiss() { 5777d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik if (mController == null) 5778d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik return; 5779d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik try { 5780d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik mController.dismiss(); 5781d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik } catch (RemoteException e) { 5782d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik Log.w(TAG, "Error calling dismiss", e); 5783d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik } 5784661f2cf45860d2e10924e6b69966a9afe255f28bJohn Spurlock } 5785d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik } 5786a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi 57870dac35af2c6aa42bcd181981b041747cfd1afa5fRoboErik /** 57880dac35af2c6aa42bcd181981b041747cfd1afa5fRoboErik * Interface for system components to get some extra functionality through 57890dac35af2c6aa42bcd181981b041747cfd1afa5fRoboErik * LocalServices. 57900dac35af2c6aa42bcd181981b041747cfd1afa5fRoboErik */ 57910dac35af2c6aa42bcd181981b041747cfd1afa5fRoboErik final class AudioServiceInternal extends AudioManagerInternal { 5792661f2cf45860d2e10924e6b69966a9afe255f28bJohn Spurlock @Override 5793661f2cf45860d2e10924e6b69966a9afe255f28bJohn Spurlock public void setRingerModeDelegate(RingerModeDelegate delegate) { 5794661f2cf45860d2e10924e6b69966a9afe255f28bJohn Spurlock mRingerModeDelegate = delegate; 5795661f2cf45860d2e10924e6b69966a9afe255f28bJohn Spurlock if (mRingerModeDelegate != null) { 5796661f2cf45860d2e10924e6b69966a9afe255f28bJohn Spurlock setRingerModeInternal(getRingerModeInternal(), TAG + ".setRingerModeDelegate"); 5797661f2cf45860d2e10924e6b69966a9afe255f28bJohn Spurlock } 5798661f2cf45860d2e10924e6b69966a9afe255f28bJohn Spurlock } 5799272e161c1a200900cb10b5b0cdab8ae1f123cabdRoboErik 5800272e161c1a200900cb10b5b0cdab8ae1f123cabdRoboErik @Override 5801272e161c1a200900cb10b5b0cdab8ae1f123cabdRoboErik public void adjustSuggestedStreamVolumeForUid(int streamType, int direction, int flags, 5802272e161c1a200900cb10b5b0cdab8ae1f123cabdRoboErik String callingPackage, int uid) { 5803272e161c1a200900cb10b5b0cdab8ae1f123cabdRoboErik // direction and stream type swap here because the public 5804272e161c1a200900cb10b5b0cdab8ae1f123cabdRoboErik // adjustSuggested has a different order than the other methods. 5805272e161c1a200900cb10b5b0cdab8ae1f123cabdRoboErik adjustSuggestedStreamVolume(direction, streamType, flags, callingPackage, uid); 5806272e161c1a200900cb10b5b0cdab8ae1f123cabdRoboErik } 5807272e161c1a200900cb10b5b0cdab8ae1f123cabdRoboErik 58080dac35af2c6aa42bcd181981b041747cfd1afa5fRoboErik @Override 58090dac35af2c6aa42bcd181981b041747cfd1afa5fRoboErik public void adjustStreamVolumeForUid(int streamType, int direction, int flags, 58100dac35af2c6aa42bcd181981b041747cfd1afa5fRoboErik String callingPackage, int uid) { 58110dac35af2c6aa42bcd181981b041747cfd1afa5fRoboErik adjustStreamVolume(streamType, direction, flags, callingPackage, uid); 58120dac35af2c6aa42bcd181981b041747cfd1afa5fRoboErik } 58130dac35af2c6aa42bcd181981b041747cfd1afa5fRoboErik 58140dac35af2c6aa42bcd181981b041747cfd1afa5fRoboErik @Override 58150dac35af2c6aa42bcd181981b041747cfd1afa5fRoboErik public void setStreamVolumeForUid(int streamType, int direction, int flags, 58160dac35af2c6aa42bcd181981b041747cfd1afa5fRoboErik String callingPackage, int uid) { 58170dac35af2c6aa42bcd181981b041747cfd1afa5fRoboErik setStreamVolume(streamType, direction, flags, callingPackage, uid); 58180dac35af2c6aa42bcd181981b041747cfd1afa5fRoboErik } 5819519c7744b522aa07e12bc3244ac3de14aa2a4ad0RoboErik 5820519c7744b522aa07e12bc3244ac3de14aa2a4ad0RoboErik @Override 5821519c7744b522aa07e12bc3244ac3de14aa2a4ad0RoboErik public void adjustMasterVolumeForUid(int steps, int flags, String callingPackage, 5822519c7744b522aa07e12bc3244ac3de14aa2a4ad0RoboErik int uid) { 5823519c7744b522aa07e12bc3244ac3de14aa2a4ad0RoboErik adjustMasterVolume(steps, flags, callingPackage, uid); 5824519c7744b522aa07e12bc3244ac3de14aa2a4ad0RoboErik } 5825661f2cf45860d2e10924e6b69966a9afe255f28bJohn Spurlock 5826661f2cf45860d2e10924e6b69966a9afe255f28bJohn Spurlock @Override 5827661f2cf45860d2e10924e6b69966a9afe255f28bJohn Spurlock public int getRingerModeInternal() { 5828661f2cf45860d2e10924e6b69966a9afe255f28bJohn Spurlock return AudioService.this.getRingerModeInternal(); 5829661f2cf45860d2e10924e6b69966a9afe255f28bJohn Spurlock } 5830661f2cf45860d2e10924e6b69966a9afe255f28bJohn Spurlock 5831661f2cf45860d2e10924e6b69966a9afe255f28bJohn Spurlock @Override 5832661f2cf45860d2e10924e6b69966a9afe255f28bJohn Spurlock public void setRingerModeInternal(int ringerMode, String caller) { 5833661f2cf45860d2e10924e6b69966a9afe255f28bJohn Spurlock AudioService.this.setRingerModeInternal(ringerMode, caller); 5834661f2cf45860d2e10924e6b69966a9afe255f28bJohn Spurlock } 58357c82ced4fc5b66c09a19eed9a5499039530142fbRoboErik 58367c82ced4fc5b66c09a19eed9a5499039530142fbRoboErik @Override 58377c82ced4fc5b66c09a19eed9a5499039530142fbRoboErik public void setMasterMuteForUid(boolean state, int flags, String callingPackage, IBinder cb, 58387c82ced4fc5b66c09a19eed9a5499039530142fbRoboErik int uid) { 58397c82ced4fc5b66c09a19eed9a5499039530142fbRoboErik setMasterMuteInternal(state, flags, callingPackage, cb, uid); 58407c82ced4fc5b66c09a19eed9a5499039530142fbRoboErik } 58410dac35af2c6aa42bcd181981b041747cfd1afa5fRoboErik } 58420dac35af2c6aa42bcd181981b041747cfd1afa5fRoboErik 5843a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi //========================================================================================== 5844a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi // Audio policy management 5845a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi //========================================================================================== 58460212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi public String registerAudioPolicy(AudioPolicyConfig policyConfig, IAudioPolicyCallback pcb, 58470212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi boolean hasFocusListener) { 58480212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi if (DEBUG_AP) Log.d(TAG, "registerAudioPolicy for " + pcb.asBinder() 58490212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi + " with config:" + policyConfig); 58508fdb0d4defb6ee2ca8057d3442ead36b408b6c17Jean-Michel Trivi String regId = null; 58510212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi // error handling 5852a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi boolean hasPermissionForPolicy = 58530212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi (PackageManager.PERMISSION_GRANTED == mContext.checkCallingPermission( 5854a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi android.Manifest.permission.MODIFY_AUDIO_ROUTING)); 5855a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi if (!hasPermissionForPolicy) { 5856a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi Slog.w(TAG, "Can't register audio policy for pid " + Binder.getCallingPid() + " / uid " 5857a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi + Binder.getCallingUid() + ", need MODIFY_AUDIO_ROUTING"); 58588fdb0d4defb6ee2ca8057d3442ead36b408b6c17Jean-Michel Trivi return null; 5859a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi } 58600212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi 5861a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi synchronized (mAudioPolicies) { 5862a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi try { 58630212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi if (mAudioPolicies.containsKey(pcb.asBinder())) { 58641b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi Slog.e(TAG, "Cannot re-register policy"); 58651b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi return null; 58661b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi } 58670212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi AudioPolicyProxy app = new AudioPolicyProxy(policyConfig, pcb, hasFocusListener); 58680212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi pcb.asBinder().linkToDeath(app, 0/*flags*/); 58690212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi regId = app.getRegistrationId(); 58700212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi mAudioPolicies.put(pcb.asBinder(), app); 5871a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi } catch (RemoteException e) { 5872a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi // audio policy owner has already died! 58730212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi Slog.w(TAG, "Audio policy registration failed, could not link to " + pcb + 5874a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi " binder death", e); 58758fdb0d4defb6ee2ca8057d3442ead36b408b6c17Jean-Michel Trivi return null; 5876a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi } 5877a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi } 58788fdb0d4defb6ee2ca8057d3442ead36b408b6c17Jean-Michel Trivi return regId; 5879a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi } 58808fdb0d4defb6ee2ca8057d3442ead36b408b6c17Jean-Michel Trivi 58810212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi public void unregisterAudioPolicyAsync(IAudioPolicyCallback pcb) { 58820212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi if (DEBUG_AP) Log.d(TAG, "unregisterAudioPolicyAsync for " + pcb.asBinder()); 5883a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi synchronized (mAudioPolicies) { 58840212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi AudioPolicyProxy app = mAudioPolicies.remove(pcb.asBinder()); 5885a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi if (app == null) { 5886a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi Slog.w(TAG, "Trying to unregister unknown audio policy for pid " 5887a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi + Binder.getCallingPid() + " / uid " + Binder.getCallingUid()); 58881b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi return; 5889a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi } else { 58900212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi pcb.asBinder().unlinkToDeath(app, 0/*flags*/); 5891a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi } 58920212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi app.release(); 5893a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi } 58948fdb0d4defb6ee2ca8057d3442ead36b408b6c17Jean-Michel Trivi // TODO implement clearing mix attribute matching info in native audio policy 5895a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi } 5896a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi 58970212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi public int setFocusPropertiesForPolicy(int duckingBehavior, IAudioPolicyCallback pcb) { 58980212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi if (DEBUG_AP) Log.d(TAG, "setFocusPropertiesForPolicy() duck behavior=" + duckingBehavior 58990212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi + " policy " + pcb.asBinder()); 59000212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi // error handling 59010212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi boolean hasPermissionForPolicy = 59020212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi (PackageManager.PERMISSION_GRANTED == mContext.checkCallingPermission( 59030212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi android.Manifest.permission.MODIFY_AUDIO_ROUTING)); 59040212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi if (!hasPermissionForPolicy) { 59050212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi Slog.w(TAG, "Cannot change audio policy ducking handling for pid " + 59060212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi + Binder.getCallingPid() + " / uid " 59070212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi + Binder.getCallingUid() + ", need MODIFY_AUDIO_ROUTING"); 59080212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi return AudioManager.ERROR; 59090212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi } 59100212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi 59110212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi synchronized (mAudioPolicies) { 59120212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi if (!mAudioPolicies.containsKey(pcb.asBinder())) { 59130212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi Slog.e(TAG, "Cannot change audio policy focus properties, unregistered policy"); 59140212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi return AudioManager.ERROR; 59150212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi } 59160212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi final AudioPolicyProxy app = mAudioPolicies.get(pcb.asBinder()); 59170212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi if (duckingBehavior == AudioPolicy.FOCUS_POLICY_DUCKING_IN_POLICY) { 59180212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi // is there already one policy managing ducking? 59190212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi for(AudioPolicyProxy policy : mAudioPolicies.values()) { 59200212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi if (policy.mFocusDuckBehavior == AudioPolicy.FOCUS_POLICY_DUCKING_IN_POLICY) { 59210212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi Slog.e(TAG, "Cannot change audio policy ducking behavior, already handled"); 59220212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi return AudioManager.ERROR; 59230212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi } 59240212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi } 59250212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi } 59260212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi app.mFocusDuckBehavior = duckingBehavior; 59270212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi mMediaFocusControl.setDuckingInExtPolicyAvailable( 59280212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi duckingBehavior == AudioPolicy.FOCUS_POLICY_DUCKING_IN_POLICY); 59290212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi } 59300212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi return AudioManager.SUCCESS; 59310212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi } 59320212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi 59331b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi private void dumpAudioPolicies(PrintWriter pw) { 59341b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi pw.println("\nAudio policies:"); 59351b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi synchronized (mAudioPolicies) { 59361b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi for(AudioPolicyProxy policy : mAudioPolicies.values()) { 59371b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi pw.println(policy.toLogFriendlyString()); 59381b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi } 59391b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi } 59401b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi } 59411b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi 5942958876fe55ea0fdeb73c72240a2f2bab32833443Jean-Michel Trivi //====================== 5943958876fe55ea0fdeb73c72240a2f2bab32833443Jean-Michel Trivi // Audio policy proxy 5944958876fe55ea0fdeb73c72240a2f2bab32833443Jean-Michel Trivi //====================== 59458fdb0d4defb6ee2ca8057d3442ead36b408b6c17Jean-Michel Trivi /** 59461b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi * This internal class inherits from AudioPolicyConfig, each instance contains all the 59471b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi * mixes of an AudioPolicy and their configurations. 59488fdb0d4defb6ee2ca8057d3442ead36b408b6c17Jean-Michel Trivi */ 59498fdb0d4defb6ee2ca8057d3442ead36b408b6c17Jean-Michel Trivi public class AudioPolicyProxy extends AudioPolicyConfig implements IBinder.DeathRecipient { 5950a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi private static final String TAG = "AudioPolicyProxy"; 5951a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi AudioPolicyConfig mConfig; 59520212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi IAudioPolicyCallback mPolicyToken; 59530212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi boolean mHasFocusListener; 59540212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi /** 59550212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi * Audio focus ducking behavior for an audio policy. 59560212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi * This variable reflects the value that was successfully set in 59570212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi * {@link AudioService#setFocusPropertiesForPolicy(int, IAudioPolicyCallback)}. This 59580212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi * implies that a value of FOCUS_POLICY_DUCKING_IN_POLICY means the corresponding policy 59590212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi * is handling ducking for audio focus. 59600212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi */ 59610212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi int mFocusDuckBehavior = AudioPolicy.FOCUS_POLICY_DUCKING_DEFAULT; 59620212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi 59630212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi AudioPolicyProxy(AudioPolicyConfig config, IAudioPolicyCallback token, 59640212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi boolean hasFocusListener) { 59658fdb0d4defb6ee2ca8057d3442ead36b408b6c17Jean-Michel Trivi super(config); 59661b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi setRegistration(new String(config.hashCode() + ":ap:" + mAudioPolicyCounter++)); 59670212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi mPolicyToken = token; 59680212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi mHasFocusListener = hasFocusListener; 59690212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi if (mHasFocusListener) { 59700212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi mMediaFocusControl.addFocusFollower(mPolicyToken); 59710212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi } 59727f5eb9fe3c10d8d83ff0e2b0fc60a05c2e6d5b02Eric Laurent connectMixes(); 5973a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi } 5974a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi 5975a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi public void binderDied() { 5976a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi synchronized (mAudioPolicies) { 59770212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi Log.i(TAG, "audio policy " + mPolicyToken + " died"); 59780212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi release(); 59790212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi mAudioPolicies.remove(mPolicyToken.asBinder()); 59808fdb0d4defb6ee2ca8057d3442ead36b408b6c17Jean-Michel Trivi } 59818fdb0d4defb6ee2ca8057d3442ead36b408b6c17Jean-Michel Trivi } 59828fdb0d4defb6ee2ca8057d3442ead36b408b6c17Jean-Michel Trivi 59830212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi String getRegistrationId() { 59841b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi return getRegistration(); 59858fdb0d4defb6ee2ca8057d3442ead36b408b6c17Jean-Michel Trivi } 59868fdb0d4defb6ee2ca8057d3442ead36b408b6c17Jean-Michel Trivi 59870212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi void release() { 59880212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi if (mFocusDuckBehavior == AudioPolicy.FOCUS_POLICY_DUCKING_IN_POLICY) { 59890212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi mMediaFocusControl.setDuckingInExtPolicyAvailable(false); 59900212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi } 59910212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi if (mHasFocusListener) { 59920212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi mMediaFocusControl.removeFocusFollower(mPolicyToken); 59930212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi } 59947f5eb9fe3c10d8d83ff0e2b0fc60a05c2e6d5b02Eric Laurent AudioSystem.registerPolicyMixes(mMixes, false); 59958fdb0d4defb6ee2ca8057d3442ead36b408b6c17Jean-Michel Trivi } 59968fdb0d4defb6ee2ca8057d3442ead36b408b6c17Jean-Michel Trivi 59977f5eb9fe3c10d8d83ff0e2b0fc60a05c2e6d5b02Eric Laurent void connectMixes() { 59987f5eb9fe3c10d8d83ff0e2b0fc60a05c2e6d5b02Eric Laurent AudioSystem.registerPolicyMixes(mMixes, true); 5999a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi } 6000a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi }; 6001a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi 6002a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi private HashMap<IBinder, AudioPolicyProxy> mAudioPolicies = 6003a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi new HashMap<IBinder, AudioPolicyProxy>(); 60048fdb0d4defb6ee2ca8057d3442ead36b408b6c17Jean-Michel Trivi private int mAudioPolicyCounter = 0; // always accessed synchronized on mAudioPolicies 60059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 6006